Recyclerview not scrolling inside Nested ScrollView
Asked Answered
V

6

10

I have Recyclerview which is under Coordinatorlayout > NestedScrollview > ViewPager and ViewPager has 3 fragment, one has image gallery which is working with the help of Recyclerview. Whenever i tried to scroll up or down it doesn't scroll at all. I have already set photosRecycler.setNestedScrollingEnabled(false); and as soon as i remove this line i am getting scroll working only down side and when i tried to move back up it move up with parent Nestedscrollview.

My layout manager is also showing StaggeredGrid as Grid i need to get this kind of layout

enter image description here

Here is my parent layout for Nestedscrollview

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:background="?android:attr/colorBackground"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways">

            <androidx.constraintlayout.widget.ConstraintLayout


                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?android:colorBackground">


                <ImageView

                    android:layout_width="match_parent"
                    android:layout_height="500dp"
                    android:src="@color/custom_transparent_colorBlack"
                    android:scaleType="centerCrop"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.0"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    />

                <de.hdodenhof.circleimageview.CircleImageView

                    android:layout_width="128dp"
                    android:layout_height="128dp"
                    app:layout_constraintBottom_toBottomOf="@+id/coverPhoto"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="@+id/coverPhoto"
                    app:layout_constraintVertical_bias="0.44"
                    tools:srcCompat="@tools:sample/avatars" />



            </androidx.constraintlayout.widget.ConstraintLayout>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
    <androidx.core.widget.NestedScrollView
        android:id="@+id/up_NestedScrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"

        >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="5dp"
            android:paddingRight="5dp"
            >
            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabItemes"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:tabGravity="fill"
                app:tabPaddingBottom="0dp"
                app:tabPaddingEnd="0dp"
                app:tabPaddingStart="0dp"
                app:tabPaddingTop="0dp"
                app:tabIndicatorHeight="0dp"
                app:tabMode="fixed"
                app:tabTextColor="@color/black"
                app:tabSelectedTextColor="@color/primary"
                app:tabIndicatorColor="@color/primary_light">

                <com.google.android.material.tabs.TabItem
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="About" />

                <com.google.android.material.tabs.TabItem
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Media" />

                <com.google.android.material.tabs.TabItem
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Con" />
            </com.google.android.material.tabs.TabLayout>

            <androidx.viewpager.widget.ViewPager

                android:layout_below="@id/tabItemes"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </RelativeLayout>
    </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

Image Gallery Fragment

public class UserPhoto_fragment extends Fragment {
    public static final String TAG="### USER PHOTO ####";
    RecyclerView photosRecycler;
    fetchPhoto_Adapter adapter;
    StaggeredGridLayoutManager layoutManager;
    ArrayList<String> ImageList;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view=inflater.inflate(R.layout.userprofile_photos,container,false);
        setRetainInstance(true);
        photosRecycler=view.findViewById(R.id.userPhotos_recycler);
        layoutManager= new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
        layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
        ImageList=new ArrayList<>();
        SpacesItemDecoration itemDecoration = new SpacesItemDecoration(16);
        photosRecycler.addItemDecoration(itemDecoration);
        photosRecycler.setLayoutManager(layoutManager);
        photosRecycler.setHasFixedSize(true);
        photosRecycler.setNestedScrollingEnabled(false);

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: User Photo Fragment "+getView()+ ImageList.size() );
        if (ImageList.size()==0){
            new fetch_photo().execute();
        }
    }

    public class fetchPhoto_Adapter extends RecyclerView.Adapter<fetchPhoto_Adapter.ViewHolder>{

        @NonNull
        @Override
        public fetchPhoto_Adapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            LayoutInflater inflater= (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View v = inflater.inflate(R.layout.userprofile_photogallery,viewGroup,false);
            return new ViewHolder(v);
        }

        @Override
        public void onBindViewHolder(fetchPhoto_Adapter.ViewHolder viewHolder, int i) {
            Glide.with(getActivity()).load(ImageList.get(i)).apply(new RequestOptions().centerCrop()).into(viewHolder.image);
        }

        @Override
        public int getItemCount() {
            if (ImageList!=null && ImageList.size()>0){
                return ImageList.size();
            }else {
                return 0;
            }
        }

        public class ViewHolder extends RecyclerView.ViewHolder {
            ImageView image;
            public ViewHolder(View itemView) {
                super(itemView);
                image = itemView.findViewById(R.id.UserProfile_photoThumb);
            }
        }

    }

}

Layout file for image gallery

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_marginTop="20dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/userPhotos_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:scrollbars="vertical">

    </androidx.recyclerview.widget.RecyclerView>
</RelativeLayout>

I am facing 2 issue with this code

  1. Recyclerview not working in nestedscrollview.
  2. StaggeredGridLayoutManager is showing images like GridLayoutManager

Please help me to resolve these issue.Thanks

Victor answered 21/5, 2020 at 3:57 Comment(5)
Please share a sample project which reproduces the same problems that you are facingBristow
@SahilManchanda i shared almost complete code.It's a same code and i am still trying to fix it.Victor
can we remove the nested scroll view from coordinator layout and put view pager directly ?Afrit
and one thing more, can you make your item 1 and then check if item click listener is working or not. I was facing same problem, i might have a solution then.Afrit
@Afrit i only depends on view pager for scroll events then it kills the purpose of CoordinatorLayoutVictor
V
1

