AppBarLayout with recyclerView in nested fragment
Asked Answered
M

3

10

As images are always better than words, I present to you my current layout.

The toolbar/tabs is in an activity.xml with a viewPager, and the recyclerView is inside a fragment within the viewPager. So you can swipe right/left to see other content.

My issue is that I want the AppBarLayout to be binded in its scrolling behaviour to the recyclerView in the first fragment, but not to the other fragments.

In the code below, I did this binding but it doesn't work because the recyclerView doesn't recognize the AppBarLayout in the outer layout. Do you have a workaround for this ?

Code for the activity :

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:fab="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="wrap_content" >

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar_main"
            android:layout_width="match_parent"
            /* pretty stuff */
            app:layout_scrollFlags="scroll|enterAlways">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                /* pretty stuff */ />

        </android.support.v7.widget.Toolbar>

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

    <android.support.v4.view.ViewPager
        android:id="@+id/main_pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.SupportFloatingActionsMenu
           ...>
           /* Code for a fancy fab w/ menu */

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

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

For the fragment containing the recyclerView :

<android.support.design.widget.CoordinatorLayout
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="com.insa.burnd.view.MainActivity.NewsfeedFragment"
    android:id="@+id/fragment_newsfeed">

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipe_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.SwipeRefreshLayout>

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

Thank you very much :) !

Maroney answered 1/7, 2015 at 12:56 Comment(2)
You asked the same question/code here: https://mcmap.net/q/282322/-tablayout-inside-toolbarBachelor
No. It's not the same thing. The question is very different, the code is pretty much the same (and the gif is the same).Maroney
N
5

What's with all the crazy code/layouts?

In the fragments where you don't want the toolbar to scroll, do this in the fragment's onCreateView():

    recyclerView.setNestedScrollingEnabled(false);
Noctilucent answered 29/2, 2016 at 16:29 Comment(0)
P
4

You can do this by implementing ViewPager.OnPageChangeListener and enabling/disabling AppBarLayout.LayoutParams scrolling flags.

Here is a sample code:

        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

        }

        @Override
        public void onPageSelected(int position) {
            if (position == 0) {
                //turn on scrolling
                AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
                toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
                mToolbar.setLayoutParams(toolbarLayoutParams);

                CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                appBarLayoutParams.setBehavior(new AppBarLayout.Behavior());
                appBarLayout.setLayoutParams(appBarLayoutParams);
            } else {
                //turn off scrolling
                AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
                toolbarLayoutParams.setScrollFlags(0);
                mToolbar.setLayoutParams(toolbarLayoutParams);

                CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                appBarLayoutParams.setBehavior(null);
                appBarLayout.setLayoutParams(appBarLayoutParams);
            }
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

But it does not seem like a good UX pattern. It will be confusing for users.

Pentstemon answered 1/7, 2015 at 17:22 Comment(5)
Thank you ! It works :) ! As whether it's a good UX pattern, I'm very concerned about this, but the other fragments can in no way be scrolled, so maybe it's less confusing...Maroney
What glitch? Can you describe it?Lavern
The second fragment fixes itself awkwardly just I finish scrolling to it. Se you see the whole ugly animation when it becomes "unliked" to behavior just as you arrive to the fragment.Maroney
I guess it's because of this appBarLayoutParams.setBehavior(new AppBarLayout.Behavior()); but this is necessary. Without it you will see an empty space below Toolbar when it's hidden on the first page.Lavern
Posted it as an issue in google.code I'll see if they're planning for this use case. Because that's the interesting part; a robust API is an API which would allow devs to handle very diverse use cases, not just the one obvious feature, and for the rest, do it by hand. It seems that DSL is still up there at this point.Maroney
C
2

I think the key for solving your problem is removing the Coordinatorlayout from the recycler view layout.

This is the acitivity_main.xml inflated by the MainActivity with a placeholder layout to include

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:itemIconTint="@color/drawer_item"
        app:itemTextColor="@color/drawer_item"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

This is the content layout with the tabs, appBar and ViewPager

<?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"
    android:background="@color/grey_200"
    tools:context=".activities.MainActivity">


    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:elevation="0dp">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways|snap"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            style="@style/MyCustomTabLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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


    <android.support.v4.view.ViewPager
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginTop="12dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"></android.support.v4.view.ViewPager>


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

And finally, the RecyclerView layout inflated by a fragment.

<?xml version="1.0" encoding="utf-8"?>

<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/your_recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

If you want a good reference code you can check the awesome demo created by Chris Banes from Google of the CoordinatorLayout and other design support library features.

The full source code can be found on github. This was the easiest way for me to understand the logic behind it.

I Hope it helps. (I've finally posted something here! :D)

Contredanse answered 29/2, 2016 at 15:36 Comment(1)
app:layout_behavior="@string/appbar_scrolling_view_behavior" this will make the viewpager translate bottom the height of appBarLayout so if there is any view layout_gravity="bottom" inside the fragment layout that won't be visible at all.Mcquoid

© 2022 - 2024 — McMap. All rights reserved.