What im trying to do?
Hello, I am trying to develop the view of a user profile in my Android application, for this I am using a CoordinatorLayout, in it, I am introducing a RecyclerView as a scrolleable element.
My actual problem
The problem is that although my RecyclerView activates the CoordinatorLayout when it is scrolled, if in each ViewHolder within my RecyclerView I add a ViewPager and try to scroll from it my CoordinatorLayout doesn't work.
What have I tried before?
At the beginning my RecyclerView was embedded in a fragment, which I thought to reuse in several views but seeing that it did not work I simplified it by taking my RecyclerView out of the fragment and adding it to my CoordinatorLayout as its direct child.
Some time later after reading various articles on StackOverflow I tried wrapping my RecyclerView with a NestedScrollView but that didn't work either.
Coordinator Layout with nested Recycler View:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ScrollingActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="#dimen/app_bar_height"
android:background="#3F51B5"
android:fitsSystemWindows="true"
android:theme="#style/Theme.CoordinatorQuestion.AppBarOverlay">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:toolbarId="#+id/toolbar">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/Theme.CoordinatorQuestion.PopupOverlay" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#673AB7"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".ScrollingActivity" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Post View Holder inside Recycler View:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/purple_200"
android:orientation="vertical"
android:paddingTop="40dp">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#9C27B0"
/>
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_marginTop="40dp" />
</androidx.appcompat.widget.LinearLayoutCompat>
Media View Holder inside ViewPager2 (If you try to scroll pressing the image, CoordinatorLayout does not move):
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#drawable/ic_launcher_background"
android:src="#drawable/ic_launcher_foreground" />
Some util info
Here is a video in which I visually show my problem: https://github.com/RafaelAmoMoralDev/CoordinatorQuestion/blob/main/coordinatorquestion.mp4?raw=true
And here is the repository in which if you wish you can download a small project in which to see a sample code of my problem: https://github.com/RafaelAmoMoralDev/CoordinatorQuestion
¡Thanks in advance!
Related
I want to make several fragments in the main activity each having a RecyclerView such that I can swipe between them. Also in this activity, I have a collapsing toolbar on top of all these things.
I tried using the RecyclerView Directly inside the ViewPager but unfortunately the Toolbar didn't Collapse (I think it needs a NestedScrollView)
I added NestedScrollView outside the ViewPager which gave me an Exception on adding new items to any of the RecyclerViews java.lang.IndexOutOfBoundsException which I found to be a bug caused by calling runOnUiThread() but if I loaded data using UI thread it would be too slow
I tried using NestedScrollViews inside each fragment (wrapping the RecyclerViews) but it gave the same exception
Is there any way to collapse the toolbar without NestedScrollView?
Have a look with this layout:
<?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"
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/colorPrimary">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:elevation="0dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:id="#+id/lnr_expandView"
android:layout_width="match_parent"
android:layout_height="130dp"
android:minHeight="130dp"
android:orientation="horizontal"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7">
</LinearLayout>
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:collapseIcon="#drawable/ic_back"
app:contentInsetStart="30dp"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/googlesans_medium"
android:padding="#dimen/pad_15"
android:text="#string/app_name"
android:textColor="#color/text_color"
android:textSize="20sp"
android:visibility="gone" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.viewpager.widget.ViewPager
android:id="#id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Your 2nd parent child layout must contains this attribute for collapse effect;
app:layout_behavior="#string/appbar_scrolling_view_behavior"
I'm having a problem with Coordinatorlayout and ViewPager implementation.
In order to reproduce this you have to scroll down vigorously and while it's still happening try to scroll the list of items up - a sort of shaky stutter effect can be visible as if CoordinatorLayout was trying to scroll the view in separate direction than its child (RecyclerView).
You can view my layout here:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/mainContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingToolbarLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<FrameLayout
android:id="#+id/headerContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout
android:id="#+id/tabControl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorHeight="4dp"
app:tabMaxWidth="500dp">
</android.support.design.widget.TabLayout>
<LinearLayout
android:id="#+id/topLayout"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="vertical"
android:visibility="gone" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/tabContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Just to provide some further details:
headerContainer contains ConstraintLayout with some stuff like bunch of textviews, button - pretty usual.
tabContainer contains LinearLayout with list of items (recyclerview)
Add this to the recyclerView in the fragment of your ViewPager..
recyclerView.setNestedScrollingEnabled(false);
This is happening because of the app:layout_behavior="#string/appbar_scrolling_view_behavior" behavior of the viewpager.. this is causing the nestedScrolling.. that is why you feel the shaky effect..
Add this line to your RecyclerView
Recyclerview.setNestedScrollingEnabled(false);
I have such layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_margin="20dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.AppCompatImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:src="#drawable/avatar_placeholder"
/>
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_marginLeft="20dp"
android:id="#+id/list"
android:orientation="horizontal"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
As you can see there are CoordinatorLayout with NestedScrollView inside it. And inside of the NestedScrollView there are horizontal RecyclerView. So this layout behaves as follows:
As one can see, problem is in RecyclerView. When I drag it up, Toolbar doesn't hide. In the same time when I dragging up the ImageView Toolbar hides. How to fix that?
did you enable nested scrolling on your recycler ?
recylcer.nestedScrollingEnabled(true)
I had a pretty similar problem, but my recycler was vertical, you can refer to my answer here : Here
I'm trying to achieve an effect like the videos in the "behavior section" at this URL ( Google Design official site ). It's the same effect of Google Photo, I guess, with a search bar on the top of the RecyclerView that disappear/appear on scrolling up/down
I don't know how to get it, I started with CoordinatorLayout and AppBarLayout, but I can't get the RecyclerView visible behind the AppBarLayout, it always remains white, covering the RecyclerView as show below ( result and code [edit: added image with layout layers] ).
Or it's a custom CoordinatorLayout.Behavior ?
Any help or suggestion would be appreciated, thank you
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.AppBarLayout
android:id="#+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsingToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|enterAlways"
android:background="#android:color/transparent">
<SearchView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#android:color/holo_green_light"
android:layout_marginTop="40dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Sample layout
It is definitely a custom CoordinatorLayout.Behavior.
After some searches and readings ( most important, some inspirations, more inspirations, and the foundamentals ), I got what I wanted with the following layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingEnd="#dimen/activity_horizontal_margin"
android:paddingStart="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/grid_spacing_header"/>
<SearchView
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginEnd="#dimen/activity_horizontal_margin"
android:layout_marginStart="#dimen/activity_horizontal_margin"
android:layout_marginTop="#dimen/searchbar_top"
app:layout_behavior=".SearchBarBehavior"/>
</android.support.design.widget.CoordinatorLayout>
with my own SearchBarBehavior that extends CoordinatorLayout.Behavior
[code still incomplete]
try to set CoordinatorLayout also transparent
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent">
I am having issues with the expected scroll behavior of a collapsing toolbar layout within an app. To ensure I kinda knew what I was doing I created a simple test project and was able to achieve the desired result, but a NestedScrollView was used in that example and the content that required scrolling was just a RelativeLayout containing a CardView with a lot of text. In the real app the scroll content is a RecyclerView, which I assume is the problem. It is as if the RecyclerView is handling the scrolling and the parent CollapsingToolbar is left out of the loop.
Notice that the app:layout_behavior="#string/appbar_scrolling_view_behavior" is not currently in the layout. I have tried adding it to various places without the desired result.
Attached is an image of the app after a small amount of scrolling has been performed with the collapsing toolbar above not reducing it's height.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.ArticleListActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/Theme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/theme_primary"
app:contentScrim="#color/theme_primary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:src="#drawable/empty_detail"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="#string/app_name"
android:src="#drawable/logo" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
According to your code what's missing is that you have to set the scrolling flag "scroll" to the imageview above the Toolbar.
I've done a similar thing and as you can see on the code below, all the views that are meant to react to the RecyclerView Scrolling have the scrolling flag and they are before the views that we don't want to scroll such asthe Toolbar:
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:id="#+id/collapsingToolbar"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
>
<include layout="#layout/movie_details_header_layout" android:id="#+id/headerLayout"
app:layout_scrollFlags="scroll"
/>
<android.support.v7.widget.Toolbar
android:layout_height="56dp"
android:layout_width="match_parent"
android:id="#+id/toolbar"
app:navigationIcon="#drawable/ic_arrow_back"
android:navigationContentDescription="Back"
app:layout_collapseParallaxMultiplier="0.7"
app:layout_collapseMode="pin"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
The project came using version 22.x of the compat libraries, updating to 23 seemed to fix everything.