The easiest way to change the status bar text and background color

question

We know that the background color of Android's status bar (StatusBar) can be changed by the developer. As for the text color, the color value cannot be directly modified by oneself, but black and white, corresponding to the two global themes of Light and Dark. model.

For a good user experience, we need to give white fonts when the background of the status bar is dark, and vice versa. For example:

insert image description here

However, sometimes we don't need black fonts in Light Mode, so we need to modify them manually.

method

In the past, we used to modify the content related to the status bar to find various reflection codes, or various packaged StatusBarUtils. Not only the code is not elegant, but also prone to strange compatibility problems, which is not conducive to maintenance.

Now, Google officials have given a solution, everything is in AndroidX. Look directly at the code:

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(...);
    }
}

By extension, including modifying the bottom navigation bar, it is similar:

// 修改导航栏按钮颜色
wic.setAppearanceLightNavigationBars(false);
// 修改导航栏背景色
getWindow().setNavigationBarColor();

other

To use WindowInsetsControllerCompatthis class, you only need to import it androidx.core, the version number is arbitrary, and the latest one is used.

But if you already depend on androidx.appcompator com.google.android.material, you don't need to introduce core separately, because the first two already include 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"
}

In fact, if we are interested, we can simply look at the source code. First, the corresponding implementation will be returned according to different system version numbers:

@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;
    }
}

Then call the corresponding implementation interface according to the corresponding version:

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 {
    
    ...}

So this is why this class can be compatible with different versions without developers having to worry about compatibility issues, effectively alleviating fragmentation. We can also see some subtle differences. For example, before API 26, API 26 was inherited and compatible from generation to generation, but in 30, the interface was re-implemented, indicating that 30 has made some major changes and optimizations.

Guess you like

Origin blog.csdn.net/ysy950803/article/details/119869625