pergunta
Sabemos que a cor de fundo da barra de status do Android (StatusBar) pode ser alterada pelo desenvolvedor. Quanto à cor do texto, o valor da cor não pode ser modificado diretamente por si mesmo, mas sim preto e branco, correspondendo aos dois temas globais de Light e Escuro. modelo.
Para uma boa experiência do usuário, precisamos fornecer fontes brancas quando o fundo da barra de status estiver escuro e vice-versa. Por exemplo:
No entanto, às vezes não precisamos de fontes pretas no Modo Claro, então precisamos modificá-las manualmente.
método
No passado, costumávamos modificar o conteúdo relacionado à barra de status para encontrar vários códigos de reflexão ou vários StatusBarUtils empacotados.Não apenas o código não é elegante, mas também está sujeito a estranhos problemas de compatibilidade, o que não favorece a manutenção.
Agora, os responsáveis da Google deram uma solução, está tudo no AndroidX. Olhe diretamente para o código:
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(...);
}
}
Por extensão, incluindo a modificação da barra de navegação inferior, é semelhante:
// 修改导航栏按钮颜色
wic.setAppearanceLightNavigationBars(false);
// 修改导航栏背景色
getWindow().setNavigationBarColor();
outro
Para usar WindowInsetsControllerCompat
esta classe, você só precisa importá-la androidx.core
, o número da versão é arbitrário e a mais recente é usada.
Mas se você já depende do androidx.appcompat
or com.google.android.material
, não precisa introduzir o core separadamente, pois os dois primeiros já incluem o core:
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"
}
Na verdade, se estivermos interessados, podemos simplesmente olhar o código-fonte. Primeiro, a implementação correspondente será retornada de acordo com diferentes números de versão do sistema:
@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;
}
}
Em seguida, chame a interface de implementação correspondente de acordo com a versão correspondente:
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 {
...}
É por isso que esta classe pode ser compatível com diferentes versões sem que os desenvolvedores tenham que se preocupar com problemas de compatibilidade, aliviando efetivamente a fragmentação. Também podemos ver algumas diferenças sutis: por exemplo, antes da API 26, a API 26 era herdada e compatível de geração em geração, mas em 30 a interface foi reimplementada, indicando que 30 fez algumas mudanças e otimizações importantes.