Android tabs in fragment with collapsing toolbar

2020-06-23 14:08发布

问题:

I have a Collapsing Toolbar in my app. I use a NavigationDrawer and switch between the items with different fragments, while replacing a FrameLayout, and leaving the Toolbar across the app.

One of the fragments has a tab layout.
When I show that fragment it is shown underneath the Toolbar, with the Toolbar shadow overlapping it.
I want it to be on the same level with the Toolbar, and to look and act like it is in the same AppBarLayout.
Also, I want to make the tabs transparent when the Toolbar is expanded.

How do I reorganize my layouts so that this will work?

Here is my Xml:

Main Xml:

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:clickable="true"
    android:layoutDirection="rtl"
    android:fitsSystemWindows="true"
    android:id="@+id/drawer_layout">
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/mainCoordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutDirection="rtl"
    android:background="#EEEEEE"
    android:clickable="true">
    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/toolbar_layout">
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            app:collapsedTitleGravity="right"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:collapsedTitleTextAppearance="@style/CollapsedTitleTextAppearance"
            app:expandedTitleTextAppearance="@style/ExpandedTitleTextAppearance"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp">
            <ImageView
                android:id="@+id/headerImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                android:src="@drawable/soldier" />
            <View
                android:layout_width="match_parent"
                android:layout_height="88dp"
                android:background="@drawable/scrim_top"
                app:layout_collapseMode="pin" />
            <View
                android:layout_width="match_parent"
                android:layout_height="88dp"
                android:layout_gravity="bottom"
                android:layout_alignBottom="@+id/headerImage"
                android:background="@drawable/scrim_bottom" />
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:theme="@style/WhiteTitle"
                app:layout_scrollFlags="scroll|enterAlways"
                app:titleTextColor="@color/White"
                android:fitsSystemWindows="true"
                android:layout_gravity="right"
                android:layoutDirection="rtl"
                app:layout_collapseMode="pin" />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/content_frame"
        android:animateLayoutChanges="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:fillViewport="true" />
    </FrameLayout>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/mainFab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_gravity="bottom|end"
        android:layout_marginLeft="16dp"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="5dp"
        android:elevation="8dp"
        app:pressedTranslationZ="12dp"
        app:backgroundTint="?android:colorAccent"
        android:src="@drawable/ic_perm_phone_msg_white_24px" />
    <LinearLayout
        android:id="@+id/miniFabFrame"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="invisible"
        android:layout_alignParentLeft="true"
        android:layout_gravity="bottom|end"
        android:layout_marginLeft="20dp"
        android:layout_marginBottom="80dp"
        android:padding="0dp">
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/messageFab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:elevation="8dp"
            android:layout_marginTop="5dp"
            android:layout_marginRight="0dp"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="5dp"
            app:pressedTranslationZ="12dp"
            app:backgroundTint="?android:colorPrimary"
            app:fabSize="mini"
            android:src="@drawable/ic_textSMS_white_24px" />
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/callFab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_marginTop="5dp"
            android:layout_marginRight="0dp"
            android:layout_marginBottom="5dp"
            android:layout_marginLeft="5dp"
            android:elevation="8dp"
            app:pressedTranslationZ="12dp"
            app:backgroundTint="?android:colorPrimary"
            app:fabSize="mini"
            android:src="@drawable/ic_call_white_24px" />
    </LinearLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:id="@+id/nav_view"
    android:layoutDirection="rtl"
    app:headerLayout="@layout/header"
    app:menu="@menu/nav_menu" />

Fragment with tabs layout:

<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:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:fitsSystemWindows="true"
    android:id="@+id/halachot_layout"
    android:layoutDirection="ltr"
    android:animateLayoutChanges="true">
  <android.support.design.widget.AppBarLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:elevation="0dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <com.refractored.PagerSlidingTabStrip
        android:id="@+id/halachotTabs"
        android:layout_below="@id/halachot_layout"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@android:color/transparent"
        android:fitsSystemWindows="true"
        pstsPaddingMiddle="false"
        app:pstsShouldExpand="true" />
    </android.support.design.widget.AppBarLayout>
    <android.support.v4.view.ViewPager
       android:id="@+id/halachotPager"
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1" />
</LinearLayout>

Any guidance will be appreciated.

Thanks.

回答1:

You should make a strucure like this

<?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:id="@+id/main_content"
    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="256dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <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">

            <android.support.design.widget.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:layout_gravity="bottom"
                app:tabMode="scrollable"
                app:tabContentStart="72dp" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="parallax" />

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

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

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

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="8dp"
        android:src="@drawable/ic_done"
        app:layout_anchor="@id/tabs"
        app:layout_anchorGravity="center|left|start"
        app:fabSize="mini"
        app:layout_behavior="com.support.android.designlibdemo.ScrollAwareFABBehavior"
        app:borderWidth="0dp" />

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

Taken from here

Also see this answer it explained well there.

If you want further explaination then read these blogs

http://blog.grafixartist.com/parallax-scrolling-tabs-design-support-library

http://blog.nkdroidsolutions.com/collapsing-toolbar-with-tabs-android-example

https://lab.getbase.com/nested-scrolling-with-coordinatorlayout-on-android/



回答2:

I had a similar problem. I solved removing the elevation of the ActionBar while showing the fragment with the undesired shadow.

I added this two methods in the Activity:

public void setToolbarElevation(){
        if (Build.VERSION.SDK_INT >= 21){
            if (toolbar!=null) {
                toolbar.setElevation(getResources().getDimensionPixelSize(R.dimen.actionbar_elevation));
            }
        }
    }

