RecyclerView左右联动形成导航效果

写作目的,仅仅是为了方便自己记忆,并非讲解,贴出的代码也只有最核心的部分

做出的效果类似下图(下图是github上面,某位开发者做出的app的截图)



public class NavigationFragment extends BaseFragment<NavigationContract.Presenter>
        implements NavigationContract.View {

    @BindView(R.id.recyclerView_left)
    RecyclerView recyclerViewLeft;

    @BindView(R.id.recyclerView_right)
    RecyclerView recyclerViewRight;

    private List<NavigationBean.DataBean> dataBeans;

    private NavigationLeftAdapter leftAdapter;

    private NavigationRightAdapter rightAdapter;

    private LinearLayoutManager leftLinearLayoutManager;

    private LinearLayoutManager rightLinearLayoutManager;

    private boolean isRightMoveBottom = false;

    private boolean isRightMoveCenter = false;

    private boolean isRightMoveUp = false;

    private boolean isLeftMove = false;

    private int rightPosition;

    private int leftPosition;


    @Override
    protected int getContentLayoutId() {
        return R.layout.fragment_navigation;
    }

    @Inject
    public NavigationFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = super.onCreateView(inflater, container, savedInstanceState);
        init();
        //加载数据
        presenter.loadNavigationData();
        return rootView;
    }

    private void init() {
        dataBeans = new ArrayList<>();
        leftAdapter = new NavigationLeftAdapter(dataBeans);
        rightAdapter = new NavigationRightAdapter(dataBeans);
        leftLinearLayoutManager = new LinearLayoutManager(this.getActivity());
        rightLinearLayoutManager = new LinearLayoutManager(this.getActivity());
        recyclerViewLeft.setAdapter(leftAdapter);
        recyclerViewRight.setAdapter(rightAdapter);
        recyclerViewLeft.setLayoutManager(leftLinearLayoutManager);
        recyclerViewRight.setLayoutManager(rightLinearLayoutManager);

        //给左边的recyclerview设置点击事件
        leftAdapter.setOnItemClickListener((view, position)->{
            //将左边点击的小项移动到中间
            moveLeftClickItemToCenter(position);
            //将isRightMoveUp,isRightMoveCenter,isRightMoveBottom设置为false
            setIsRightFalse();
            int rightFirstVisiblePosition = rightLinearLayoutManager.findFirstVisibleItemPosition();
            int rightLastVisiblePosition = rightLinearLayoutManager.findLastVisibleItemPosition();
            if(position < rightFirstVisiblePosition){ //position在firstVisiblePosition的上面直接滚动即可
                isRightMoveUp = true;
                recyclerViewRight.smoothScrollToPosition(position);
            }else if(position >= rightFirstVisiblePosition && position <= rightLastVisiblePosition){ //可视的范围内
                isRightMoveCenter = true;
                //直接用下面这句话会有bug,来回切换2个项目的时候会出现问题
                //int top = recyclerViewRight.getChildAt(position - firstVisiblePosition).getTop();
                int top = rightLinearLayoutManager.findViewByPosition(position).getTop();
                recyclerViewRight.smoothScrollBy(0, top);
            }else{ //position在lastVisiblePosition的下面
                isRightMoveBottom = true;
                //这个并不能立即就滚到到位,必须监听右边的滚动
                recyclerViewRight.smoothScrollToPosition(position);
            }
            rightPosition = position;

        });

        //监听右侧recyclerView的滚动
        recyclerViewRight.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                log("isRightMoveBottom = " + isRightMoveBottom + "....." + "isRightMoveCenter = "
                        + isRightMoveCenter + "......" + "isRightMoveUp = " + isRightMoveUp);
                //跟随左边的滑动改变右边的位置(这部分逻辑是被动滚动,非手指触摸造成的滚动)
                if(isRightMoveBottom){
                    if(isItemVisible(rightLinearLayoutManager, rightPosition)){
                        isRightMoveBottom = false;//停止该部分逻辑的回调
                        int top = rightLinearLayoutManager.findViewByPosition(rightPosition).getTop();
                        recyclerView.smoothScrollBy(0, top);
                        //将isRightMoveUp,isRightMoveCenter,isRightMoveBottom设置为false
                        setIsRightFalse();
                        isRightMoveCenter = true;
                    }
                }else if(isRightMoveCenter){
                    if(isItemVisible(rightLinearLayoutManager, rightPosition)){
                        log("isRightMoveCenter....top = " + rightLinearLayoutManager.findViewByPosition(rightPosition).getTop());
                        if(rightLinearLayoutManager.findViewByPosition(rightPosition).getTop() == 0){
                            isRightMoveCenter = false;
                        }
                    }
                }else if(isRightMoveUp){
                    if(isItemVisible(rightLinearLayoutManager, rightPosition)){
                        log("isRightMoveUp......top = " + rightLinearLayoutManager.findViewByPosition(rightPosition).getTop());
                        log("isRightMoveUp......DensityUtils.dp2px(10) = " + DensityUtils.dp2px(10));
                        if(rightLinearLayoutManager.findViewByPosition(rightPosition).getTop() == DensityUtils.dp2px(10)){
                            isRightMoveUp = false;
                        }
                    }
                }else{
                    //右边滚动改变左边位置(主动的滚动,手指触摸造成的滚动)
                    int firstVisiblePosition = rightLinearLayoutManager.findFirstVisibleItemPosition();
                    ViewGroup viewGroup = (ViewGroup) leftLinearLayoutManager.findViewByPosition(firstVisiblePosition);
                    if(viewGroup == null){
                        isLeftMove = true;
                        //这个并不能使左边立即滚动到位,必须监听左边的滚动
                        recyclerViewLeft.scrollToPosition(firstVisiblePosition);
                        leftPosition = firstVisiblePosition;
                    }else{ //可视
                        moveLeftClickItemToCenter(firstVisiblePosition);
                        TextView textView = (TextView) viewGroup.getChildAt(0);
                        leftAdapter.selectItem(firstVisiblePosition, textView);
                    }
                }

            }
        });

        //监听左侧recyclerview的滚动
        recyclerViewLeft.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if(isLeftMove){
                    int firstVisiblePosition = leftLinearLayoutManager.findFirstVisibleItemPosition();
                    if(isItemVisible(leftLinearLayoutManager, leftPosition)){
                        ViewGroup viewGroup = (ViewGroup) leftLinearLayoutManager.findViewByPosition(leftPosition);
                        moveLeftClickItemToCenter(leftPosition);
                        TextView textView = (TextView) viewGroup.getChildAt(0);
                        leftAdapter.selectItem(firstVisiblePosition, textView);
                        isLeftMove = false;//停止监听
                    }
                }
            }
        });

    }

    private void setIsRightFalse(){
        isRightMoveUp = false;
        isRightMoveCenter = false;
        isRightMoveBottom = false;
    }

    /**
     * 将左边点击的小项移动到中间
     */
    private void moveLeftClickItemToCenter(int position) {
        int leftFirstVisiblePosition = leftLinearLayoutManager.findFirstVisibleItemPosition();
        int leftLastVisiblePosition = leftLinearLayoutManager.findLastVisibleItemPosition();
        int centerPosition = (leftFirstVisiblePosition + leftLastVisiblePosition) / 2;
        int centerTop = leftLinearLayoutManager.findViewByPosition(centerPosition).getTop();
        int currentTop = leftLinearLayoutManager.findViewByPosition(position).getTop();
        recyclerViewLeft.smoothScrollBy(0, currentTop - centerTop);
    }


    /**
     * 指定位置的item是否可见
     * @param layoutManager LinearLayoutManager
     * @param position 位置,adapter中的位置
     */
    private boolean isItemVisible(LinearLayoutManager layoutManager, int position){
        int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
        int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();
        if(position >= firstVisiblePosition && position <= lastVisiblePosition){ //可视
            return true;
        }
        return false;
    }


    @Override
    public void refreshList(List<NavigationBean.DataBean> dataBeans) {
        this.dataBeans.clear();
        this.dataBeans.addAll(dataBeans);
        leftAdapter.notifyDataSetChanged();
        rightAdapter.notifyDataSetChanged();
    }
}

完整的代码,可以去 https://github.com/liangshui999/WanAndroid 上面查看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值