web-dev-qa-db-ja.com

半透明/透明ステータスバー+ CoordinatorLayout +ツールバー+フラグメント

私は次のセットアップがあります:

  • AppCompatを使用しています
  • MainActivityは、フラグメントを保持し、ツールバーを持ち、スクロールダウンすると非表示になります
  • Fragment with RecyclerView
  • 画面に収まるはずのすべてのビューには、対応するAndroid:fitsSystemWindows="true" xmlレイアウト

問題は、この場合ステータスバーを透明にできないことです。私がしていることは次のとおりです:

  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)フラグメントを含む

この場合、ステータスバーは単色であり、ビューはその下に描画されません...なぜですか?

欲しいもの

画面がスクロールされ、完全に非表示になっているツールバーが必要ですが、このツールバーの下のコンテンツはScreenに収まり、透明なナビゲーションバーの後ろに描画されます。

レイアウト

主なアクティビティは次のとおりです。

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

EDIT-スクリーンショット

私は明るい/暗いベーステーマとすべてを手でテーマを使用します(ユーザーがプライマリ/アクセントカラーとして任意の色を選択できるため)。ツールバーが白であることを気にしないでください(デフォルトのテーマの背景色とプライマリ色です)。アクティビティの終了位置を確認できるように、黒い境界線も追加しました...

  • 最初のスクリーンショット:ツールバーを表示しますが、何もスクロールされません
  • 2番目のスクリーンショット:スクロールを開始しました=>ツールバーがスクロールします
  • 3番目のスクリーンショット:メインコンテンツがナビゲーションバーの下にスクロールします...

最後に、視覚効果を高めるために、もちろんツールバーとナビゲーションバーを半透明にします...

enter image description hereenter image description hereenter image description here

21
prom85

私にとっては、それ自体が機能しなかったからではなく、Mike Penzのマテリアルドロワーライブラリを使用し、このライブラリはツールバーの後ろにフルスクリーン+オフセット+カスタムバックグラウンドを使用しているため、その特別な点に関する問題を解決する必要がありましたセットアップ...

私の意見では最も有益な答えにポイントを報酬します...

1
prom85

tl; drAndroid:fitsSystemWindows="false"を少なくともルートCoordinatorLayoutおよび内部フラグメントコンテナ@frame_containerに設定します。

これは最終的な解決策ではない可能性があります(つまり、変更する他のfitsSystemWindowsが存在する可能性があります)。問題がある場合は教えてください。

理由

ステータスバーに関しては、fitsSystemWindowsのように思います。

  • fitsSystemWindows="false":ビューを通常どおりに描画します。設定したウィンドウフラグのため、nderステータスバー。
  • fitsSystemWindows="true":通常はビューを描画します。nder設定したウィンドウフラグのためにステータスバーが表示されますが、top paddingを追加の場合、コンテンツは下に描画されますステータスバーとそれらは重複しません。

実際、私の意見では、表示される白はステータスバーの色ではなく、CoordinatorLayout背景です。これは、コーディネーターのfitsSystemWindows="true"によるものです。ウィンドウ全体に背景を描画しますが、コンテンツに上部パディングを追加して、内部ビューがステータスバーで覆われないようにします。

これはあなたが望むものではありません。内側のコンテンツmustはステータスバーで覆われているため、fitsSystemWindows="false"をコーディネーターに設定する必要があります(したがって、上部のパディングが適用されません)。

仕組みがわかったら、 デバッグが簡単で、探している効果を実現できます実際にはそうではありません。何年も経ちますが、ほとんどのビュー(少なくともサポートライブラリ内)が上記で説明したデフォルトの動作を、ほとんど直感的ではない方法でオーバーライドするため、適切なfitsSystemWindowsの組み合わせを見つけるのに何時間も費やします。使い方の小さなガイドについては、 この投稿 を参照してください。

63
natario

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'
8
Udit Kapahi

あなたの質問についての説明を読んだ後、Google Photosのスタイルはあなたの要件に合っていると思いました。

OK、質問にはいくつかのヒントがあります。テスト後、動作します。

  • ステータスバーの背後にコンテンツを表示する場合は、Androidバージョンレベルが19(つまりKitKat)より大きい場合に<item name="Android:windowTranslucentStatus">true</item>をスタイルに追加する必要があります
  • ナビゲーションバーの背後にコンテンツを表示する場合、Androidバージョンレベルが19(つまりKitKat)より大きい場合に<item name="Android:windowTranslucentNavigation">true</item>をスタイルに追加する必要があります
  • コンテンツが上にスクロールされるときにToolbarをスムーズに非表示にし、コンテンツが下にスクロールされるときにToolbarをスムーズに表示するには、現在のコードに基づいてToolbarの属性にapp:layout_collapseMode="parallax"を追加する必要があります。もちろん、ToolbarCollapsingToolbarLayoutCoordinatorLayoutおよびAppBarLayoutとの座標が必要です。
4
SilentKnight

一部のユーザーが言ったように、Android:fitsSystemWindows="false"を設定することにより、レイアウトはoverlapped below statusbarです。

Android:fitsSystemWindows="true"CoordinatorLayoutタグの設定app:statusBarBackground="@Android:color/transparent"を設定することで解決しました。

2
MHSFisher

Android:fitsSystemWindowsの設定に依存する関連問題がありました。 falseの場合:ナビゲーションバーの下にスナックが描画されました。trueの場合:ステータスバーに透明な背景がありませんでした。

解決策は本当に簡単でした... Android:layout_marginBottom = "48dp"を追加するだけです。そのような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">

理論的には、ナビゲーションバーのサイズは "48dp"に固定されているはずですが、将来のリリースでは変更される可能性があります(ステータスバーがマシュマロで1dpスリムになったなど)。さらに、それを取得して実行時に適用することをお勧めします。

私のようなGoogleマップを使用している場合、実行時にActionBar/Toolbarのサイズとナビゲーションバーを知りたい場合があります。

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だけ短くなります

0
Artur Ex

私は同じ問題を抱えていて、私のソリューションはAndroid:fitsSystemWindows = "true"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>
0
Jorge Casariego