Androidのタイトルバー、ステータスバーアイコンのテキストの色と背景のダイナミクス



Android Title Bar Status Bar Icon Text Color



アンドロイドの没入型ステータスバーの記事はすでに通りでいっぱいですが、いくつかの効果の実現では、それでもさまざまな種類を検索する必要があります。テスト終了後は、携帯電話の需要に応えることが難しくても、最終的には要件を満たせません。別の携帯電話に入れてみたところ、効果が良くないことがわかりました。今日は、過去数日間に学んだ没入型ステータスバーに関する知識を要約します。

問題



たとえば、次の効果を実現したいと思います。

  1. 同じアクティビティで、タイトルバーとステータスバーのテキストフォントの色の値を動的に変更する必要があります。どのように実現しますか?



  2. アクティビティに複数のフラグメントスイッチ、異なるフラグメントのステータスバーの背景、ステータスバーのテキストの色、アイコンの要件が同じでない場合はどうでしょうか。

  3. 没入型ステータスバー、さまざまなAndroidバージョンの違い、非常に多くのフラグを設定し、同じように見えますが、違いは何ですか?

これらの質問で、私が達成した最初の2つのレンダリングは、絵も真実もありません。



以下は、同じアクティビティが異なるフラグメント間で切り替わるときにステータスバーのテキストの色が変化する効果図です。

同じアクティビティが異なるフラグメント間で切り替わると、ステータスバーのテキストの色が変わります。

次の図は、同じアクティビティを上にスクロールしたときの変更に応じた、タイトルバーとステータスバーのテキストの色の影響を示しています。

アクティビティが上にスクロールすると、タイトルバーとステータスバーのテキストの色が変わります。

1.透過ステータスバーの一般的な方法を実装します

Protected boolean useThemestatusBarColor = false / / whether to use a special title bar background color, android5.0 can set the status bar background color, if not use the transparent color value Protected boolean useStatusBarColor = true / / Whether to use the status bar text and icons are dark, if the status bar is white, you need to make the status bar and icon dark, android6.0 or above can be set protected void setStatusBar() { If (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0 and above View decorView = getWindow().getDecorView() int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE decorView.setSystemUiVisibility(option) / / According to the above settings, whether to set the color separately for the status bar if (useThemestatusBarColor) { getWindow().setStatusBarColor(getResources().getColor(R.color.colorTheme)) } else { getWindow().setStatusBarColor(Color.TRANSPARENT) } } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) //4.4 to 5.0 WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes() localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS If (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !withoutUseStatusBarColor) //android6.0 can modify the status bar text color and icon later getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN }

android:fitsSystemWindows =” true”属性をアクティビティレイアウトのルートに追加します。レイアウトがステータスバーとナビゲーションバーの下に来る場合、それはナビゲーションバーとステータスバーと重なります。これは確かに私たちが望んでいることではありません。

上記の設定でアクティビティを行うと、次のような効果が得られます。

ステータスバーのテキストの色とアイコンは黒です

上記の2つのフラグは、主にステータスバーのテキストの色とアイコンを暗い色に設定するために使用されます。

/ / Set the status bar text color and icon is dark getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR)
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREENは、次の効果を実現するためにAPI16から有効になっています。
    ビューはステータスバー領域まで拡張され、ステータスバーはビューの上に浮かんでいます。

  • View.SYSTEM_UI_FLAG_LIGHT_STATUS_BARは、次の効果を実現するためにAPI23から有効になっています。
    ステータスバーアイコンとステータスバーのテキストの色を暗く設定します。ステータスバーの背景に合わせるために、フラグは点灯しています。このフラグは、FLAG_DRWS_SYSTEM_BAR_BACKGROUNDSが使用され、FLAG_TRANSLUCENT_STATUSが使用されていない場合にのみ有効です。ステータスバーが透明な場合にのみ有効です。

2.同じアクティビティに複数のフラグメントが含まれている場合、異なるフラグメントステータスバーの背景とテキストの色を実現する方法が異なります

次の効果図に示すように:

同じアクティビティが異なるフラグメント間で切り替わると、ステータスバーのテキストの色が変わります。

ステータスバーを暗く設定した後、元に戻す必要があります。これは主に次の2つのフラグフラグに基づいています。上記の2つのフラグフラグを実装できます。

/ / Set the status bar text color and icon is light getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN前述のように、これにより、ビューがステータスバー領域に拡張され、ステータスバーがビューレイアウトの上に浮かび上がります。

  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE
    ビュー全体を安定させ、システムUIの変更によってビューが再レイアウトされないように、システムUIを制御して非表示のフラグをフロートおよび非表示にすることがよくあります。

上記の効果を実現するには、上記のコードを別のフラグメントスイッチに配置します。

