预期效果
类似魅族便签下拉显示标题的效果,加入了显示隐藏的动画。
实现
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()即当前滑动的距离与header View高度的比较,并设定一个阈值,当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;
//这里要确保点击事件不失效
//we force stop scroll when touch down
//in some case we need to finish scroll up or down
if (currentPage == PAGE_TOP) {
//下面的判断已经能确定用户是否往上滑
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设置粘性滑动(有没有更贴切的名字?) 即scrollview的滑动不跟随手指的滑动,假如设置的比值为0.4,那么手指滑动10个像素,实际scrollview只滑动了4个像素,类似下拉刷新的那种下拉吃力的感觉。实现方法很简单,在TouchEvent中,通过scrollBy()方法实现scrollview的滑动,并返回true,表示scrollview消费了该次事件。
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isInIgnoredView(ev)) {
Log.e(TAG, "onTouchEvent>>不消费事件");
return false;
} else {
Log.e(TAG, "onTouchEvent>>消费事件");
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...欢迎吐槽...