質問
Android のステータス バー (StatusBar) の背景色は開発者が変更できることはわかっていますが、テキストの色については、色の値を自分で直接変更することはできませんが、Light と 2 つのグローバル テーマに対応する白と黒です。ダークモデル。
優れたユーザー エクスペリエンスを実現するには、ステータス バーの背景が暗い場合は白いフォントを表示する必要があり、その逆の場合も同様です。例えば:
ただし、ライト モードでは黒いフォントが必要ない場合があるため、手動で変更する必要があります。
方法
以前は、ステータス バーに関連するコンテンツを変更して、さまざまな反映コードやさまざまなパッケージ化された StatusBarUtils を探していましたが、コードが洗練されていないだけでなく、奇妙な互換性の問題が発生しやすく、メンテナンスに役立ちませんでした。
現在、Google 関係者は、すべてが AndroidX にあるという解決策を提供しています。コードを直接見てください。
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsControllerCompat;
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 修改状态栏字体颜色,用AndroidX官方兼容API
WindowInsetsControllerCompat wic = ViewCompat.getWindowInsetsController(getWindow().getDecorView());
if (wic != null) {
// true表示Light Mode,状态栏字体呈黑色,反之呈白色
wic.setAppearanceLightStatusBars(false);
}
// 修改状态栏背景颜色,还是通用API,这个比较简单
getWindow().setStatusBarColor(...);
}
}
拡張すると、下部のナビゲーション バーの変更も含めて、同様になります。
// 修改导航栏按钮颜色
wic.setAppearanceLightNavigationBars(false);
// 修改导航栏背景色
getWindow().setNavigationBarColor();
他の
このクラスを使用するにはWindowInsetsControllerCompat
、それをインポートするだけでよくandroidx.core
、バージョン番号は任意で、最新のものが使用されます。
androidx.appcompat
ただし、すでにまたはに依存している場合はcom.google.android.material
、最初の 2 つにすでにコアが含まれているため、コアを個別に導入する必要はありません。
dependencies {
// 直接依赖
implementation "androidx.core:core:1.5.0"
// 间接依赖
implementation "androidx.appcompat:appcompat:1.3.1"
// or
implementation "com.google.android.material:material:1.4.0"
}
実際、興味があれば、ソース コードを確認するだけで済みます。まず、対応する実装が、さまざまなシステム バージョン番号に従って返されます。
@Nullable
public static WindowInsetsControllerCompat getWindowInsetsController(@NonNull View view) {
if (Build.VERSION.SDK_INT >= 30) {
return ViewCompat.Api30Impl.getWindowInsetsController(view);
} else {
Context context = view.getContext();
while (context instanceof ContextWrapper) {
if (context instanceof Activity) {
Window window = ((Activity) context).getWindow();
return window != null ? WindowCompat.getInsetsController(window, view) : null;
}
context = ((ContextWrapper) context).getBaseContext();
}
return null;
}
}
次に、対応するバージョンに従って、対応する実装インターフェイスを呼び出します。
private static class Impl {
Impl() {
//privatex
}
// ... 省略其他
public boolean isAppearanceLightStatusBars() {
return false;
}
public void setAppearanceLightStatusBars(boolean isLight) {
}
public boolean isAppearanceLightNavigationBars() {
return false;
}
public void setAppearanceLightNavigationBars(boolean isLight) {
}
}
@RequiresApi(20)
private static class Impl20 extends Impl {
...}
@RequiresApi(23)
private static class Impl23 extends Impl20 {
...}
@RequiresApi(26)
private static class Impl26 extends Impl23 {
...}
@RequiresApi(30)
private static class Impl30 extends Impl {
...}
これが、開発者が互換性の問題を心配することなく、このクラスがさまざまなバージョンと互換性を持ち、断片化を効果的に軽減できる理由です。たとえば、API 26 より前では、API 26 は継承され、世代間で互換性がありましたが、API 30 ではインターフェイスが再実装されており、30 でいくつかの大きな変更と最適化が行われたことがわかります。