基于这个 SO答案,我得到了下面的设计:
![设计](https://istack.dev59.com/L5LKJ.webp)
<?xml version="1.0" encoding="utf-8"?>
<!--Outer container layout-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity">
<!--To display Channels list-->
<LinearLayout
android:layout_width="150dp"
android:layout_height="match_parent"
android:orientation="vertical">
<!--Position (0,0)-->
<TextView
android:id="@+id/tv_change_date"
android:layout_width="match_parent"
android:layout_height="50dp" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rcv_channel_name"
android:scrollbars="none"
android:layout_width="150dp"
android:layout_height="match_parent"/>
</LinearLayout>
<!--To display Time and Programs list-->
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical">
<!--Time horizontal list-->
<android.support.v7.widget.RecyclerView
android:id="@+id/rcv_vertical_header"
android:scrollbars="none"
android:layout_width="match_parent"
android:layout_height="50dp"/>
<!--Vertical list whose each element is horizontal list to show programs-->
<android.support.v7.widget.RecyclerView
android:id="@+id/rcv_vertical"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
现在,我需要同步rcv_vertical和rcv_channel_name的垂直滚动。我按照这个github项目中的实现方式进行了实现。
public class SelfRemovingOnScrollListener extends RecyclerView.OnScrollListener {
@Override
public final void onScrollStateChanged(@NonNull final RecyclerView recyclerView, final int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
recyclerView.removeOnScrollListener(this);
}
}
}
在MainActivity中
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);
programsRecyclerView.scrollBy(dx, dy);
}
};
private final RecyclerView.OnScrollListener programScrollListener = new SelfRemovingOnScrollListener() {
@Override
public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
super.onScrolled(recyclerView, dx, dy);
channelsRecyclerView.scrollBy(dx, dy);
}
};
@Override
protected void onStart() {
super.onStart();
//Sync channel name RCV and Programs RCV scrolling
channelsRecyclerView.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 && programsRecyclerView
.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");
}
});
programsRecyclerView.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 && channelsRecyclerView
.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");
}
});
[![}][3]][3]
在HorizontalScrollView中进行水平滚动之前,它可以正常工作。但是在此之后,左侧的rcv_channel_name RecyclerView比右侧的rcv_vertical RecyclerView滚动得更快。
非常感谢任何有关解决此问题的帮助或建议。