ViewPager 中的第二个片段使用滚动事件

Second fragment in ViewPager consumes scroll events

我有一个 SwipeRefreshLayout 在我的 Activity 中托管 ViewPager。 我正在向 ViewPager 添加两个片段。第一个片段有 RecyclerView,第二个片段有 ScrollView.

在第一个片段上,SwipeRefreshLayout 正在消耗滚动事件。我添加了 OnScrollListener,如果视图不在顶部,我将禁用刷新。

我在第二个片段中遇到与 ScrollView 相同的问题,我将 ViewTreeObserver.OnScrollChangedListener() 添加到 ScrollView

但是,当我在第一页时,滚动事件传递到第二页。

我尝试在第一个片段的父视图上设置 android:clickable="true",但没有成功。

任何建议都会有所帮助。

my_activity.xml

<include android:id="@+id/toolbar" layout="@layout/include_toolbar" />

<FrameLayout
    android:id="@id/container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/toolbar">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/login_background"
            android:fillViewport="true"
            android:fitsSystemWindows="true"
            android:layout_below="@id/tab_layout">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <TextView
                    android:id="@+id/last_update"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:paddingLeft="@dimen/normal_padding"
                    android:paddingTop="@dimen/small_padding"
                    android:textColor="@color/gray"
                    android:paddingBottom="@dimen/small_padding"
                    android:textSize="@dimen/caption"
                    android:textStyle="bold" />

                <android.support.v4.view.ViewPager
                    android:id="@+id/pager"
                    android:layout_below="@id/last_update"
                    android:layout_width="match_parent"
                    android:layout_height="fill_parent"/>

            </RelativeLayout>

        </android.support.v4.widget.SwipeRefreshLayout>
    </RelativeLayout>
</FrameLayout>

first_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="16dp"
android:background="@android:color/transparent"
android:clickable="true">

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />
</LinearLayout>

second_fragment.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:background="@android:color/transparent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true">

There are some child views here. 

</ScrollView

第二个片段

    onScrollChangedListener = new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            SwipeRefreshLayout swipeRefreshLayout = (SwipeRefreshLayout) getActivity().findViewById(R.id.swipe_container);

            int scrollY = scrollView.getScrollY();
            if (scrollY == 0) swipeRefreshLayout.setEnabled(true);
            else swipeRefreshLayout.setEnabled(false);

        }
    };

    scrollView.getViewTreeObserver().addOnScrollChangedListener(onScrollChangedListener);

尝试添加单独的 SwipeRefreshLayout 而不是共同声明,例如。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:elevation="16dp"
android:background="@android:color/transparent"
android:clickable="true">
<android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/login_background"
            android:fillViewport="true"
            android:fitsSystemWindows="true"
            android:layout_below="@id/tab_layout">

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical" />

 </android.support.v4.widget.SwipeRefreshLayout>
</LinearLayout>

这是因为第二个 Fragment 是与第一个 Fragment 一起创建的,并且它获得了焦点。我在使用 Depth Page Transformer 时遇到了这个问题。第二个 Fragment 在第一个 Fragment 下渲染,因此消耗了触摸。

尝试使用以下页面转换器:

viewPager.setPageTransformer(false, new CustomViewPager.PageTransformer() {

    @Override
    public void transformPage(View view, float position) {
        // TODO Auto-generated method stub

        int pageWidth = view.getWidth();
        int pageHeight=view.getHeight();
        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);
        } 
        else if (position <= 1) { // [-1,1]

         float scaleFactor = Math.max(min_scale, 1 -Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha((float) (0.2 +
                    (scaleFactor - min_scale) /
                    (1 - min_scale) * (1 - 0.2)));

        }
        else { 
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }       
});

第二个 Fragment 现在呈现在右侧,因此触摸事件被传递到第一个 Fragment。

如果我们 add 片段而不是 replace,下面的 fragment 可以消耗 click/touch 事件,以防上面的 fragment 没有消耗它。为避免这种情况,我们可以设置顶部 fragmentroot view 可点击,如下所示(不在 XML 中):

private var binding: FragmentFragment1Binding? = null

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentFragment1Binding.inflate(inflater, container, false)
        binding?.root?.isClickable = true 
        return binding?.root
    }