最近看到應用寶管理界面裏面那個能縮能放的標題欄很有意思,所以自己嘗試簡單模仿下。
實現原理:
結合代碼:
這個網址做了詳細解釋
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(bigHeaderView == null && smallHeaderView == null){
initData();
}
}
private void initData() {
int bigHeaderViewId= getResources().getIdentifier("big_header_view", "id", getContext().getPackageName());
int smallHeaderViewId = getResources().getIdentifier("small_header_view", "id", getContext().getPackageName());
// System.out.println("bigHeaderViewId = " + bigHeaderViewId + " smallHeaderViewId = " + smallHeaderViewId);
if (bigHeaderViewId != 0 && smallHeaderViewId != 0) {
bigHeaderView = findViewById(bigHeaderViewId);
smallHeaderView = findViewById(smallHeaderViewId);
heightBV = bigHeaderView.getMeasuredHeight();
currentHeightBV = heightBV;
heightSV = smallHeaderView.getMeasuredHeight();
// System.out.println("heightBV = " + heightBV + " heightSV = " + heightSV);
bigHeaderView.setVisibility(VISIBLE);
smallHeaderView.setVisibility(INVISIBLE);
state = BIG_HEADER_VIEW_STATE;
} else {
Log.e("Error Inform", "沒有設置HeaderView Id");
}
}
下面是改變藍色區域大小的代碼:
//根據滑動設置高度
public void setHeaderHeight(float dis) {
int height = (int)(currentHeightBV + dis);
if (height < heightSV) {
height = heightSV;
} else if (height > heightBV) {
height = heightBV;
}
if (bigHeaderView != null && bigHeaderView.getLayoutParams() != null) {
bigHeaderView.getLayoutParams().height = height;
System.out.println("height = " + height + " currentHeight = " + currentHeightBV);
//計算縮放比,有了縮放比,你就可以做很多其他事情,比如控制alpha變化,控制scale變化
//像有些標題欄是根據手勢移動,來改變透明度的.
float scalePercent = (height - heightSV)*1.0f / (heightBV - heightSV);
setTextViewHeight(scalePercent);
bigHeaderView.requestLayout();
} else {
Log.e(TAG, "bigHeaderView = null");
}
if(height <= heightSV){
smallHeaderView.setVisibility(VISIBLE);
bigHeaderView.setVisibility(INVISIBLE);
state = SMALL_HEADER_VIEW_STATE;
} else {
smallHeaderView.setVisibility(INVISIBLE);
bigHeaderView.setVisibility(VISIBLE);
if(height == heightBV)
state = BIG_HEADER_VIEW_STATE;
else
state = MID_HEADER_VIEW_STATE;
}
}
爲了體驗更好,在藍色區域縮放到2/3以內大小的時候,自動縮小直到最小。我的實現方式是通過線程來慢慢改變高度,詳見代碼,註釋很詳細
/**
* 當位置大於heightSV 並且小於 heightBV*2/3的時候,執行平滑縮放
* 感覺自己用線程實現的平滑效果不是很好......
*/
public void smoothSetHeaderHeight() {
currentHeightBV = bigHeaderView.getHeight();
final int timeCount = 1*200; //0.2秒鐘 從heightBV*2/3 縮放到 heightSV
final float dis = -1 * (heightBV*2.0f/3.0f-heightSV)*1.0f/timeCount*10;
// System.out.println("currentHeightBV = " + currentHeightBV);
if(currentHeightBV > (heightBV*2 / 3) || currentHeightBV <= heightSV) {
return;
}
// System.out.println("dis = " + dis);
new Thread() {
@Override
public void run() {
for (int i = 0; i < timeCount/10; i++) {
final float sumDis = i*dis + dis;
post(new Runnable() {
public void run() {
setHeaderHeight(sumDis);
}
});
try {
sleep(10); //爲了體驗好點,慢慢縮放
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
View.OnTouchListener onTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int moveY = (int)event.getRawY(); //取得手指相對屏幕的Y座標
if(event.getAction() == MotionEvent.ACTION_DOWN){
mDownY = event.getRawY(); //按下時候的座標
}
if(event.getAction() == MotionEvent.ACTION_MOVE){
int dis = (int)(moveY - mDownY); //移動距離
// System.out.println("move distance = " + dis);
int state = scrollerHeaderLayout.getState(); //當前滑動狀態
//下滑時候 需要做如下操作
if(dis > 0 && !recycleView.canScrollVertically(-1)
&& (state == ScrollerHeaderLayout.SMALL_HEADER_VIEW_STATE
|| state == ScrollerHeaderLayout.MID_HEADER_VIEW_STATE)){
// System.out.println("stateScrollerDir" + stateScrollerDir);
/**
* 這裏邏輯是:如果你突然換方向移動,那麼需要改變mDownY的座標爲"換方向的那個轉折點"的Y標。
* 並初始化當前 scrollerHeaderLayout的高度。
*/
if(stateScrollerDir < 0) {
mDownY = moveY;
scrollerHeaderLayout.initCurrentHeightBV();
}
//改變移動狀態
stateScrollerDir = 1;
dis = (int)(moveY - mDownY); //重新計算距離 :可能換方向移動了,原來計算的距離不對了.
scrollerHeaderLayout.setHeaderHeight(dis); //設置高度
return true;
}
//上滑 同下滑操作一樣
if(dis < 0 && (state == ScrollerHeaderLayout.BIG_HEADER_VIEW_STATE
|| state == ScrollerHeaderLayout.MID_HEADER_VIEW_STATE)){
if(stateScrollerDir > 0) {
mDownY = moveY;
scrollerHeaderLayout.initCurrentHeightBV();
// System.out.println("mDownY = " + mDownY);
}
stateScrollerDir = -1;
dis = (int)(moveY - mDownY);
// System.out.println("-1 dis = " + dis);
scrollerHeaderLayout.setHeaderHeight(dis);
return true;
}
mDownY = event.getRawY();
}
if(event.getAction() == MotionEvent.ACTION_UP){
scrollerHeaderLayout.initCurrentHeightBV();
scrollerHeaderLayout.smoothSetHeaderHeight();
}
return false;
}
};
總結:這裏通過線程方式實現的自動縮放致最小高度,因爲是勻速的,效果有點不太好...