How to sync scrolling first-positions of 2 RecyclerViews?

后端 未结 4 1963
情话喂你
情话喂你 2021-01-01 21:21

Background

I have 2 RecyclerView instances. One is horizontal, and the second is vertical.

They both show the same data and have the same amount of items,

4条回答
  •  旧巷少年郎
    2021-01-01 21:57

    Building on Burak's TopLinearLayoutManager, but correcting the logic of the OnScrollListener we finally get working smoothscrolling and correct snapping (of the horizontal RecyclerView).

    public class MainActivity extends AppCompatActivity {
        View masterView = null;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity);
            final LayoutInflater inflater = LayoutInflater.from(this);
            final RecyclerView topRecyclerView = findViewById(R.id.topReccyclerView);
            RecyclerView.Adapter adapterTop = new RecyclerView.Adapter() {
                @Override
                public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                    return new ViewHolder(inflater.inflate(R.layout.horizontal_cell, parent, false));
                }
    
                @Override
                public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
                    ((TextView) holder.itemView).setText(String.valueOf(position));
                    holder.itemView.setBackgroundColor(position % 2 == 0 ? Integer.valueOf(0xffff0000) : Integer.valueOf(0xff00ff00));
                }
    
                @Override
                public int getItemCount() {
                    return 100;
                }
    
                class ViewHolder extends RecyclerView.ViewHolder {
                    final TextView textView;
    
                    ViewHolder(View itemView) {
                        super(itemView);
                        textView = itemView.findViewById(R.id.textView);
                    }
                }
            };
            topRecyclerView.setAdapter(adapterTop);
    
            final RecyclerView bottomRecyclerView = findViewById(R.id.bottomRecyclerView);
            RecyclerView.Adapter adapterBottom = new RecyclerView.Adapter() {
                int baseHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50f, getResources().getDisplayMetrics());
    
                @Override
                public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                    return new ViewHolder(inflater.inflate(R.layout.vertical_cell, parent, false));
                }
    
                @Override
                public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
                    ((TextView) holder.itemView).setText(String.valueOf(position));
                    holder.itemView.setBackgroundColor((position % 2 == 0) ? Integer.valueOf(0xffff0000) : Integer.valueOf(0xff00ff00));
                    holder.itemView.getLayoutParams().height = baseHeight + (position % 3 == 0 ? 0 : baseHeight / (position % 3));
                }
    
                @Override
                public int getItemCount() {
                    return 100;
                }
    
                class ViewHolder extends RecyclerView.ViewHolder {
                    final TextView textView;
    
                    ViewHolder(View itemView) {
                        super(itemView);
                        textView = itemView.findViewById(R.id.textView);
                    }
                }
            };
            bottomRecyclerView.setAdapter(adapterBottom);
    
            TopLinearLayoutManager topLayoutManager = new TopLinearLayoutManager(this, LinearLayoutManager.HORIZONTAL);
            topRecyclerView.setLayoutManager(topLayoutManager);
            TopLinearLayoutManager bottomLayoutManager = new TopLinearLayoutManager(this, LinearLayoutManager.VERTICAL);
            bottomRecyclerView.setLayoutManager(bottomLayoutManager);
    
            final OnScrollListener topOnScrollListener = new OnScrollListener(topRecyclerView, bottomRecyclerView);
            final OnScrollListener bottomOnScrollListener = new OnScrollListener(bottomRecyclerView, topRecyclerView);
            topRecyclerView.addOnScrollListener(topOnScrollListener);
            bottomRecyclerView.addOnScrollListener(bottomOnScrollListener);
    
            GravitySnapHelper snapHelperTop = new GravitySnapHelper(Gravity.START);
            snapHelperTop.attachToRecyclerView(topRecyclerView);
        }
    
        class OnScrollListener extends RecyclerView.OnScrollListener {
            private RecyclerView thisRecyclerView;
            private RecyclerView otherRecyclerView;
            int lastItemPos = Integer.MIN_VALUE;
    
            OnScrollListener(RecyclerView thisRecyclerView, RecyclerView otherRecyclerView) {
                this.thisRecyclerView = thisRecyclerView;
                this.otherRecyclerView = otherRecyclerView;
            }
    
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
                    masterView = thisRecyclerView;
                } else if (newState == RecyclerView.SCROLL_STATE_IDLE && masterView == thisRecyclerView) {
                    masterView = null;
                    lastItemPos = Integer.MIN_VALUE;
                }
            }
    
            @Override
            public void onScrolled(RecyclerView recyclerview, int dx, int dy) {
                super.onScrolled(recyclerview, dx, dy);
                if ((dx == 0 && dy == 0) || (masterView != thisRecyclerView)) {
                    return;
                }
                int currentItem = ((TopLinearLayoutManager) thisRecyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition();
                if (lastItemPos == currentItem) {
                    return;
                }
                lastItemPos = currentItem;
                otherRecyclerView.getLayoutManager().smoothScrollToPosition(otherRecyclerView, null, currentItem);
            }
        }
    }
    

提交回复
热议问题