Materialデザイン風にStatusBarにcolorPrimaryDarkを付けて、なおかつNavigationBarを透明にしながらCoordinatorLayoutでToolbarをスクロールしたら隠したいってときに思った風にできずにハマったので、あまり綺麗ではない対処法を取ったので書いておきます
あとソースコードはXamarin使ってるのでC#ですけど簡単にJava翻訳できると思います
SupportLibraryはJavaで使われてるやつのXamarin版となるXamarin.Android.Support.**のv23.1.1.1を使ってます
最初
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/RootLayout"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/CoordinatorLayout"
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:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/TabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/ViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:id="@+id/RootLayout">
~~~コンテンツ~~~
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/ColorPrimary</item>
<item name="colorPrimaryDark">@color/ColorPrimaryDark</item>
<item name="colorAccent">@color/ColorAccent</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>
</resources>
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/ColorPrimary</item>
<item name="colorPrimaryDark">@color/ColorPrimaryDark</item>
<item name="colorAccent">@color/ColorAccent</item>
<item name="android:statusBarColor">@color/ColorPrimaryDark</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
</resources>
(android:navigationBarColorの設定は必要ないかもしれない)
ViewPagerの中にはFragmentがぶちこまれます
これでイケると思ったのですがandroid:fitsSystemWindows="true"
はStatusBarだけでなくNavigationBarのとこもpaddingしちゃうみたいで透過したNavigationBarの下にコンテンツを見せるということができなかったのです
試行錯誤
android:fitsSystemWindows="true"
の入れる場所を変えたり、android:fitsSystemWindows="true"
を使わずにpaddingしたり、StatusBarの部分になにもないViewを追加したりしても希望通りの状態にはなりませんでした…
ぐーぐる大先生
とりあえずぐーぐる大先生に聞いてみようってことで調べていたらstackOverFlowにAndroid 4.4 — Translucent status/navigation bars — fitsSystemWindows/clipToPadding don't work through fragment transactionsという関係ありそうな記事を見つけました
そしてそこのリンク先のTHE MIND OF AN ANDROID DEV - MAKING THE STATUS BAR AND NAVIGATION BAR TRANSPARENT, WITH A LISTVIEW, ON ANDROID 4.4 KITKATを見るとどうやらandroid:clipToPadding="false"
でScrollViewなどでViewからはみ出た部分を表示することができるということがわかりました
対策
なのでandroid:clipToPadding="false"
とそれを使うのに必要らしいandroid:clipChildren="false"
を使ったのですが、今度はViewPagerの高さがToolbarが表示されているときの高さのまま固定されToolbarが隠れたら下にToolbarの高さ分余白ができてしまいました
ということなので最初からViewPagerの高さをToolbarの高さ分大きくしておくことにしました
private int originalViewPagerHeight = 0;
public override void OnWindowFocusChanged(bool hasFocus) {
base.OnWindowFocusChanged(hasFocus);
if(Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
var viewpager = FindViewById<ViewPager>(Resource.Id.ViewPager);
if(originalViewPagerHeight == 0) {
originalViewPagerHeight = viewpager.Height;
}
viewpager.LayoutParameters.Height = originalViewPagerHeight + GetActionbarSize();
}
}
public int GetActionbarSize() {
var tv = new TypedValue();
int result = 0;
if(this.Theme.ResolveAttribute(Resource.Attribute.actionBarSize,tv,true)) {
result = TypedValue.ComplexToDimensionPixelSize(tv.Data,this.Resources.DisplayMetrics);
}
return result;
}
そしたら今度はNestedScrollViewでToolbarの高さ分スクロールできる部分が減ってしまう事態に
(これはまじで原因わからなかった)
ということなのでスクロールできる部分が減るなら最初から多めに取っておけばいいじゃんってことでレイアウトを変更しました
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clipToPadding="false">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:id="@+id/RootLayout">
~~~コンテンツ~~~
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/BottomView"
android:visibility="gone" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
public override View OnCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
~~~いろいろ~~~
if(Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
view.FindViewById<View>(Resource.Id.BottomView).Visibility = ViewStates.Visible;
}
return view;
}
これで完璧wってなったのですが画面回転を試すと
- 縦画面で起動←OK
- 横画面で起動←OK
- 縦画面で起動→横画面に←Toolbarの高さ分スクロールできない
- 横画面で起動→縦画面に→横画面に→Toolbarの高さ分スクロールできない
という風に画面回転をすると横画面の時にまたToolbarの高さ分スクロールできないということに(なんでだよ…)
対策版
以上を踏まえたうえでの対策した完成版をあげておきます
下部に余計な余白がでてくる可能性はありますがまぁ大丈夫かと
(Styleはそのままです)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/RootLayout"
android:fitsSystemWindows="true"
android:clipChildren="false"
android:clipToPadding="false">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/CoordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/Toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<android.support.design.widget.TabLayout
android:id="@+id/TabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/ViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clipToPadding="false">
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:id="@+id/RootLayout">
~~~コンテンツ~~~
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/BottomView"
android:visibility="gone" />
<View
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:id="@+id/BottomView2"
android:visibility="gone" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
private int originalViewPagerHeight = 0;
public override void OnWindowFocusChanged(bool hasFocus) {
base.OnWindowFocusChanged(hasFocus);
if(Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
var viewpager = FindViewById<ViewPager>(Resource.Id.ViewPager);
if(originalViewPagerHeight == 0) {
originalViewPagerHeight = viewpager.Height;
}
viewpager.LayoutParameters.Height = originalViewPagerHeight + GetActionbarSize();
}
}
public int GetActionbarSize() {
var tv = new TypedValue();
int result = 0;
if(this.Theme.ResolveAttribute(Resource.Attribute.actionBarSize,tv,true)) {
result = TypedValue.ComplexToDimensionPixelSize(tv.Data,this.Resources.DisplayMetrics);
}
return result;
}
public override View OnCreateView(LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {
~~~いろいろ~~~
if(Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop) {
view.FindViewById<View>(Resource.Id.BottomView).Visibility = ViewStates.Visible;
if(view.Resources.Configuration.Orientation== global::Android.Content.Res.Orientation.Landscape) {
view.FindViewById<View>(Resource.Id.BottomView2).Visibility = ViewStates.Visible;
}
}
return view;
}
さいごに
もっと綺麗なやり方あったらコメントお願いします
画面はXperia Z4でしか確認していないので機種差はあるかもしれないです