You need NestedScrollableHost to scroll in RecyclerView

Works for me with following layout tree

activity.xml

<androidx.constraintlayout.widget.ConstraintLayout
    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"
    tools:context=".view.MainActivity">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/vp_views"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal" />

</androidx.constraintlayout.widget.ConstraintLayout>

fragment.xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:constraint="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        ...

        <com.anatoli.thebattleofcards.fabric.NestedScrollableHost
            android:id="@+id/rv_items_host"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            constraint:layout_constraintEnd_toEndOf="parent"
            constraint:layout_constraintStart_toStartOf="parent"
            constraint:layout_constraintTop_toTopOf="parent">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_items"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"      <!-- change orientation if needs -->
                android:paddingStart="@dimen/layout_padding_small"
                android:paddingEnd="@dimen/layout_padding_small"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />

        </com.anatoli.thebattleofcards.fabric.NestedScrollableHost>

        ...

    </androidx.constraintlayout.widget.ConstraintLayout>

</ScrollView>
Venerate answered 30/5, 2020 at 6:34 Comment(0)
D
0

I think you should put you tabLayout in the appBar:

<androidx.coordinatorlayout.widget.CoordinatorLayout 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:background="?android:attr/colorBackground"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <android.support.design.widget.CollapsingToolbarLayout
        .
        .
        .
        />

            <ImageView
                .
                .
                .
                />

        </android.support.design.widget.CollapsingToolbarLayout>

        <android.support.design.widget.TabLayout
        .
        .
        .
             />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

and put nestedScrolling in your fragments. Read this post: CollapsingToolbar with ViewPager and fragments

Diogenes answered 23/5, 2020 at 12:12 Comment(3)
It will make tablayout out from the NestedScrollviewVictor
i also tried your suggestion but it doesn't make any different to recyclerviewVictor
please try to make it above layout. ThanksVictor
S
0

Perhaps your nestedScrollView hasn't covered the entire screen. Try adding this in your nestedScrollView

android:fillViewport="true"
Salomone answered 24/5, 2020 at 9:33 Comment(0)
F
0

After setting the adapter try putting this line.

ViewCompat.setNestedScrollingEnabled(recyclerView, false);
Fashion answered 26/5, 2020 at 10:25 Comment(1)
what's the difference between recyclerView.setNestedScrollingEnabled(false); and your solutionVictor
P
0

I have faced the same requirement but have solved it in a different manner,

app:layout_behavior="@string/appbar_scrolling_view_behavior"

Set this attribute to the main content layout in your CoordinatorLayout.

    <string name="appbar_scrolling_view_behavior" translatable="false">com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior</string>

The layout looks like

    <androidx.coordinatorlayout.widget.CoordinatorLayout >

    <com.google.android.material.appbar.AppBarLayout>

        <androidx.appcompat.widget.Toolbar>

            <androidx.constraintlayout.widget.ConstraintLayout>

                <ImageView />
                //Header content

            </androidx.constraintlayout.widget.ConstraintLayout>

        </androidx.appcompat.widget.Toolbar>

        <com.google.android.material.tabs.TabLayout />

    </com.google.android.material.appbar.AppBarLayout>

    <LinearLayout

        app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/light_gray">

            </androidx.viewpager.widget.ViewPager>

    </LinearLayout>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

And the main fragments parent view must be nested scroll view with app:layout_behavior

Note: My fragment contains linear layout, so I just used wrap_content if you are using recycler view you should flatten it out inside the fragment

Ptero answered 30/5, 2020 at 6:20 Comment(1)
if i put main content into NestedScrollView then it killed the purpose of CoordinatorLayouVictor
M
0
  1. Since it's viewPager that's directly inside your CoordinatorLayout and not your recyclerView, viewPager shoud have scrolling_layout_behaviour and not your recyclerview

    <androidx.viewpager.widget.ViewPager
       android:layout_below="@id/tabItemes"
       android:layout_width="match_parent"
       android:layout_height="match_parent" 
       app:layout_behavior="@string/appbar_scrolling_view_behavior" />
    
  2. Set up your StaggeredGridLayoutManager like this

    StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(3, LinearLayoutManager.VERTICAL);
    recyclerView.setLayoutManager(staggeredGridLayoutManager); // set LayoutManager to RecyclerView
    

In order for StaggeredGridLayout to work, you must not set your imageView scaletype to cropCenter and height of your cardView containing the imageView element should be set to wrap content and not fixed.

<android.support.v7.widget.cardview 
   android:layout_height="wrap_content" 
   android:layout_width="match_parent"
   app:cardcornerradius="4dp" 
   app:cardusecompatpadding="true">

  <linearlayout 
    android:background="@color/colorPrimary" 
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical">

      <imageview
       android:adjustviewbounds="true" 
       android:id="@+id/placePic" 
       android:layout_height="match_parent" 
       android:layout_width="match_parent" 
       android:scaletype="fitXY" />

   </linearlayout>
</android.support.v7.widget.cardview>
Metabolite answered 30/5, 2020 at 8:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.