javaandroidandroid-viewpager2fragmentpageradapterfragmentstateadapter

RecyclerView onClick event is not working with SwipeRefreshLayout?


Before using FragmentStateAdapter. I was using FragmentPagerAdapter then everything was fine but when I migrated from FragmentPagerAdapter to FragmentStateAdapter to reduce memory usage. The issue that I'm facing is that when RecyclerView is at the top position then clicking on any item in the list is not working. If I scroll the RecyclerView a bit down then onClick works fine. This problem was not happening with SwipeRefreshLayout. When I remove SwipeRefreshLayout from parent of RecyclerView. It working fine. How can I use it with SwipeRefreshLayout?

I'm using children Fragments inside a parent Fragment like this enter image description here

This is the code of Parent Fragment.

public class DailyFragment extends Fragment {
    private FragmentDailyBinding binding;
    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {
        binding = FragmentDailyBinding.inflate(inflater, container, false);
        MyChildFragmentAdapter childFragmentAdapter = new MyChildFragmentAdapter(this.getChildFragmentManager(), this.getLifecycle()); // I'm showing these fragment in Parent fragment. So that I'm using getChildFragmentManager() 
        childFragmentAdapter.addFragment(new FirstFragment(),"first");
        childFragmentAdapter.addFragment(new SecondFragment(),"second");
        childFragmentAdapter.addFragment(new ThirdFragment(),"third");
        childFragmentAdapter.addFragment(new FourthFragment(),"fourth");
        childFragmentAdapter.addFragment(new FifthFragment(),"fifth");
        binding.dailyViewPager.setAdapter(childFragmentAdapter);
        new TabLayoutMediator(binding.dailyTabLayout, binding.dailyViewPager, (tab, position) -> tab.setText(childFragmentAdapter.fragmentsArrayListTitle.get(position))).attach();
        binding.dailyViewPager.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
        return binding.getRoot();
    }


    // FragmentStateAdapter
    public static class MyChildFragmentAdapter extends FragmentStateAdapter {
        private final ArrayList<Fragment> fragmentsArrayList = new ArrayList<>();
        private final ArrayList<String> fragmentsArrayListTitle = new ArrayList<>();

        public MyChildFragmentAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
            super(fragmentManager, lifecycle);
        }



        public void addFragment(Fragment fragment, String title) {
            fragmentsArrayList.add(fragment);
            fragmentsArrayListTitle.add(title);
        }

        @NonNull
        @Override
        public Fragment createFragment(int position) {
            return fragmentsArrayList.get(position);
        }

        @Override
        public int getItemCount() {
            return fragmentsArrayList.size();
        }

    }
}

and This this XML of FirstFragment()

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".ChieldFragment.dailyChield.MahadevFragment">
    
<androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/mahadevSwipe"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/mahadevRecyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

My question is similar to this question

ViewPager2 conflicting with SwipeRefreshLayout

I checked these answers but not solved my problem.


Solution

  • I had same problem not so long ago. I fixed mine by adding NestedScrollView as SwipeRefreshLayout child, and then simply put your recycler layout as NestedScrollView's child. See example below :

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            android:id="@+id/mahadevSwipe"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            // I didn't put mandatory constraints, but you'll have to
            <androidx.core.widget.NestedScrollView
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
                <androidx.recyclerview.widget.RecyclerView
                    android:id="@+id/mahadevRecyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.5"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent" />
    
            </androidx.core.widget.NestedScrollView>
    
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    

    Alternatively, you could also keep your code like it is, and add custom scrolling behavior with scroll listener. Tell me if my first guess don't work, i'll give you example of custom scroll handling.