追記
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>
を指定して、Activity の onCreate() に以下の処理を追加します。
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();
}
...
}
CollapsingToolbarLayout の直接の子ビューで fitsSystemWindows が false のものは、ビューの配置位置を insetTop(ステータスバーの高さ)分だけ下にずらすようになっています。
つまり、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>
values-v21/bools.xml
<?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 でも次のような結果になります。
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 件のコメント:
コメントを投稿