3

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.

M DEV
  • 763
  • 1
  • 7
  • 20
  • Not sure, but Can you disable the nested scrolling of the ViewPager2 RecyclerView (if you are using VP2); [described here](https://stackoverflow.com/questions/67749500/how-to-enable-dragging-on-viewpager2-inside-bottomsheetdialogfragment/67865776#67865776) – Zain Jun 03 '22 at 16:56
  • @Zain Yes, I'm using ViewPager2. I think this problem occurred with Nested Scrolling of ViewPager2. Because when my images are getting loaded then my device is also hanging. – M DEV Jun 04 '22 at 09:53
  • Great.. Have you tried disabling it? – Zain Jun 04 '22 at 11:51
  • @Zain Sorry, But the problem is not solved yet. My ViewPager2 is Showing correctly but unable to click on the top position of Images. When I scroll the `RecyclerView` a bit down then onClick works fine. – M DEV Jun 04 '22 at 18:26

2 Answers2

4

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.

Jacouille
  • 951
  • 8
  • 14
  • Thank you for your answer. I checked `NestedScrollView` but it consumes `3X memory` and also hangs the device. I think this is not a suitable method to solve this problem. – M DEV Jun 07 '22 at 18:54
  • In certain conditions. Your NestedScrollView helped to solve this. This is good if you add your second method to your question. If some developers have another issue. Then they can try your second method if this one is not works. – M DEV Jun 09 '22 at 12:52
  • @MDev I was aiming at giving solution with minimum changes involved. IMHO, best solution would be getting rid of swipe to refresh layout and implement a custom behavior to recylcerView, and thus making it custom swipeToRefresh without hassle of nesting behavior-conflicting-layouts. – Jacouille Jun 09 '22 at 13:01
  • yeah, it is also good if I use `ProgressBar` to refresh my layout. Anyway `NestedScrollView` solved my problem with certain conditions. Thank you so much for your answer. – M DEV Jun 09 '22 at 13:04
  • oh didn't think of that, clever workaround ! No problem, thanks for the bounty ;) – Jacouille Jun 09 '22 at 13:06
  • 1
    This error was also asked in Android issue Tracker. And solved by changing its parent layout. If anyone Facing this type of error try to change the Parent Layout of `SwipeRefreshLayout` like `FrameLayout` or `LinearLayout`. or try this answer or try this also https://stackoverflow.com/a/61115487/16765223 – M DEV Jun 09 '22 at 13:10
0

Try adding app:layout_behavior="@string/appbar_scrolling_view_behavior" to all views under coordinator layout.

Juanje
  • 1,235
  • 2
  • 11
  • 28
  • @jaunje Thank you for your answer. but this also not solved my answer. `NestedScrollView` work. But it is good if you have any other answer to solve this without `NestedScrollView`. Otherwise, it works with `NestedScrollView`(but something also problem with nested) – M DEV Jun 09 '22 at 12:54