Translucent/Transparent status bar + CoordinatorLayout + Toolbar + Fragment

后端 未结 8 1123
难免孤独
难免孤独 2020-12-05 07:23

I have following setup:

  • I\'m using AppCompat
  • MainActivity, that holds a fragment and has a toolbar, that\'s hiding when scrolling down
相关标签:
8条回答
  • 2020-12-05 07:48

    tl;dr Set android:fitsSystemWindows="false" at least to the root CoordinatorLayout and to the inner fragment container, @frame_container.

    This might not be the final solution (i.e. there might be other fitsSystemWindows to change) so tell me if you have any problems.

    why

    When it comes to status bar, I think of fitsSystemWindows like so:

    • fitsSystemWindows="false" : draws the view normally, under the status bar because of the window flags you have set.
    • fitsSystemWindows="true" : draws the view normally, under the status bar because of the window flags you have set, but adds a top padding so that content is drawn below the status bar and they don't overlap.

    In fact, in my opinion, the white you see is not the status bar color, but rather your CoordinatorLayout background. That is due to fitsSystemWindows="true" on the coordinator: it draws the background to the whole window, but adds top padding to the content so inner views are not covered by status bar.

    This is not what you want. Your inner content must be covered by the status bar, and so you have to set fitsSystemWindows="false" to the coordinator (so it won't apply top padding) and probably to the content itself.

    Once you get how it works, it is easy to debug and achieve the effect you are looking for. Actually, it is not. Years pass, but I still spend hours trying to figure out the right fitsSystemWindows combination, because most Views (in the support libraries at least) override the default behavior that I stated above, in ways that are mostly not intuitive. See this post for a small guide on how to use it.

    0 讨论(0)
  • 2020-12-05 07:52

    Here's what I did to have the toolbar have the same color as the status bar, by getting the status bar transparent:

    build.gradle

    ...
        implementation 'androidx.core:core-ktx:1.2.0'
        implementation 'androidx.appcompat:appcompat:1.1.0'
        implementation 'com.google.android.material:material:1.1.0'
    
    
    **ScrollingActivity.kt**
    ```kt
    class ScrollingActivity : AppCompatActivity(R.layout.activity_scrolling) {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setSupportActionBar(toolbar)
        }
    }
    

    activity_scrolling.xml

    <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="wrap_content"
            android:background="#f00" android:fitsSystemWindows="true" android:theme="@style/AppTheme.AppBarOverlay">
    
            <com.google.android.material.appbar.MaterialToolbar
                android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/AppTheme.PopupOverlay" />
        </com.google.android.material.appbar.AppBarLayout>
    
        <androidx.core.widget.NestedScrollView
            android:layout_width="match_parent" android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
    
            <TextView
                android:layout_width="wrap_content" android:layout_height="wrap_content"
                android:layout_margin="@dimen/text_margin" android:text="@string/large_text" />
    
        </androidx.core.widget.NestedScrollView>
    
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    

    styles.xml

    <resources>
        <style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
            <item name="colorAccent">@color/colorAccent</item>
        </style>
    
        <style name="AppTheme.NoActionBar">
            <item name="windowActionBar">false</item>
            <item name="windowNoTitle">true</item>
            <item name="android:statusBarColor">@android:color/transparent</item>
        </style>
    
        <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
    
        <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
    
    </resources>
    

    manifest

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lb.myapplication">
    
        <application
            android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme">
            <activity
                android:name=".ScrollingActivity" android:label="@string/app_name"
                android:theme="@style/AppTheme.NoActionBar">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>
    
    0 讨论(0)
  • 2020-12-05 07:56

    For me, the reason was not that it did not work per se, but that I use the material drawer library from Mike Penz and this library does use fullscreen + offset + custom background behind the toolbar so I had to solve the problem respecting that special setup...

    I'll reward the points to the in my opinion most informative answer though...

    0 讨论(0)
  • 2020-12-05 08:01

    After reading your descriptions about your question, I thought styles of Google Photos matches your requirement.

    OK, there are just some tips for your question. After my test, it works.

    • If you want to show content behind status bar, you need add <item name="android:windowTranslucentStatus">true</item> into your style when Android version level is larger than 19(namely KitKat)
    • If you want to show content behind navigation bar, you need add <item name="android:windowTranslucentNavigation">true</item> into your style when Android version level is larger than 19(namely KitKat)
    • If you want to hide Toolbar smoothly when content is scrolled up and to show Toolbar smoothly when content is scrolled down, you need to add app:layout_collapseMode="parallax" into your Toolbar's attributes based on your current codes.Of course, you need coordinate Toolbar with CollapsingToolbarLayout CoordinatorLayout and AppBarLayout.
    0 讨论(0)
  • 2020-12-05 08:01

    I had relevant issues depend on android:fitsSystemWindows setting. Once false: Snacks was drawn under the Navigation bar Once true: Status bar had none transparent background

    Solution was really simple... Just to add android:layout_marginBottom="48dp". to CoordinatorLayout like that:

    just to add <android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:map="http://schemas.android.com/apk/res-auto"
    tools:context=".MapsActivity"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    
    android:fitsSystemWindows="false"
    android:layout_marginBottom="48dp">
    

    Theoretically Navigation bar should have fixed size "48dp", but in future releases potentially it may change (like Status bar got slimmer by 1dp in Marshmallow), so I wouldn't rely on fixed size. Better additionally get it and apply on run time.

    If You are using Google Map like me You may want to know ActionBar/Toolbar size and the navigation bar in run time:

    in onCreate use this code:

                final TypedArray styledAttributes = MapsActivity.this.getTheme().obtainStyledAttributes(
                    new int[]{android.R.attr.actionBarSize});
            mToolbarHeight = (int) styledAttributes.getDimension(0, 0);
            styledAttributes.recycle();
            // translucent bars code. Will not fire below Lollipop
            // Ask NavigationBar Height
            ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.coordinatorLayout),
                    new OnApplyWindowInsetsListener() { // setContentView() must be fired already
                        @Override
                        public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                            statusBar = insets.getSystemWindowInsetTop(); // You may also need this value
                            mNavBarHeight = insets.getSystemWindowInsetBottom();
                            if (mMap != null)
                                mMap.setPadding(0, mToolbarHeight, 0, mNavBarHeight);
                            // else will be set in onMapReady()
                            SharedPreferences.Editor editor = mSharedPref.edit();
                            editor
                                    .putInt(NAVBAR_HEIGHT_KEY, mNavBarHeight)
                                    .commit(); // Save the results in flash memory and run the code just once on app first run instead of doing it every run
                            return insets;
                        }
                    }
            );
    

    And what's important. If You got some additional layers like drawer etc put them encapsulating the CoordinatorLayout inside rather than outside as otherwise it will make other views inside shorter by the marginBottom

    0 讨论(0)
  • 2020-12-05 08:03

    Edit your styles.xml (v21) , add the following style

     <style name="AppTheme.Home" parent="AppTheme.Base">
        <!-- Customize your theme here. -->
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    
    </style>
    

    You can change parent theme as per your liking, but now declare this theme in your AndroidManifest.xml file for a particular activity like this :

     <activity
            android:theme="@style/AppTheme.Home"
            android:name=".HomeActivity"
            android:launchMode="singleTop"
            android:screenOrientation="portrait" />
    

    This will let your content visible under the transparent actionbar.

    Now use the following to align your toolbar below the StatusBar properly, call this in your oncreate:

     toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
    

    Get statusbar height using following :

    public int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }
    

    Remove the following from your coordinator layout tags :

    android:fitsSystemWindows="true"
    

    Now in order to collapse your toolbar or hide it you may refer to this tutorial

    Make sure you are using following version of design support library, as it is bug free :

    compile 'com.android.support:design:23.1.0'

    0 讨论(0)
提交回复
热议问题