半透明/透明状态栏+ CoordinatorLayout +工具栏+片段

时间:2016-01-13 08:27:23

标签: android android-fragments toolbar android-coordinatorlayout

我有以下设置:

  • 我正在使用AppCompat
  • MainActivity,包含一个片段并有一个工具栏,在向下滚动时隐藏
  • FragmentRecyclerView
  • 适合屏幕的所有视图都在xml布局中具有相应的android:fitsSystemWindows="true"

问题是,在这种情况下我无法使状态栏透明。我所做的是:

  1. 创建活动并调用setContent
  2. 然后我尝试调整活动,以编程方式获得如下的半透明工具栏:

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public void themeNavAndStatusBar(Activity activity)
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
            return;
    
        Window w = activity.getWindow();
        w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
        w.setFlags(
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        w.setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent));
    
        w.setStatusBarColor(activity.getResources().getColor(android.R.color.transparent));
    }
    
  3. 将活动(@+id/frame_container)中的占位符替换为片段

  4. 在这种情况下,状态栏是纯色的,并且未在其下方绘制视图...为什么?

    我想要什么

    我想要一个工具栏,滚动屏幕并完全隐藏,而此工具栏下方的内容应该适合屏幕,并在透明导航栏后面绘制。

    布局

    这是我的主要活动:

    <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/clMain"
        android:fitsSystemWindows="true"
        android:background="?attr/main_background_color"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.design.widget.AppBarLayout
            android:id="@+id/appBarLayout"
            android:fitsSystemWindows="true"
            android:background="@null"
            app:elevation="0dp"
            app:contentInsetLeft="0dp"
            app:contentInsetStart="0dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:elevation="4dp"
                android:theme="?actionBarThemeStyle"
                app:popupTheme="?actionBarPopupThemeStyle"
                app:layout_scrollFlags="scroll|enterAlways">
    
                <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content">
    
                    <LinearLayout
                        android:orientation="horizontal"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content">
    
                        <ImageView
                            android:id="@+id/ivToolbarDataSource"
                            android:layout_gravity="center_vertical"
                            android:layout_marginRight="2dp"
                            android:layout_width="24dp"
                            android:layout_height="24dp" />
    
                        <TextView
                            android:id="@+id/tvToolbarTitle"
                            style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
                            android:theme="?actionBarThemeStyle"
                            android:layout_gravity="center_vertical"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
    
                    </LinearLayout>
    
                    <TextView
                        android:id="@+id/tvToolbarSubTitle"
                        style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
                        android:theme="?actionBarThemeStyle"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content" />
    
                </LinearLayout>
    
    
    
            </android.support.v7.widget.Toolbar>
    
            <!-- BUG: http://stackoverflow.com/questions/30541409/coordinatorlayoutappbarlayout-does-not-draw-toolbar-properly -->
            <View
                android:layout_width="fill_parent"
                android:layout_height="1dp"/>
    
        </android.support.design.widget.AppBarLayout>
    
        <FrameLayout
            android:id="@+id/frame_container"
            android:fitsSystemWindows="true"
            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="bottom|right"
            android:layout_margin="32dp"
            android:src="@drawable/ic_local_offer_white_24dp"
            app:backgroundTint="?attr/colorPrimary"
            app:borderWidth="0dp"
            app:fabSize="normal"
            app:rippleColor="?attr/colorPrimaryDark"
            app:layout_anchorGravity="bottom|right|end"
            app:layout_behavior="com.test.classes.ScrollAwareFABBehavior"/>
    
    </android.support.design.widget.CoordinatorLayout>
    

    这是我的片段,将放在主要活动中:

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:fitsSystemWindows="true"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/srlImages"
            android:fitsSystemWindows="true"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/rvImages"
                android:fitsSystemWindows="true"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
    
        </android.support.v4.widget.SwipeRefreshLayout>
    
        <TextView
            android:id="@+id/tvEmpty"
            android:gravity="center"
            android:layout_centerInParent="true"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    
    </RelativeLayout>
    

    编辑 - 屏幕截图

    我使用浅色/深色基本主题并手工制作主题(因为用户可以选择任何颜色作为主要/强调颜色),所以不要介意工具栏是白色的(它是默认的主题背景颜色和主要颜色)颜色)。我还添加了一个黑色边框,以便您看到活动结束的位置......

    • 第一个屏幕截图:显示工具栏,不滚动任何内容
    • 第二个屏幕截图:我刚开始滚动=&gt;现在工具栏应该滚动
    • 第三个屏幕截图:主要内容现在应该在导航栏下方滚动...

    最后,我当然会让工具栏和导航栏半透明,以获得更好的视觉效果......

    enter image description here enter image description here enter image description here

8 个答案:

答案 0 :(得分:60)

tl; dr 至少将android:fitsSystemWindows="false"设置为根CoordinatorLayout和内部片段容器@frame_container