private void switchTo(int position) { FragmentTransaction transaction = getSupportFragmentManager().beginTransaction() switch (position) View.SYSTEM_UI_FLAG_LAYOUT_STABLE) getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, CommonUtils.navigationHeight) break Case 1: //activity hideShowFragment(transaction, homeFragment, thirdFragment, fourFragment, secondFragment)//Show the second fragment if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, CommonUtils.navigationHeight) break Case 2: //All pictures hideShowFragment(transaction, homeFragment, fourFragment, secondFragment, thirdFragment) //Show the third fragment if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) / / Realize the status bar icon and text color is dark getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, CommonUtils.navigationHeight) break Case 3://my hideShowFragment(transaction, homeFragment, secondFragment, thirdFragment, fourFragment)//Show the fourth fragment / / Realize the status bar icon and text color is light getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } //fragment switch implementation private void hideShowFragment(FragmentTransaction transaction, Fragment fragment1, Fragment fragment2, Fragment fragment3, Fragment fragment4) { transaction.hide(fragment1) transaction.hide(fragment2) transaction.hide(fragment3) transaction.show(fragment4) transaction.commitAllowingStateLoss() }

ここで各フラグメントを切り替えると、次のコード行があることに気付くかもしれません。

getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, CommonUtils.navigationHeight)

このコード行の用途は何ですか。ホームページとマイページはステータスバーに背景画像を入力する必要があるため、android:fitsSystemWindowsプロパティを使用できないため、大きな携帯電話があります。上記の効果を実装する場合の下部のナビゲーションバー。ピット、解決策は第3章に示されています。同時にandroid:fitsSystemWindowsプロパティを使用しないでください。レイアウトの作成方法はステータスバーのテキストを覆い隠しません。解決策は第4章に示されています。

3.下部のナビゲーションバーを備えた電話の下部にあるナビゲーションボタンは、ナビゲーションバーと重なります

以下に示すように:

下部のナビゲーションバーが下部のボタンと重なっています

フルスクリーンでは、ビューレイアウトがステータスバーとナビゲーションバーの下に表示されるため、android:fitsSystemWindows =” true”属性を使用しない場合、アプリケーションの下部のナビゲーションバーと下部のボタンが重なって表示されます。ガイドボタンのクリックは無効になります。私は何をすべきか? ?
インターネット上で関連情報を検索した後、実装方法は透過ステータスバーの実装と一致しています。
解決:

  1. まず、電話に物理的なボタンがあるかどうかを判断して、NavigationBarがあるかどうかを判断します

  2. 下部のナビゲーションバーの高さを計算します

  3. 最後に、ビューマージンを設定します。

3.1反射によって電話に物理的なボタンNavigationBarがあるかどうかを判断する

/ / Determine whether there is a NavigationBar public static boolean checkDeviceHasNavigationBar(Context context) { boolean hasNavigationBar = false Resources rs = context.getResources() int id = rs.getIdentifier('config_showNavigationBar', 'bool', 'android') if (id > 0) { hasNavigationBar = rs.getBoolean(id) } try { Class systemPropertiesClass = Class.forName('android.os.SystemProperties') Method m = systemPropertiesClass.getMethod('get', String.class) String navBarOverride = (String) m.invoke(systemPropertiesClass, 'qemu.hw.mainkeys') if ('1'.equals(navBarOverride)) { hasNavigationBar = false } else if ('0'.equals(navBarOverride)) { hasNavigationBar = true } } catch (Exception e) { } return hasNavigationBar }

3.2下部のナビゲーションバーの高さを計算します

/** * Get the height of the bottom navigation bar * @return */ public static int getNavigationBarHeight(Context context) { Resources resources = context.getResources() int resourceId = resources.getIdentifier('navigation_bar_height', 'dimen', 'android') / / Get the height of the NavigationBar navigationHeight = resources.getDimensionPixelSize(resourceId) return navigationHeight }

3.3ビューマージンの設定

getWindow().getDecorView().findViewById(android.R.id.content).setPadding(0, 0, 0, CommonUtils.navigationHeight)

上記の設定では、レイアウトは下部のナビゲーションバーからの高さになります。
最終的な実装は次のとおりです。

ナビゲーションバーが下のボタンと重ならない

参考記事:android6.0ナビゲーションバーNavigationBarインパクトビューソリューション

4. fiySystemWindowプロパティを使用せずに、レイアウトがステータスバーのテキストを覆い隠さないようにするにはどうすればよいですか?

第3章と同様に、ホームページで、マージンステータスバーの高さまでのテキストでレイアウトのレイアウトを作成する必要があります。

4.1最初にレイアウトにデューティLinearLayoutを設定します

3番目のフラグメントのレイアウトを見てみましょう。

4.2コードでデューティレイアウトの高さを動的に設定する

