先上终究作用

安卓实现掘金 APP 首页滑动吸顶效果

使用的组件 TabLayout ViewPager NestScrollView RecyclerView

主要完成

首先咱们要自定义一个我 ScrollView 承继自 NestedScrollView,重写 onMeasure 办法,在这个办法中咱们获取 scrollview 能够翻滚的最大间隔,再重新 onNestedPreScroll 办法,在这里面去判别是否先消费子级的翻滚。下面是主要代码展现

public class MyScrollView extends NestedScrollView {
    private final String TAG = "MyScrollView";
    private int maxScrollHeight;
    public MyScrollView(Context context) {
        super(context);
    }
    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //获取scrollView 最大可翻滚的间隔
        maxScrollHeight = this.getChildAt(0).getMeasuredHeight() - this.getMeasuredHeight();
    }
    @Override
    public void onNestedPreScroll(@NonNull View target, int dx, int dy, @NonNull int[] consumed,
                                  int type) {
        super.onNestedPreScroll(target, dx, dy, consumed, type);
        //假如最大可翻滚间隔大于 0 则表明 scrollview 能够翻滚,则去先消费用户滑动
        if(this.maxScrollHeight > 0){
            //判别用户是否是向上滑动,并且没有超出 scrollview 可滑动的最大间隔
            boolean headerScrollUp = dy > 0 && getScrollY() < this.maxScrollHeight;
            //判别用户是否是向下滑动,并且没有超出可滑动间隔
            boolean headerScrollDown = dy < 0 && getScrollY() > 0;
            //假如 scrollview 能够滑动,则去消费滑动
            if (headerScrollUp || headerScrollDown) {
                scrollBy(0, dy);
                consumed[1] = dy;
            }
            //告诉子列表,父级消费的间隔
            this.dispatchNestedPreScroll(dx, dy, consumed, null, type);
        }
    }
}

接着咱们需要将 tab view 的内容高的设置为整个屏幕高度,这样咱们在往上翻滚的时分,最终就会只剩下 tab 的内容。下面是主要代码展现。

//动态设置外层布局的高度,让整个 tab 页为屏幕高度
LinearLayout linearLayout = this.findViewById(R.id.linearLayout);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, height);
linearLayout.setLayoutParams(layoutParams);

最终附上完好代码地址代码