public void removeToolbarElevation(){
        if (Build.VERSION.SDK_INT >= 21){
            if (toolbar!=null) {
                toolbar.setElevation(0);
            }
        }
    }

So when you call the fragment with the tabs, you call the removeToolbarElevation() in the activity and the shadow should disappear.

Let me know if it works for you.



回答3:

When I show that fragment it is shown underneath the Toolbar, with the Toolbar shadow overlapping it. I want it to be on the same level with the Toolbar, and to look and act like it is in the same AppBarLayout.

for this give the same elevation to the tab layout as per the material design guidelines described here default elevation is 4 dp. so try giving the tab layout elevation

Also, I want to make the tabs transparent when the Toolbar is expanded.

for this add a class like this

public abstract class AppBarStateChangeListener implements AppBarLayout.OnOffsetChangedListener {

public enum State {
    EXPANDED,
    COLLAPSED,
    IDLE
}

private State mCurrentState = State.IDLE;

@Override
public final void onOffsetChanged(AppBarLayout appBarLayout, int i) {
    if (i == 0) {
        if (mCurrentState != State.EXPANDED) {
            onStateChanged(appBarLayout, State.EXPANDED);
        }
        mCurrentState = State.EXPANDED;
    } else if (Math.abs(i) >= appBarLayout.getTotalScrollRange()) {
        if (mCurrentState != State.COLLAPSED) {
            onStateChanged(appBarLayout, State.COLLAPSED);
        }
        mCurrentState = State.COLLAPSED;
    } else {
        if (mCurrentState != State.IDLE) {
            onStateChanged(appBarLayout, State.IDLE);
        }
        mCurrentState = State.IDLE;
    }
}

public abstract void onStateChanged(AppBarLayout appBarLayout, State state);
 }

then in your activity use it like

appBarLayout.addOnOffsetChangedListener(new AppBarStateChangeListener() {
@Override
public void onStateChanged(AppBarLayout appBarLayout, State state) {
    Log.d("STATE", state.name());

    //if state is expanded then set your tab layout background to transparent
  }
});


回答4:

You have go through this. As I am refering this Blog.

It is combination of what you have require means the combination of DrawerLayout + Fragments + CollapsingToolbarLayout.

activity_main.xml

<?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"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

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

app_bar_main.xml

<?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=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="192dp"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            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:background="?attr/colorPrimary"
                app:layout_collapseMode="pin"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/AppTheme.PopupOverlay" />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

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

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/app_bar_main">

    <FrameLayout
        android:id="@+id/content_main_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>

Output :



回答5:

Thank you everyone for all the input.
What I ended up doing, is this:

Main Xml:

<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:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="right"
android:clickable="true"
android:layoutDirection="rtl"
android:fitsSystemWindows="true"
android:id="@+id/drawer_layout">
<android.support.design.widget.CoordinatorLayout
    android:id="@+id/mainCoordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutDirection="rtl"
    android:background="#EEEEEE"
    android:clickable="true">
    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:id="@+id/toolbar_layout">
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="?attr/colorPrimary"
            app:collapsedTitleGravity="right"
            app:expandedTitleGravity="bottom|right"
            app:expandedTitleMarginBottom="50dp"
            app:collapsedTitleTextAppearance="@style/CollapsedTitleTextAppearance"
            app:expandedTitleTextAppearance="@style/ExpandedTitleTextAppearance"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp">

            <ImageView
                android:id="@+id/headerImage"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"
                android:background="@drawable/soldier" />
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:gravity="top"
                app:titleTextColor="@color/White"
                android:fitsSystemWindows="true"
                android:layout_gravity="right"
                android:layoutDirection="rtl"
                app:layout_collapseMode="pin"
                android:minHeight="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:titleMarginTop="15dp" />
        </android.support.design.widget.CollapsingToolbarLayout>
        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:layout_gravity="bottom"
            app:tabIndicatorHeight="3dp"
            android:layoutDirection="ltr"
            app:tabIndicatorColor="@android:color/white"
            app:tabSelectedTextColor="@color/White"
            app:tabTextColor="@color/Black"
            app:tabMode="fixed"
            app:tabGravity="fill" />
    </android.support.design.widget.AppBarLayout>
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/content_frame"
        android:animateLayoutChanges="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:fillViewport="true" />
    </FrameLayout>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:id="@+id/nav_view"
    android:layoutDirection="rtl"
    app:headerLayout="@layout/header"
    app:menu="@menu/nav_menu" />
</android.support.v4.widget.DrawerLayout>

Then, when I switch the fragments, I show the tabs only on the fragment that I want them in, and hide them when I don't want them to show:

toolbar_layout.SetExpanded(true);
tabs.Visibility = ViewStates.Gone;

And when I want to show them:

toolbar_layout.SetExpanded(false,false);
tabs.Visibility = ViewStates.Visible;

Although I don't get them transparent, but I decided to just collapse the toolbar when I show them, and disable expanding it on the fragment with the tabs.
Maybe not the best solution, but it works pretty well for me.

These links really helped me:
- http://blog.iamsuleiman.com/parallax-scrolling-tabs-design-support-library/
- http://blog.iamsuleiman.com/material-design-tabs-with-android-design-support-library/
- How to use a TabLayout with Toolbar inside CollapsingToolbarLayout?
- http://manishkpr.webheavens.com/android-material-design-tabs-collapsible-example/
- Disable Scrolling in child Recyclerview android - How to disable expanding the toolbar on the fragment with the tabs (that also contains a recyclerview).

See what it looks like here: https://youtu.be/y2xLVSQ_NGM

It may not be the best solution, but I wanted a cleaner way that looks good.
Thank you all for your help!