預(yù)期效果
類似魅族便簽下拉顯示標(biāo)題的效果,加入了顯示隱藏的動畫。
實(shí)現(xiàn)
1、OnLayout中獲取第一個子view的高度
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mChildLayout = (ViewGroup) getChildAt(0);
mTopChildView = mChildLayout.getChildAt(0);
topChildHeight = mTopChildView.getMeasuredHeight();
screenHeight = getMeasuredHeight();
offsetDistance = topChildHeight - screenHeight;
if (!mInited) {
mInited = true;
if (currentPage == PAGE_BOTTOM) {
scrollTo(0, topChildHeight);
}
}
}
2、dispatchTouchEvent中在ACTION_UP時,通過getscrollY()即當(dāng)前滑動的距離與header View高度的比較,并設(shè)定一個閾值,當(dāng)getscrollY()大于或小于該閾值時,顯示或隱藏header view。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (isInIgnoredView(ev)) {
//往下傳遞
Log.e(TAG, "dispatchTouchEvent>>傳遞事件");
return super.dispatchTouchEvent(ev);
} else {
Log.e(TAG, "dispatchTouchEvent>>不傳遞事件");
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
isTouch = true;
downY = (int) ev.getY();
downTime = System.currentTimeMillis();
if (mScroller != null) {
mScroller.forceFinished(true);
mScroller = null;
}
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
isTouch = false;
upY = (int) ev.getY();
upTime = System.currentTimeMillis();
boolean isUpMove = upY - downY <= 0;//是否上劃
//用戶手指在屏幕上的時間
long duration = upTime - downTime;
//這里要確保點(diǎn)擊事件不失效
//we force stop scroll when touch down
//in some case we need to finish scroll up or down
if (currentPage == PAGE_TOP) {
//下面的判斷已經(jīng)能確定用戶是否往上滑
if (getScrollY() > offsetDistance) {
mScroller = new Scroller(mContext);
if (getScrollY() < (screenHeight * PERCENT + offsetDistance) && duration > TOUCH_DURATION) {
//基本可以無視
isPageChange = false;
scrollToTarget(PAGE_TOP);
} else if (getScrollY() > topChildHeight / 5) {
//切換到下界面 手勢是上劃且滑動的距離大于一定值
isPageChange = true;
scrollToTarget(PAGE_BOTTOM);
} else if (getScrollY() <= topChildHeight / 5) {
isPageChange = false;
scrollToTarget(PAGE_TOP);
} else if (getScrollY() > topChildHeight) {
isPageChange = true;
currentPage = PAGE_BOTTOM;
}
return false;
}
} else {
if (getScrollY() < topChildHeight) {
mScroller = new Scroller(mContext);
if (getScrollY() < topChildHeight / 2) {
//切換到上界面
isPageChange = true;
scrollToTarget(PAGE_TOP);
} else {
isPageChange = false;
scrollToTarget(PAGE_BOTTOM);
}
return false;
}
}
break;
}
}
return super.dispatchTouchEvent(ev);
}
3、header view設(shè)置粘性滑動(有沒有更貼切的名字?) 即scrollview的滑動不跟隨手指的滑動,假如設(shè)置的比值為0.4,那么手指滑動10個像素,實(shí)際scrollview只滑動了4個像素,類似下拉刷新的那種下拉吃力的感覺。實(shí)現(xiàn)方法很簡單,在TouchEvent中,通過scrollBy()方法實(shí)現(xiàn)scrollview的滑動,并返回true,表示scrollview消費(fèi)了該次事件。
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isInIgnoredView(ev)) {
Log.e(TAG, "onTouchEvent>>不消費(fèi)事件");
return false;
} else {
Log.e(TAG, "onTouchEvent>>消費(fèi)事件");
currentY = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY = currentY - lastY;
lastY = currentY;
if (currentPage == PAGE_BOTTOM) {
if (getScrollY() <= topChildHeight) {
//下拉
scrollBy(0, (int) (-moveY * mFraction));
return true;
} else {
return super.onTouchEvent(ev);
}
} else {
return super.onTouchEvent(ev);
}
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
break;
}
return super.onTouchEvent(ev);
}
}
4、動畫。動畫使用了屬性動畫,這里就不多介紹了。
效果圖
gif太大..簡書上傳不了.
偷偷懶,移步github看效果
GitHub
歡迎star...歡迎吐槽...