I am currently making a project that requires 2 horizontal recyclerviews that scroll at the same time, i have tried some code from another answer her but it just keep looping, anybody have a simple way to sync the scrolls of 2 recyclerviews?
Current code i am trying to use:
private final RecyclerView.OnScrollListener channelScrollListener = new SelfRemovingOnScrollListener() {
    @Override
    public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
        super.onScrolled(recyclerView, dx, dy);
        Log.d("onScrolled Channels -","X = "+dx+" Y = "+dy);
        liveLineUpRecyclerView.scrollBy(dx, 0);
    }
}, programScrollListener = new SelfRemovingOnScrollListener() {
    @Override
    public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
        super.onScrolled(recyclerView, dx, dy);
        Log.d("onScrolled Programs -","X = "+dx+" Y = "+dy);
        liveLineUpRecyclerViewFooter.scrollBy(dx,0);
    }
};
And this part
liveLineUpRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        private int mLastY;
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            Log.d("debug", "LEFT: onInterceptTouchEvent");
            final Boolean ret = rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
            if (!ret) {
                onTouchEvent(rv, e);
            }
            return Boolean.FALSE;
        }
        @Override
        public void onTouchEvent(RecyclerView rv, MotionEvent e) {
            Log.d("debug", "LEFT: onTouchEvent");
            final int action;
            if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && liveLineUpRecyclerView
                    .getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                mLastY = rv.getScrollY();
                Log.d("scroll","channelsRecyclerView Y: "+mLastY);
                rv.addOnScrollListener(channelScrollListener);
            }
            else {
                if (action == MotionEvent.ACTION_UP && rv.getScrollY() == mLastY) {
                    rv.removeOnScrollListener(channelScrollListener);
                }
            }
        }
        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
            Log.d("debug", "LEFT: onRequestDisallowInterceptTouchEvent");
        }
    });
    liveLineUpRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
        private int mLastY;
        @Override
        public boolean onInterceptTouchEvent(@NonNull final RecyclerView rv, @NonNull final
        MotionEvent e) {
            Log.d("debug", "RIGHT: onInterceptTouchEvent");
            final Boolean ret = rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
            if (!ret) {
                onTouchEvent(rv, e);
            }
            return Boolean.FALSE;
        }
        @Override
        public void onTouchEvent(@NonNull final RecyclerView rv, @NonNull final MotionEvent e) {
            Log.d("debug", "RIGHT: onTouchEvent");
            final int action;
            if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && liveLineUpRecyclerViewFooter
                    .getScrollState
                            () == RecyclerView.SCROLL_STATE_IDLE) {
                mLastY = rv.getScrollY();
                rv.addOnScrollListener(programScrollListener);
                Log.d("scroll","programsRecyclerView Y: "+mLastY);
            }
            else {
                if (action == MotionEvent.ACTION_UP && rv.getScrollY() == mLastY) {
                    rv.removeOnScrollListener(programScrollListener);
                }
            }
        }
        @Override
        public void onRequestDisallowInterceptTouchEvent(final boolean disallowIntercept) {
            Log.d("debug", "RIGHT: onRequestDisallowInterceptTouchEvent");
        }
    });