解决ScrollView嵌套RecyclerView滑动冲突问题

突然有个朋友问我ScrollView嵌套RecyclerView滑动冲突怎么解决,刚好记录一下,直接使用NestedScrollView替代ScrollView就能解决了,这挺好用。

什么是NestedScrollView:https://www.jianshu.com/p/f55abc60a879;

业务逻辑:如饿了么点餐界面,lsit上边还有商家推荐啊这些等等,当滑动到一定位置之后list才开始滚动。


Screenrecorder-2019-02-18-17-34-36-823.gif

思路:当滑动NestedScrollView的时候Y坐标到达RecyclerView滑动的位置就让RecyclerView消费滑动值。
主页布局文件:




    

        

            

            

            

        
    

    


自定义NestedScrollView :

package com.hdc.test;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.NestedScrollingParent2;
import android.support.v4.widget.NestedScrollView;
import android.util.AttributeSet;
import android.view.View;

/**
 * 使用NestedScrollView替代ScrollView
 */

public class MyNestedScrolling extends NestedScrollView implements NestedScrollingParent2 {

    private int recommendY;

    public MyNestedScrolling(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    //当子 view (直接或间接)调用startNestedScroll(View, int)时,会回调父控件该方法。
    @Override
    public boolean onStartNestedScroll(@NonNull View child, @NonNull View target, int axes, int type) {
        //获取textViewStart顶部的Y值,这个Y值是RecyclerView开始滚动的位置以及NestedScrolling停止滚动的位置
        recommendY = child.findViewById(R.id.textViewStart).getTop();
        return true;
    }

    @Override
    public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes, int type) {
        super.onNestedScrollAccepted(child, target, axes);
    }

    @Override
    public void onStopNestedScroll(@NonNull View target, int type) {
        super.onStopNestedScroll(target);
    }

    @Override
    public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
    }

    /**
     * 在子View消费滑动事件前,优先响应滑动操作,消费部分或全部滑动距离。
     *
     * @param target   触发嵌套滑动的 view
     * @param dx       表示 view 本次 x 方向的滚动的总距离,单位:像素
     * @param dy       表示 view 本次 y 方向的滚动的总距离,单位:像素
     * @param consumed 输出:表示父布局消费的水平和垂直距离。
     * @param type     触发滑动事件的类型:其值有
     *                 ViewCompat. TYPE_TOUCH
     *                 ViewCompat. TYPE_NON_TOUCH
     */
    @Override
    public void onNestedPreScroll(@NonNull View target, int dx, int dy, @Nullable int[] consumed, int type) {
        //当滑动距离(dy)大于0,并且当前Y轴小于RecyclerView开始滚动的位置就让NestedScrollView滚动,滑动距离消费不完则由RecyclerView消费
        if (dy > 0 && getScrollY() < recommendY) {
            scrollBy(0, dy);
            consumed[1] = dy;
        }
    }
}

Adapter布局文件:




    


Adapter :

package com.hdc.test;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;

/**
 * Adapter
 */

public class MyAdapter extends RecyclerView.Adapter {

    private Context context;
    private List list;

    public MyAdapter(Context context, List list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_left, parent, false);
        return new LeftItemHolder(view);
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        holder.setIsRecyclable(false);
        LeftItemHolder leftItemHolder = (LeftItemHolder) holder;
        leftItemHolder.categoryName.setText(list.get(position));
    }

    @Override
    public int getItemCount() {
        return list.size();
    }

    private class LeftItemHolder extends RecyclerView.ViewHolder {

        private TextView categoryName;

        public LeftItemHolder(View itemView) {
            super(itemView);
            categoryName = (TextView) itemView.findViewById(R.id.categoryName);
        }
    }
}

Activity :

package com.hdc.test;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

/**
 * 这是调用者
 */

public class MainActivity extends Activity {

    private Context context;
    private RecyclerView recyclerView;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;

        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        init();
    }

    private void init() {
        List list = new ArrayList();
        for (int i = 0; i < 30; i++) {
            list.add("List" + i);
        }

        MyAdapter myAdapter = new MyAdapter(context, list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

        recyclerView.setLayoutManager(layoutManager);

        recyclerView.setAdapter(myAdapter);
        recyclerView.setFocusable(false);

    }
}
Screenrecorder-2019-02-25-17-52-47-260.gif

已完成测试!有不对的地方欢迎指出,感恩。

你可能感兴趣的:(解决ScrollView嵌套RecyclerView滑动冲突问题)