I have 3 views in my layout file with CoordinatorLayout as the root view : AppbarLayout, RecyclerView and a Footer(not visible all the time). Recyclerview implements the default behavior appbar_scrolling_view_behavior, that ideally, brings recyclerview below the appbarlayout. But the recyclerview and footer overlap. To Prevent that, I had to write a custom behavior so that when footer is visible, Recyclerview should make space for the footer. But now, the default behavior of appbar_scrolling_view_behavior is gone and now appbarlayout and recyclerview overlap.Here is the Image of the layout
Link to the custom behavior i implemented:
https://github.com/Mandeep221/CustomBehaviorForRecyclerview/blob/master/CustomBehavior.java
My Question: How can i implement 2 things(simultaneously in one behavior):
get the recyclerview below the appbarlayout inside the co-ordinatorlayout
get the recycelerview to make space for the footer if the footer is visible.
If you can suggest some workaround, that would also be great! Thanks alot!
<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/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/list_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:scrollbars="vertical"
app:layout_behavior="prokure.it.prokure.Search.NewSearch.CustomBehavior" />
<prokure.it.prokure.FooterBarLayout
android:id="#+id/footerBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
//footer child views
</LinearLayout>
</prokure.it.prokure.FooterBarLayout>
</android.support.design.widget.CoordinatorLayout>
Don't keep the android.support.design.widget.CoordinatorLayout as root layout.
Add a RelativeLayout as a root layout. Then add android.support.design.widget.CoordinatorLayout with property layout_alignParentTop and layout_above="#+id/footerBar" and set prokure.it.prokure.FooterBarLayout as align parent bottom as second child of RelativeLayout.
<RelativeLayout
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.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="#+id/footerBar">
<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/app_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:scrollbars="vertical"
/>
</android.support.design.widget.CoordinatorLayout>
<prokure.it.prokure.FooterBarLayout
android:id="#+id/footerBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
//footer child views
</LinearLayout>
</prokure.it.prokure.FooterBarLayout>
</RelativeLayout>
Another simpler way is to add following lines to your prokure.it.prokure.FooterBarLayout
app:layout_anchor="#id/list_recycler_view"
app:layout_anchorGravity="bottom"
and keep prokure.it.prokure.FooterBarLayout inside coordinator layout.
Make sure to add an empty cell at the end of the recycler view so that prokure.it.prokure.FooterBarLayout does not overlap with last cell of RecyclerView.
Related
I have an activity with a coordinator layout as a parent, the activity is composed of a toolbar and viewpager tablayout. The activity has a fragment with a relative layout parent and nested in this relative layout is a recyclerview and a bottom sheet.
Now the problem is that the bottom sheet does not work well with the relative layout but the toolbar scrolls well on recyclerview scroll event.
However, when I use a coordinator layout as the parent of the fragment layout, the bottom sheet works fine but the tab fails to scroll hence the bottom sheet is not fully shown.
My question: How can I use bootomsheet in a relativelayout parent. Or can I still use Coordinator layout in the fragment and the parent tab still scrolls well?
Here is the code for the fragment with the relative layout as root layout:
<RelativeLayout
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<include layout="#layout/report_question_bottom_sheet"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
Here is the code for the fragment with coordinator layout as root layout
<androidx.coordinatorlayout.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"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<include layout="#layout/report_question_bottom_sheet"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Here is the code for my activity with tab layout
<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:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".Bookmarks">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_weight="1"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable"
app:tabGravity="fill"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I expect the toolbar to scroll out of view when scrolling down the recylerview items and scroll into view when scrolling up the recyclerview items.
You can check the doc:
BottomSheetBehavior is applied to a child of CoordinatorLayout to make that child a persistent bottom sheet.
BottomSheetBehavior works in tandem with CoordinatorLayout to let you display content on a Bottom sheet.
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);
When the activity is opened, it shows the top of the RecyclerView layout instead of the top of the activity layout.
Activity layout .xml file:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="20dp"
android:paddingTop="20dp">
...
<RelativeLayout/>
<View />
<LinearLayout/>
...
<android.support.v7.widget.RecyclerView
android:id="#+id/venue_place_info_gallery_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
</LinearLayout>
</ScrollView>
Activity onCreate:
RecyclerView galleryRecyclerView = (RecyclerView) findViewById(R.id.venue_place_info_gallery_recycler_view);
galleryRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(gridLayoutColumns, StaggeredGridLayoutManager.VERTICAL));
VenueGalleryAdapter venueGalleryAdapter = new VenueGalleryAdapter(VenuePlaceInfoActivity.this, images);
galleryRecyclerView.setAdapter(venueGalleryAdapter);
The adapter is very simple. It receives the images as an argument in the constructor and the data cannot be changed later on.
I've tried to apply all kinds of settings to the RecyclerView layout, but it works the same with or without them. For example:
galleryRecyclerView.setNestedScrollingEnabled(false);
galleryRecyclerView.setHasFixedSize(true);
galleryRecyclerView.setLayoutFrozen(true);
galleryRecyclerView.setPreserveFocusAfterLayout(false);
UPDATE:
I have found more info on the subject in the answer of another question. It's all because of the ScrollView and RecyclerView not being capable to live together even if you set setNestedScrollingEnabled to true. But it still doesn't give me the resolution of my problem. I need to have some stuff above the gallery RecyclerView and I want to scroll down through all the images (not putting them in a container).
If you want your layout to look good, I would use a CoordinatorLayout with an AppBarLayout as the first element inside it, and the RecyclerView as the second. Inside the AppBarLayout, you should put whatever it is that you would like to have above the RecyclerView. Something similar to this:
<LinearLayout
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:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:titleEnabled="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="20dp"
app:layout_collapseMode="parallax">
<!-- stuff you want above your recyclerview -->
</LinearLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
Someone does something similar here, just instead of using a toolbar in the appbarlayout, you may use whatever view layouts you'd like. AppBarLayout is an extended Vertical LinearLayout: http://www.basagee.tk/handling-scrolls-with-coordinatorlayout/
just add the following tag on your activity/fragment root layout and you are good to go.
android:descendantFocusability="blocksDescendants"
I´m attempting to use the new Android Design Library´s CoordinatorLayout inside of another layout. The CoordinatorLayout contains a RecyclerView. What I´m attempting to do is to place a simple LinearLayout below the CoordinatorLayout. This layout should be placed below the CoordinatorLayout. This is XML I´m using:
<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:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="fill_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="150dp"
android:orientation="horizontal">
<EditText
android:layout_width="fill_parent"
android:layout_height="match_parent" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="#drawable/ic_send_white_36dp" />
</LinearLayout>
</LinearLayout>
As you can see, I´m attempting to wrap the CoordinatorLayout inside another LinearLayout. However, on-screen the second part of the layout doesn´t even render.
That is because the CoordinatorLayout has layout_height="match_parent". That means it takes the whole size of the screen and your LinearLayout is rendered but it is below the CoordinatorLayout and off-screen.
An easy way to fix this would be setting the weight of the CoordinatorLayout to fill the parent layout but leave space necesseary to display the footer LinearLayout. This would be
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
But this is not ideal way so I would suggest leaving the CoordinatorLayout as the root element and place your LinearLayout just bellow the RecyclerView where it belongs. Since your footer LinearLayout has fixed height this can be done easily
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:paddingBottom="150dp" />
<LinearLayout
android:layout_height="150dp"
android:layout_gravity="bottom">
<EditText />
<ImageButton />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
I recently started messing around with the new components of AppCompat 21 and implementing Material Design. Currently, I have an ActionBarActivity with a Toolbar and am trying to have it host a fragment containing a RecyclerView of TextView items (just to test out Recycler). I have items being displayed, but the text in each view is cut off and the entire Recycler is covering the Toolbar like so:
As you can see, there are three TextViews. Their text is cut off halfway and it's overlaying the Toolbar (no Title I know). The TextView item layouts are contained within a RecyclerView layout, which is the layout of the Fragment. The parent Activity has a FrameLayout -> Toolbar, FrameLayout. I am inserting the Fragment into the Activity's sub FrameLayout. Here's the XML:
Each view in the Recycler:
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="48dp"
android:fontFamily="sans-serif"
android:paddingTop="16dp"
android:paddingBottom="20dp"
android:textSize="16sp"/>
The Recycler layout, which is the layout of the Fragment:
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/recycler_tasks"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="stuff.MainActivity$TaskFragment">
</android.support.v7.widget.RecyclerView>
And the parent Activity's layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"/>
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>
I know it must be something simple but I've been stumped on it for a while, trying various things to no avail.
Please do not forget to add app:layout_behavior="#string/appbar_scrolling_view_behavior" to your content layout
<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:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Use RelativeLayout instead of FrameLayout as top parent. Then just add dependencies like layout_above for the Toolbar or layout_below for the fragment container.