I have an Activity that contains a ViewPager:
activity.xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"/>
</FrameLayout>
The fragments this pager contains – which are all generated from the same layout – have a CoordinatorLayout and CollapsingToolbarLayout to provide a collapsing image-back titlebar:
fragment.xml:
<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:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.v4.widget.NestedScrollView
android:id="#+id/scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!-- Content here -->
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="256dp"
android:elevation="8dp"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleMarginStart="72dp"
android:fitsSystemWindows="true">
<ImageView
android:id="#+id/photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax"
android:background="#color/photo_placeholder"
android:fitsSystemWindows="true"/>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_collapseMode="pin"
android:layout_gravity="bottom">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Without the fitsSystemWindows flags in the activity layout, the image in the fragment properly displays behind the system status bar, while the text sometimes collapses behind the status bar when scrolled up. If I add the flags in – as shown above – the text issue is resolved, but the image now cuts off at the status bar. Keeping the collapsing toolbar code in the fragment, is there a way to fit the fragment's content to the system window?
Without fitsSystemWindows in the activity (preferred behaviour):
With fitsSystemWindows in the activity:
You haven't declared, that you want NestedScrollView also to fitSystemWindows. So, literally, you are prohibiting WindowInsets to be passed to children off NestedScrollView, thus ViewPager is not even aware about WindowInsets.
Apply android:fitSystemWindows="true" to NestedScrollView also.
Related
I'm trying to work with different AppBarLayouts in one Activity.
When a Fragment is loaded, it can call a "ToolbarManager", that handles the replacing of the currently active Toolbar (namely an AppBarLayout).
For some of these Toolbars (using CollapsingToolbarLayout) I want them to draw behind the StatusBar.
This works fine when setting the "fitsSystemWindow" to true in the XML.
But when using just a Toolbar with layout_scrollFlags="scroll", the Toolbar Title is displayed even behind the StatusBar.
To avoid this, I want to disable the "fitsSystemWindow" when loading such a Toolbar by using setFitsSystemWindow(false).
Disabling works fine, but when re-enabling by setFitsSystemWindow(true) for using with CollapsingToolbarLayout, the StatusBar is colored and the Toolbar is placed below the StatusBar with a padding in size of the StatusBar on top.
Image: Drawn below StatusBar instead of behind
When I don't use setFitsSystemWindow(true) and just set it to true in the XML layout, the display of CollapsingToolbarLayout is fine.
Is this a bug in setFitSystemWindow or is this method just different from the XML attribute?
Here are the layouts I use:
Activity:
<android.support.v4.widget.DrawerLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_layout"
android:fitsSystemWindows="true"
tools:context=".activities.MainActivity"
style="#style/AppTheme">
<android.support.design.widget.CoordinatorLayout
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:id="#+id/coordinator_layout">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:layout_height="wrap_content">
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/fragment_container"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</FrameLayout>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateDuration="1000"
android:layout_marginBottom="-7dp"
android:id="#+id/loadingBar"
style="#style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_gravity="center_horizontal|bottom"
android:gravity="bottom"/>
</android.support.design.widget.CoordinatorLayout>
<include layout="#layout/include_navigationview" />
The AppBarLayout is replaced every time a new Fragment is loaded.
The following layout is the Toolbar which should not draw behind the StatusBar, but the Toolbar should scroll (leaving only the TabLayout visible)
<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:id="#+id/toolbar_discover"
android:fitsSystemWindows="true"
android:paddingBottom="0dp">
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/toolbar"
android:layout_height="?attr/actionBarSize"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="#style/AppTheme.Toolbar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|snap">
</android.support.v7.widget.Toolbar>
<android.support.design.widget.TabLayout
android:id="#+id/tablayout_discover"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:tabMode="fixed"
app:tabGravity="fill" />
</android.support.design.widget.AppBarLayout>
This used to work when I set fitsSystemWindows=false on the CoordinatorLayout in the MainActivity Layout. When doing so, the following CollapsingToolbar cannot draw behind the StatusBar.
<android.support.design.widget.AppBarLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:id="#+id/toolbar_account"
android:fitsSystemWindows="true"
android:paddingBottom="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:id="#+id/collapsingToolbarLayout">
<ImageView
android:layout_width="match_parent"
android:layout_height="250dp"
android:scaleType="centerCrop"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"
android:id="#+id/banner_image"
android:src="#mipmap/img_header"/>
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/toolbar"
android:fitsSystemWindows="false"
android:layout_height="?attr/actionBarSize"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:theme="#style/AppTheme.Toolbar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
If i have such a configuration as shown below, like a custom View inside a CollapsingToolbarLayout with height more than a screen height, i cannot collapse it.
What for i need to do it? I need to have a content which will scroll up with a recyclerview below it. Without parallax or other effect, just scroll.
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/refresher"
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:background="#color/accent_material_light"
android:isScrollContainer="false">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:fitsSystemWindows="true"
app:layout_collapseMode="pin"/>
<View android:layout_width="match_parent"
android:layout_height="1500dp"
android:background="#color/green_A100"
app:layout_scrollFlags="scroll"
/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/cardview_light_background"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
</android.support.v4.widget.SwipeRefreshLayout>
Per the Support Library 23.1 release blog post:
You’ll also find that AppBarLayout now allows users to start scrolling from within the AppBarLayout rather than only from within your scrollable view
If you'd like to start scrolling from within your AppBarLayout/CollapsingToolbarLayout, you'll want to update to at least version 23.1.0 of the Design Library.
I have set up a DrawerLayout and a CoordinatorLayout in order to use a modern layout with a NavigationView and collapsing toolbar.
It works just fine until the device is rotated. Then the main_content is moved to a new permanent location. If I remove the appbar_scrolling_view_behavior from the main_content FrameLayout rotation works, but the content is no longer aware of the Toolbar.
Any advice?
activity_main.xml
<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="#00ff00">
<!-- ACTIONBAR START -->
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="#ff0000">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
<!-- ACTIONBAR END -->
<!-- MAIN CONTENT START -->
<FrameLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:background="#0000ff"/>
<!-- MAIN CONTENT END -->
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView ...>
<!-- NavigationView code omitted ... -->
</android.support.v4.widget.DrawerLayout>
fragment_main.xml (loaded into main_content)
<FrameLayout 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=".fragments.MainFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!"/>
</FrameLayout>
A few points that should collectively resolve your problem:
The height of the AppBarLayout determins the expanded size of the collapsing toolbar, whilst the Toolbar determins the collapsed size. As such, you should set the AppBarLayout height to something more than the Toolbar (i.e. 280dp) to see the collapsing behaviour.
Immediately inside the AppBarLayout should be a CollapsingToolbarLayout, which contains the Toolbar and, optionally, other views too (normally an ImageView with a parallax collapse mode)
For the toolbar to collapse and expand correctly, it relies on a ViewGroup that supports nested scrolling (RecyclerView or NestedScrollView. As such, in your example you should try either changing main_content from a FrameLayout to a NestedScrollView, or conversely change the FrameLayout that forms the root layout of Fragment into a NestedScrollView.
Here is an example:
<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_height="match_parent"
android:layout_width="match_parent"
android:id="#+id/coordinator_layout">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="240dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar" >
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/collapsing_toolbar_layout"
app:contentScrim="#color/primary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/header_image"
android:src="#drawable/header_image"
android:scaleType="centerCrop"
android:contentDescription="#string/header_image"
app:layout_collapseMode="parallax"/>
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="#+id/toolbar"
app:layout_collapseMode="pin"
app:theme="#style/ThemeOverlay.AppCompat.Dark"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
As the title suggests, I have an activity that has a FrameLayout that houses my Fragments [I am NOT using a Tabs, just Transactions]. I also have a NavigationDrawer and Toolbar. All of these things work fine.
The issue is that I'm trying to add a CollapsingToolbarLayout to the Activity layout and have RecyclerView in the Fragment scroll and control the collapsing of the CollapsingToolbarLayout.
With the setup shown below, I'm able to use the NavigationDrawer, see the Toolbar and the expanded CollapsingToolbarLayout with NO image inside (odd issue there). I load the Fragment into the FrameLayout which contains a RecyclerView with 10 test views. This scrolls fine below the CollapsingToolbar but it does not collapse.
Activity Layout XML
<android.support.v4.widget.DrawerLayout
android:id="#+id/dl_drawer_layout"
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:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/cl_dashboard"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.AppBarLayout
android:id="#+id/abl_dashboard"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/ctb_dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="#color/the_color"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/iv_dashboard_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="#mipmap/the_image"
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax"/>
<include
android:id="#+id/toolbar"
layout="#layout/overlay_toolbar"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fl_dashboard_fragmentframe"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nv_navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/overlay_drawer_header"
app:menu="#menu/menu_drawer"/>
</android.support.v4.widget.DrawerLayout>
Fragment Layout XML
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_fragment_dashboardhome"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</android.support.v7.widget.RecyclerView>
I don't understand why this isn't working and I've run through a lot of documentation and examples with no luck. Any help or suggestion would be greatly appreciated.
It turned out that the layout I was using for the Toolbar did not have the correct height value.
overlay_toolbar.xml
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
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="wrap_content"
android:background="#color/get_blue"
android:elevation="5dp"
android:minHeight="?attr/actionBarSize"
app:theme="#style/actionbar_getblue">
</android.support.v7.widget.Toolbar>
Adjustment to overlay_toolbar include call in Activity XML
<include
android:id="#+id/toolbar"
layout="#layout/overlay_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
After that single adjustment to the height the CollapsingToolbarLayout began working perfectly.
app:layout_behavior should be applied to RecyclerView or any other View capable of nested scrolling such as NestedScrollView.
See this tutorial from codepath: https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
You can use app:layout_behavior="#string/appbar_scrolling_view_behavior" on RecyclerView you have in fragment.
The behavior of CollapsibleToolbarLayout with regards to the RecyclerView seems broken. When setting a value for
app:layout_scrollFlags
If you do not use "scroll|enterAlways", the Collabsible layout will never expand. It will always contract, but when you pull down, it does not expand anymore, so it just gets locked to the top.
If you use "scroll|enterAlways", it works as expected, meaning it instantly expands the header to its full height whenever you scroll down.
Without knowing anymore, it seems as if the Collapsible layout cannot properly determine when the RecyclerView is at the top of the list, as that is the criteria for when it should expand to full height in the other cases.
Here is the layout that I am testing with. The java code isn't really important, it is just populating the recyclerview with dummy data and using a LinearLayoutManager.
<?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/recycler_view"
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="200dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:toolbarId="#id/toolbar_id"
app:contentScrim="#color/white"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_id"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
Try with scroll|enterAlways|enterAlwaysCollapsed. This way the toolbar should always enter in the collapsed mode, and then expand when you reach the top of the sibling view.
If you want to show a list with RecyclerView under the AppBarLayout you should place the RecyclerView XML under
<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/appbar"
android:layout_width="match_parent"
android:layout_height="200dp"
android:theme="#style/ThemeOverlay.AppCompat.ActionBar"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:toolbarId="#id/toolbar_id"
app:contentScrim="#color/white"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_id"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>