追記
AppBarLayout と CollapsingToolbarLayout にも android:fitsSystemWindows="true" の指定を追加するようにしました。 これにより、v25.0.1, v25.0,0, v24.2.1, v24.2.0, v24.1.1, v24.1.0, v24.0.0, v23.4.0, v23.3.0, v23.2.1 でも動作することを確認してあります。
わかりやすいように
colorPrimary : #ff0000(赤)
colorPrimaryDark : #99ff00ff(マゼンダ)
contentScrim : #990000ff(青)
statusBarScrim : #9900ffff(シアン)
Toolbar の background : #9900ff00(緑)
にしてあります。
普通に実装するとこんな感じになります。
- <?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">
- <android.support.design.widget.AppBarLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fitsSystemWindows="true"
- android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
- <android.support.design.widget.CollapsingToolbarLayout
- android:id="@+id/toolbar_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:fitsSystemWindows="true"
- app:contentScrim="#990000ff"
- app:layout_scrollFlags="scroll|exitUntilCollapsed"
- app:statusBarScrim="#9900ffff">
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="360dp"
- android:scaleType="centerCrop"
- android:src="@drawable/sample"
- tools:ignore="ContentDescription" />
- <android.support.v7.widget.Toolbar
- android:id="@id/toolbar"
- android:layout_width="match_parent"
- android:layout_height="?attr/actionBarSize"
- app:layout_collapseMode="pin"
- tools:background="#9900ff00" />
- </android.support.design.widget.CollapsingToolbarLayout>
- </android.support.design.widget.AppBarLayout>
- <android.support.v4.widget.NestedScrollView
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="fill_vertical"
- app:layout_behavior="@string/appbar_scrolling_view_behavior">
- ...
- </android.support.v4.widget.NestedScrollView>
- </android.support.design.widget.CoordinatorLayout>


マゼンダ色の status bar が表示されています。この status bar を透明にして ImageView をその分上にあげるにはどうすればいいか。
そのためにまずテーマに
- <item name="android:statusBarColor">@android:color/transparent</item>
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- findViewById(android.R.id.content).setSystemUiVisibility(
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- }



マゼンダから赤色に変わりました。これはステータスバーの色が見えているのではなく CollapsingToolbar の領域が見えています。その証拠にスクロールするとこの領域も移動します。
この領域はどこで確保されているかというと CollapsingToolbarLayout の onLayout() です。
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- ...
- // Update our child view offset helpers
- for (int i = 0, z = getChildCount(); i < z; i++) {
- final View child = getChildAt(i);
- if (mLastInsets != null && !ViewCompat.getFitsSystemWindows(child)) {
- final int insetTop = mLastInsets.getSystemWindowInsetTop();
- if (child.getTop() < insetTop) {
- // If the child isn't set to fit system windows but is drawing within the inset
- // offset it down
- ViewCompat.offsetTopAndBottom(child, insetTop);
- }
- }
- getViewOffsetHelper(child).onViewLayout();
- }
- ...
- }
つまり、fitsSystemWindows = true を子ビューにセットすれば、この処理が行われないということです。
そこで ImageView に android:fitsSystemWindows="true" を追加すると
- <android.support.design.widget.CollapsingToolbarLayout
- ... >
- <ImageView
- ...
- android:fitsSystemWindows="true" />
- <android.support.v7.widget.Toolbar
- ... />
- </android.support.design.widget.CollapsingToolbarLayout>


この方法を取る場合、4.4 で注意が必要です。 「 StatusBar 透明化の正しい方法」で書いているように、v19 では android:windowTranslucentStatus をセットして、v21 では android:statusBarColor をセットしている場合、上記の対応を入れると次のように 4.4 で余分な領域が確保されてしまいます。

そのため、v21以降だけ android:fitsSystemWindows="true" が指定されるようにします。
values/bools.xml
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <bool name="fitsSystemWindowForImage">false</bool>
- </resources>
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <bool name="fitsSystemWindowForImage">true</bool>
- </resources>
- <android.support.design.widget.CollapsingToolbarLayout
- ... >
- <ImageView
- ...
- android:fitsSystemWindows="@bool/fitsSystemWindowForImage" />
- <android.support.v7.widget.Toolbar
- ... />
- </android.support.design.widget.CollapsingToolbarLayout>

4.4 での実行結果をよく見ると、閉じたときに status bar 分の領域が確保されずに Toolbar が status bar の下にきてしまうことがわかります。

残念ながら 4.4 で閉じた時に status bar 分を確保するシンプルな方法はありません。 以下のように inset を margin に付け替える Toolbar を用意するとこれが解決できます。
- public class CustomToolbar extends Toolbar {
- public CustomToolbar(Context context) {
- super(context);
- }
- public CustomToolbar(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public CustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
- @Override
- protected boolean fitSystemWindows(Rect insets) {
- final ViewGroup.LayoutParams params = getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- ((MarginLayoutParams) params).topMargin = insets.top;
- }
- return true;
- }
- }


0 件のコメント:
コメントを投稿