web-dev-qa-db-ja.com

Android)でステータスバーのパディングをNavigationViewに設定する

サポートライブラリからDrawerLayoutとNavigationViewをホストするアクティビティがあります。ヘッダーレイアウトをナビゲーションビューに設定していて、ナビゲーションヘッダーの高さを「wrap_content」にします。そのため、高さを「wrap_content」に設定すると、ヘッダーレイアウトがステータスバーの後ろに表示されます。

私が望む結果は、ナビゲーションドロワーはステータスバーの後ろに描画する必要がありますが、ナビゲーションヘッダーはステータスバーの高さだけ押し下げられる必要があります。

以下は私が得ているもののスクリーンショットです。ステータスバーの後ろにある「サインイン」ボタンに注意してください。

screenshot

アクティビティレイアウト

<Android.support.v4.widget.DrawerLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:id="@+id/nav_drawer"
Android:fitsSystemWindows="true">

<Android.support.design.widget.CoordinatorLayout
                Android:layout_width="match_parent"
                Android:layout_height="match_parent">

    <Android.support.v4.view.ViewPager
        Android:id="@+id/view_pager"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"></Android.support.v4.view.ViewPager>
    <Android.support.design.widget.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content">

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

        <Android.support.design.widget.TabLayout
            app:theme="@style/ThemeOverlay.AppCompat.Dark"
            style="@style/MyCustomTabLayout"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            Android:id="@+id/tabs"
            />

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

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

<Android.support.design.widget.NavigationView
    Android:id="@+id/navigation_view"
    Android:layout_width="wrap_content"
    Android:layout_height="match_parent"
    app:headerLayout="@layout/nav_header"
    app:menu="@menu/menu_navigation"
    Android:fitsSystemWindows="true"
    Android:layout_gravity="start"/>

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

ナビゲーションビューヘッダーレイアウト

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
          Android:layout_width="match_parent"
          Android:layout_height="wrap_content"
          Android:background="?attr/colorPrimaryDark"
          Android:padding="16dp"
          Android:theme="@style/ThemeOverlay.AppCompat.Dark"
          Android:orientation="vertical"
          Android:fitsSystemWindows="true"
          Android:gravity="bottom">

<TextView
    Android:visibility="gone"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:id="@+id/text_user_name"
    Android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

<TextView
    Android:visibility="gone"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:id="@+id/text_email"
    Android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>

<Button
    Android:id="@+id/button_sign_in"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:text="Sign In"/>

</LinearLayout>

StackOverflowで解決策を検索しましたが、見つかりませんでした。だから誰かが光を当ててください。前もって感謝します。

16
Sreekanth
<Android.support.design.widget.NavigationView
Android:id="@+id/navigation_view"
Android:layout_width="wrap_content"
Android:layout_height="match_parent"
app:headerLayout="@layout/nav_header"
app:menu="@menu/menu_navigation"
Android:fitsSystemWindows="false"
Android:layout_gravity="start"/>

Android:fitsSystemWindows = "false"

およびCoordinatorLayout => Android:fitsSystemWindows = "false"

12
PanCrucian

まず、ロリポップの前にステータスバーの後ろに引くことはできないことを覚えておいてください。

解決

Lollipop +の場合、DrawerLayoutAndroid:fitsSystemWindows="true"を設定し、NavigationViewにデフォルトのままにする必要があります。

次に、ヘッダーを設定した後のアクティビティまたはフラグメントについて:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat_WATCH) {
    navigationView.setOnApplyWindowInsetsListener { v, insets ->

        val header = navigationView.getHeaderView(0)
        header.setPadding(
            header.paddingLeft, 
            header.paddingTop + insets.systemWindowInsetTop,
            header.paddingRight, 
            header.paddingBottom
        )
        insets.consumeSystemWindowInsets()
    }
}

説明

ウィンドウは、insets(上、左、下、右の寸法)というオブジェクトを子ビューに渡します。 fitSystemWindows=trueを持つ子ビューは、このインセットに対して何も行わず、子に転送する場合があります。 falseのビューは、値を使用して、それ自体に追加のパディングまたはマージンを追加する場合があります。

NavigationViewのSetfitSystemWindows=falseは、インセットを使用してそれ自体に追加のマージンを適用しているため、機能していません。必要なのは、このマージンを適用するためのヘッダービューLinearLayoutです。ただし、NavigationView内には2つの中間コンテナビューがあり、インセットをLinearLayoutに転送しないため、これらのコンテナの前にウィンドウのインセットをインターセプトして、マージンまたはパディングを適用する必要があります。ヘッダービュー。

絶対にすべきでないこと

Androidバージョンが何であれ、ウィンドウインセットが固定値であると想定したり、リソースから取得したりしないでください。特定のデバイスにはウィンドウインセットに特定の値があり、一部のデバイスにはより厚い「ノッチ」があります。大きなカメラに合うように、一部のメーカーはそれをAndroid推奨仕様よりも薄くすることを決定します。

4
Allan Veloso

ヘッダーレイアウトのルート要素としてLinearLayoutを使用しています。 FrameLayoutLinearLayoutなどは、Android:fitsSystemWindows属性を無視する基本的なレイアウトです。 ヘッダーレイアウトのルート要素としてCoordinatorLayoutを使用することをお勧めします。CoordinatorLayoutとそのAndroid:fitsSystemWindowsを使用する属性をtrueに設定すると、内部パディングが自動的に調整され、子要素がステータスバーなどのシステムウィンドウと重複しないようになります。

これらの情報は この記事 、「なぜfitsSystemWindowsが必要なのですか?」イアンレイクによって。

基本的なレイアウト(FrameLayout、LinearLayoutなど)はデフォルトの動作を使用しますが、特定のユースケースに合うようにfitsSystemWindowsへの反応をすでにカスタマイズしているレイアウトがいくつかあります。

.。

CoordinatorLayoutは、ウィンドウインセットの処理方法をオーバーライドすることも利用して、子ビューに設定された動作が、各子自体でdispatchApplyWindowInsets()を呼び出す前に、ビューがウィンドウインセットに反応する方法をインターセプトおよび変更できるようにします。また、fitsSystemWindowsフラグを使用して、ステータスバーの背景をペイントする必要があるかどうかを判断します。

目的を達成するには、このレイアウト構造に従っていることを確認してください。

layout/activity_xxxxx.xml

<Android.support.v4.widget.DrawerLayout
    ...
    Android:fitsSystemWindows="true">

    <!-- content -->
    ...

    <!-- drawer -->
    <Android.support.design.widget.NavigationView
        ...
        Android:fitsSystemWindows="true" 
        app:headerLayout="@layout/nav_header" />

<Android.support.v4.widget.DrawerLayout>

layout/nav_header.xml

<Android.support.design.widget.CoordinatorLayout
    ...
    Android:fitsSystemWindows="true">

    <!-- content -->
    ...

<Android.support.design.widget.CoordinatorLayout>
0
bmdelacruz