Android realizes the sliding ceiling effect of the Nuggets APP homepage

The final effect first

1657521886191.gif

Components used TabLayout ViewPager NestScrollView RecyclerView

Main implementation

First of all, we need to customize a ScrollView inherited from NestedScrollView, and override the onMeasure method. In this method, we obtain the maximum distance that the scrollview can scroll, and then restart the onNestedPreScroll method to judge whether to consume the scrolling of the child first. The following is the main code display

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);
        }
    }
}
复制代码

Then we need to set the height of the content of the tab view to the height of the entire screen, so that when we scroll up, only the content of the tab will be left in the end. The following is the main code display.

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

Finally, attach the complete code address code

Guess you like

Origin juejin.im/post/7119007162965164040