/** * Dynamic setting status bar Implement immersive status bar */ private void initState() { //You can use the immersive status bar when the system version is 4.4 or higher. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //Transparent status bar getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) / / Transparent navigation bar getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) bindingView.llBar.setVisibility(View.VISIBLE) / / Get the height of the status bar int statusHeight = CommonUtils.getStatusBarHeight(getActivity()) / / Dynamic settings hide the height of the layout LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) bindingView.llBar.getLayoutParams() params.height = statusHeight bindingView.llBar.setLayoutParams(params) } } /** * Get the status bar height by reflection * * @return */ public static int getStatusBarHeight(Context context) { try { Class c = Class.forName('com.android.internal.R$dimen') Object obj = c.newInstance() Field field = c.getField('status_bar_height') int x = Integer.parseInt(field.get(obj).toString()) return context.getResources().getDimensionPixelSize(x) } catch (Exception e) { e.printStackTrace() } return 0 }

上記の2番目と3番目のフラグメントの実装では、ビューレイアウトがステータスバーのテキストを覆い隠さないようにするために、主に最初にインターフェイスの場所のレイアウトを設定し、次にコードでレイアウトをステータスバーの高さに動的に設定します、これは実際にはステータスバーをこのデューティレイアウトの上に浮かせてください。ビューレイアウトがステータスバーの効果を覆い隠さないように、ビューレイアウトはデューティレイアウトの下にあります。
上記のバージョンの判断では、Androidのバージョンが4.4より大きい場合、レイアウトが表示され、バージョンは4.4より小さくなります。没入型のステータスバー効果がないため、インターフェイスを設定する必要はありません。空のレイアウト。

最初のホームページと4番目のマイフラグメントでは、レイアウトする必要のある画像がステータスバーの下に表示され、タイトルバーはステータスバーの下にあります。実際、必要なトリックは1種類だけです。一般的に携帯電話のステータスバーの高さは25dp前後ですが、もちろんステータスバーの高さはコードで動的に取得され、動的な設定も可能です。私は簡単な実装を行うためにここにいます。タイトルバーのmarginTopステータスバーの高さは、Androidのさまざまなバージョンで、次のように設定できます。
値にdimensions.xmlのステータスバーの高さを設定します。

0dp

values-v19でdimensions.xmlのステータスバーの高さを設定します。

25dp

5.同じアクティビティを上下にスワイプすると、タイトルバーとステータスバーのテキストフォントの色の値が動的に変更されます

効果は次のとおりです。

アクティビティが上にスクロールすると、タイトルバーとステータスバーのテキストの色が変わります。

このレイアウトの実装は、主にCoordinatorLayout + AppBarLayout + CollapsingToolbarLayout +ツールバー+ NestedScrollViewに依存しています。 CoordinatorLayoutの使用法を紹介するために、同様のブログ投稿も作成しました。興味のあるパートナーは参照できます:androidイマーシブステータスバー、fitsSystemWindows、タイトルバー折りたたみ
インターフェイスをスワイプしたときにステータスバーとタイトルバーのテキストの色を変更する方法について説明しましょう。

これは主に、AppBarLayoutのスライドの距離を聞いて、上にスライドすることによるものです。タイトルバーの高さよりも大きい場合は、タイトルバーのテキストの色を動的に変更する必要があります。タイトルバーを折りたたむと、ステータスバーの色とボタンのアイコンが戻り、ステータスバーの色が暗くなります。
下にスライドすると、タイトルバーがゆっくりと消えるので、ステータスバーのテキストの色を明るい色に変更する必要があります。

private void setAppBarListener() { measureHeight() bindingView.appbar.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { if (verticalOffset == 0) { if (state != CollapsingToolbarLayoutState.EXPANDED) View.SYSTEM_UI_FLAG_VISIBLE) } else if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) { bindingView.titleTv.setVisibility(View.VISIBLE) bindingView.toolbar.setNavigationIcon(R.drawable.nav_icon_return) State = CollapsingToolbarLayoutState.COLLAPSED / / modified to collapsed state if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } else { if (Math.abs(verticalOffset) > height) { bindingView.titleTv.setVisibility(View.VISIBLE) float scale = 1- height / (float) Math.abs(verticalOffset) if (state != CollapsingToolbarLayoutState.INTERNEDIATE) { If (state == CollapsingToolbarLayoutState.COLLAPSED && scale = Build.VERSION_CODES.M) getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN } state = CollapsingToolbarLayoutState.INTERNEDIATE } float alpha = (255 * scale) bindingView.titleTv.setTextColor(Color.argb((int) alpha, 53,55,58)) bindingView.toolbar.setNavigationIcon(R.drawable.nav_icon_return) } else { bindingView.titleTv.setVisibility(View.GONE) bindingView.toolbar.setNavigationIcon(R.drawable.nav_icon_white_return) } } }) } / / Get the height of the title bar private void measureHeight() { ViewTreeObserver vto = bindingView.coordinatorlayout.getViewTreeObserver() vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { if (hasMeasured == false) { height = bindingView.toolbar.getMeasuredHeight() hasMeasured = true } return true } }) }

総括する

アンドロイドが提供するウィドノウフラグ、ステータスバーの明るいトーンと暗いトーンによると、アクティビティのステータスバーの色をリアルタイムで動的に変更でき、CoordinatorLayoutと組み合わせることで、より複雑な効果を実現できます。

コード転送ゲート:
https://github.com/xiewenfeng/statusbartextcolorchange