Android中ScrollView和RecylCerView的交互

Android中ScrollView和RecylCerView的交互,android,Android,我正在尝试创建一个垂直和水平滚动日历,当你垂直滚动时,它是按一天中的小时滚动,当你水平滚动时,它是按一个月中的天滚动。此链接包含我所需的几乎正常工作的gif: 如果您注意到在gif的后半部分附近,在垂直滚动之后,正文和日标题的水平滚动已同步,但一旦您将列表移回开始或结束,它们将再次同步 基本上,我这里有两个水平滚动的回收器视图,它们彼此滚动,如下所述: 实际执行情况: public class CalendarFragment extends BaseFragment { @BindVie

我正在尝试创建一个垂直和水平滚动日历,当你垂直滚动时,它是按一天中的小时滚动,当你水平滚动时,它是按一个月中的天滚动。此链接包含我所需的几乎正常工作的gif:

如果您注意到在gif的后半部分附近,在垂直滚动之后,正文和日标题的水平滚动已同步,但一旦您将列表移回开始或结束,它们将再次同步

基本上,我这里有两个水平滚动的回收器视图,它们彼此滚动,如下所述:

实际执行情况:

public class CalendarFragment extends BaseFragment {

@BindView(R.id.dayHeaderView)
RecyclerView dayHeaderView;

@BindView(R.id.dayBodyView)
RecyclerView dayBodyView;

private static final String TAG = CalendarFragment.class.getSimpleName();

private DayHeaderAdapter dayHeaderAdapter = new DayHeaderAdapter();
private DayBodyAdapter dayBodyAdapter = new DayBodyAdapter();

private final RecyclerView.OnScrollListener dayHeaderOSL = new SelfRemovingOnScrollListener() {
    @Override
    public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
        super.onScrolled(recyclerView, dx, dy);
        dayBodyView.scrollBy(dx, dy);
        Log.e(TAG, "onScrolled: dayHeader x : " + dx + " y : " + dy );
    }
};
private  final RecyclerView.OnScrollListener dayBodyOSL = new SelfRemovingOnScrollListener() {

    @Override
    public void onScrolled(@NonNull final RecyclerView recyclerView, final int dx, final int dy) {
        super.onScrolled(recyclerView, dx, dy);
        dayHeaderView.scrollBy(dx, dy);
        Log.e(TAG, "onScrolled: function x : " + dx + " y : " + dy );
        Log.e(TAG, "onScrolled: dayHeader x : " + dayHeaderView.getX() + " y : " + dayHeaderView.getY() );
        Log.e(TAG, "onScrolled: dayBody x : " + dayBodyView.getX() + " y : " + dayBodyView.getY() );
    }
};

public CalendarFragment() {}

public static CalendarFragment create(boolean showScheduler) {
    return new CalendarFragment();
}

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_calendar, container, false);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    getComponent().inject(this);
    ButterKnife.bind(this, view);

    LinearLayoutManager llm = new LinearLayoutManager(getContext());
    llm.setOrientation(LinearLayoutManager.HORIZONTAL);

    LinearLayoutManager llm2 = new LinearLayoutManager(getContext());
    llm2.setOrientation(LinearLayoutManager.HORIZONTAL);

    dayHeaderView.setLayoutManager(llm2);
    dayHeaderView.setAdapter(dayHeaderAdapter);
    dayHeaderAdapter.displayHeader();

    dayHeaderView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {

        private int mLastX;

        @Override
        public boolean onInterceptTouchEvent(@NonNull final RecyclerView rv, @NonNull final
        MotionEvent e) {
            Log.d("debug", "Day Header: 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", "Day Header: onTouchEvent");

            final int action;
            if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && dayBodyView
                    .getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                mLastX = rv.getScrollX();
                dayBodyView.scrollBy(rv.getScrollX(), rv.getScrollY());
                rv.addOnScrollListener(dayHeaderOSL);
            }
            else {
                if (action == MotionEvent.ACTION_UP && rv.getScrollX() == mLastX) {
                    rv.removeOnScrollListener(dayHeaderOSL);
                }
            }
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(final boolean disallowIntercept) {
            Log.d("debug", "Day Header: onRequestDisallowInterceptTouchEvent");
        }
    });

    CalenderLayoutManager clm = new CalenderLayoutManager();
    clm.setTotalColumnCount(10);
    dayBodyView.setLayoutManager(llm);
    dayBodyView.setAdapter(dayBodyAdapter);
    dayBodyAdapter.displayBody();

    dayBodyView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {

        private int mLastX;

        @Override
        public boolean onInterceptTouchEvent(@NonNull final RecyclerView rv, @NonNull final
        MotionEvent e) {
            Log.d("debug", "Day Body: 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", "Day Body: onTouchEvent");

            final int action;
            if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && dayHeaderView
                    .getScrollState
                            () == RecyclerView.SCROLL_STATE_IDLE) {
                mLastX = rv.getScrollX();
                dayHeaderView.scrollBy(rv.getScrollX(), rv.getScrollY());
                rv.addOnScrollListener(dayBodyOSL);
            }
            else {
                if (action == MotionEvent.ACTION_UP && rv.getScrollX() == mLastX) {
                    rv.removeOnScrollListener(dayBodyOSL);
                }
            }
        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(final boolean disallowIntercept) {
            Log.d("debug", "Day Body: onRequestDisallowInterceptTouchEvent");
        }
    });

}


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);
        }
    }
}
}
垂直滚动通过列行完成,第二个水平回收器视图的主体包含在滚动视图中。如图所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/silver"
android:gravity="center"
android:orientation="vertical">

<LinearLayout 
    android:id="@+id/fillable_area_01"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:splitMotionEvents="false">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <View
            android:layout_width="30dp"
            android:layout_height="40dp"
            android:background="@color/black"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/dayHeaderView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"
        android:splitMotionEvents="false">

        <LinearLayout
            android:id="@+id/fillable_area_02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:splitMotionEvents="false">

            <edu.calendar.ui.HourView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />


            <android.support.v7.widget.RecyclerView
                android:id="@+id/dayBodyView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />

        </LinearLayout>
    </ScrollView>
</LinearLayout>

有人知道为什么在使用scrollview之后会出现dsync吗?我能做些什么来修复它?失败或除此之外,是否有更好的方法来实现此设置?标题的行为有时是固定的,有时是可滚动的,这对我来说是个难题,任何建议都将不胜感激

非常感谢你抽出时间