这可能不是最终解决方案(即可能有其他fitsSystemWindows要更改)所以告诉我你是否有任何问题。

<强>为什么

说到状态栏,我认为fitsSystemWindows是这样的:

  • fitsSystemWindows="false":由于您设置了窗口标记,因此正常绘制视图,位于状态栏下。
  • fitsSystemWindows="true":正常绘制视图,位于状态栏下,因为您设置了窗口标记,但添加了一个顶部填充,以便内容为在状态栏下方绘制,它们不重叠。

事实上,在我看来,你看到的白色不是状态栏颜色,而是你的CoordinatorLayout背景。这是由于协调器上的fitsSystemWindows="true":它将背景绘制到整个窗口,但是向内容添加了顶部填充,因此状态栏不会覆盖内部视图。

这不是你想要的。您的内部内容必须由状态栏覆盖,因此您必须将fitsSystemWindows="false"设置为协调员(因此它不会应用顶部填充),并且可能会将内容本身设置为内容。< / p>

一旦你了解它的工作方式,就可以轻松调试并达到你想要的效果实际上,事实并非如此。多年过去了,但我仍然花费数小时试图找出正确的fitsSystemWindows组合,因为大多数视图(至少在支持库中)都会覆盖我上面提到的默认行为,其方式大多不直观。有关如何使用它的小指南,请参阅this post

答案 1 :(得分:8)

编辑styles.xml(v21),添加以下样式

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

您可以根据自己的喜好更改父主题,但现在在AndroidManifest.xml文件中声明此主题,以执行以下特定活动:

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

这会让您的内容在透明操作栏下显示。

现在使用以下内容将工具栏正确对齐StatusBar,在你的oncreate中调用它:

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

使用以下内容获取状态栏高度:

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

从协调器布局标记中删除以下内容:

    android:fitsSystemWindows="true"

现在,为了折叠工具栏或隐藏它,您可以参考以下教程:

http://antonioleiva.com/collapsing-toolbar-layout/

确保您使用的是以下版本的设计支持库,因为它没有错误:

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

答案 2 :(得分:4)

在阅读了有关您问题的说明后,我认为 Google照片的样式符合您的要求。

好的,您的问题只有一些提示。经过我的测试,它确实有效。

  • 如果您想在状态栏后面显示内容,则需要在{。}}中添加<item name="android:windowTranslucentStatus">true</item> Android版本级别大于19(即 KitKat
  • 时的样式
  • 如果要在导航栏后面显示内容,则需要添加 <item name="android:windowTranslucentNavigation">true</item>进入你的 Android版本级别大于19(即 KitKat
  • 时的样式
  • 如果要在滚动内容时平滑地隐藏Toolbar 并在内容向下滚动时顺利显示Toolbar,你 需要将app:layout_collapseMode="parallax"添加到您的帐号中 Toolbar基于您当前代码的属性。当然,您 需要与Toolbar协调CollapsingToolbarLayout CoordinatorLayoutAppBarLayout

答案 3 :(得分:1)

对我来说,原因不是它本身不起作用,而是我使用Mike Penz的材料抽屉库,这个库确实使用工具栏后面的全屏+偏移+自定义背景,所以我不得不解决问题尊重那种特殊的设置...

我会奖励那些在我看来最具信息性的答案中的观点......

答案 4 :(得分:1)

正如一些用户所说,通过设置android:fitsSystemWindows="false",布局重叠低于statusbar

我通过设置android:fitsSystemWindows="true"并在CoordinatorLayout代码设置app:statusBarBackground="@android:color/transparent"中解决了这个问题。

答案 5 :(得分:0)

我有同样的问题,我的解决方案是将 android:fitsSystemWindows =&#34; true&#34; 添加到 DrawerLayout

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

....

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

答案 6 :(得分:0)

我有相关问题取决于android:fitsSystemWindows设置。 一旦错误: 在导航栏下绘制了小吃 一旦真实: 状态栏没有透明背景

解决方案非常简单...... 只是添加android:layout_marginBottom =&#34; 48dp&#34;。像CoordinatorLayout那样:

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

理论上导航栏应该有固定的大小&#34; 48dp&#34;,但在将来的版本中它可能会改变(就像状态栏在棉花糖中变得更加纤细1dp),所以我不会依赖于固定大小。 更好的是另外得到它并在运行时应用。

如果你像我一样使用谷歌地图你可能想知道运行时的动作栏/工具栏大小和导航栏:

onCreate中的

使用此代码:

            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;
                    }
                }
        );

重要的是什么。如果您有一些额外的图层,如抽屉等,则将它们封装在内部而不是外部的CoordinatorLayout中,否则它将通过marginBottom将其他视图缩短为内部

答案 7 :(得分:0)

在这里,我要使工具栏具有与状态栏相同的颜色,方法是使状态栏透明:

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