前言
最近自己想实现一个类似AppBarLayout滑动的功能,上面一个标题栏,标题栏下面有个搜索框,在下面有个RecyclerView,滑动页面的时候标题栏固定不动搜索框随着RecyclerView上下,上去时需要滑进标题栏下面消失
实现思路
参照了DragLayout 通过Parent的layout 方法 自己动态计算两个View的位置来实现,刚好用官方的ViewDragHelper 这个类省去了很多拖动判断的代码,整个过程很简单,但是还有一些细节没有实现,这个只当巩固知识吧
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if(ev.getAction() != MotionEvent.ACTION_DOWN){
viewDragHelper.cancel();
return false;
}
viewDragHelper.shouldInterceptTouchEvent(ev);
//这里所有的事件都拦截了,不然在RecyclerView自己拦截了后续事件,这里需要判断是否是滚动view的起始位置 或者做个接口让子类自己判断
return true;
}
ViewDragHelper 中主要是根据不同的view限制了滑动的top值
ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
captureView = child;
return child == headView || child == dragContentView;
}
//返回拖动view垂直方向拖动的范围, 返回的是与上下的边距
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
//top 必须限制在刚好能隐藏headerView的位置
int newTop = top;
if(child == headView){
final int minTop = - headView.getMeasuredHeight(); //刚好将topView隐藏
final int maxTop = 0;
if(top <= minTop){
newTop = minTop;
}else if(top >= maxTop){
newTop = maxTop;
}
}else if(child == dragContentView){ //如果是contentView那么滑动的范围刚好在顶部到 headerView的高度
final int minTop = 0;
final int maxTop = headView.getMeasuredHeight();
newTop = Math.min(Math.max(top,minTop), maxTop);
}
return newTop;
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//拖动手势释放后的处理,xvel 和yvel 是速度
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
//在onViewPositionChanged方法中控制拖动后新位置的处理。因为拖动过程中还需对TopView进行响应的处理,所以在方法内记录拖动的top位置
//并在onLayout中回调处理最新位置的显示
contentTop = top;
requestLayout();
}
};
在onLayout中根据拖动的View 设置两个view的位置
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//设置headView一直在ContentView头部
if(captureView == headView || captureView == null){
headView.layout(left,contentTop,right,contentTop+headView.getMeasuredHeight());
dragContentView.layout(left, contentTop + headView.getMeasuredHeight(),right,bottom);
}else {
dragContentView.layout(left, contentTop,right,bottom);
headView.layout(left,contentTop - headView.getHeight(),right,contentTop);
}
}