要实现这种效果,使用CoordinatorLayout,AppBarLayout,RecyclerView很容易就能完成。由于当前开发的工程由于一些原因不能使用AndroidDesignSupport包。只能自己解决滑动嵌套问题,实现了这个功能,顺便学习了下NestedScrollingParent,NestedScrollingChild的用法。如果想结合代码看文章源码链接在底部。
简单的说下NestedScrollingParent,NestedScrollingChild就是两个接口,在新的android.support.v4包中,两个接口定义了一些操作,然后通过NestedScrollingChildHelper把两者联系起来。
在子View中要联动滚动之前需要调用startNestedScroll(),这个时候NestedScrollingChildHelper中就会向父View寻找实现了NestedScrollingParent的View,并把他保存起来。当滑动事件传递到子View的时候,子View一般要去询问父View是否要滚动,然后方法返回后子View在决定自身是否要滚动。
子View可以通过传给helper的consumed,offsetInWindow数组得到父View消耗的距离,与自身在屏幕的偏移距离。这样子View根据父View的返回在决定自己是否滚动。大概调用关系如下图。
动画中的View布局关系如下图,先滚动1(也有可能不滚动),在滚动2.
这里是NestedScrollParentLayout的简单实现,调用scrollBy方法滚动
public class NestedScrollParentLayout extends RelativeLayout implements NestedScrollingParent {
private NestedScrollingParentHelper mParentHelper;
private int mTitleHeight;
private View mTitleTabView;
public NestedScrollParentLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public NestedScrollParentLayout(Context context) {
super(context);
init();
}
private void init() {
mParentHelper = new NestedScrollingParentHelper(this);
}
//获取子view
@Override
protected void onFinishInflate() {
mTitleTabView = this.findViewById(R.id.title_input_container);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mTitleHeight = mTitleTabView.getMeasuredHeight();
super.onMeasure(widthMeasureSpec, heightMeasureSpec + mTitleHeight);
}
//接口实现--------------------------------------------------
//在此可以判断参数target是哪一个子view以及滚动的方向,然后决定是否要配合其进行嵌套滚动
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
if (target instanceof NestedListView) {
return true;
}
return false;
}
@Override
public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
mParentHelper.onNestedScrollAccepted(child, target, nestedScrollAxes);
}