以编程方式安装Android M Light and Dark状态栏 - 如何让它再次变黑?

问题描述 投票:25回答:6

在Android M中,我们可以将状态栏图标设置为黑暗。为此,我们可以在主题的xml中指定属性:

<item name="android:windowLightStatusBar">true</item>

或者我们使用以下代码在运行时设置它:

View someView = findViewById(R.id.some_view);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    someView.setSystemUiVisibility(someView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

它实际上工作正常。但问题是如何在运行时将状态栏模式正确设置为黑暗?

我已经尝试过这些变种:

// Makes status bar mode dark, but also hides it along with all navigation views. 
someView.setSystemUiVisibility(someView.getSystemUiVisibility() | ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

// Does nothing 
someView.setSystemUiVisibility(someView.getSystemUiVisibility() & ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

// Also does nothing 
someView.setSystemUiVisibility(someView.getSystemUiVisibility() ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

那么如何才能以正确的方式完成?

android user-interface android-6.0-marshmallow android-statusbar
6个回答
39
投票

@Aracem发布的解决方案有效,但如果您尝试更改状态栏的背景颜色,则无效。就我而言,我是按照以下方式进行的。

要启用windowLightStatusBar(以编程方式,在Utils类中),例如:

 public static void setLightStatusBar(View view,Activity activity){


            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                int flags = view.getSystemUiVisibility();
                flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
                view.setSystemUiVisibility(flags);
                activity.getWindow().setStatusBarColor(Color.WHITE); 
            }
}

要将StatusBar恢复到以前的状态:

  public static void clearLightStatusBar(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Window window = activity.getWindow();
            window.setStatusBarColor(ContextCompat
                 .getColor(activity,R.color.colorPrimaryDark)); 
        }
    }

恢复状态栏的颜色就足够了,它还可以恢复图标颜色。非常重要:直到setLightStatusBar(View view ..)中使用的视图从屏幕消失(即view.getVisibility()== GONE | INVISIBLE),才会发生恢复操作。


28
投票

根据Nick Butcher的项目“Plaid”

public static void clearLightStatusBar(@NonNull View view) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        int flags = view.getSystemUiVisibility();
        flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
        view.setSystemUiVisibility(flags);
    }
}

你可以找到项目Here


11
投票

我基于@Aracem和@CarlosHernándezGil,但我认为如果我们使用按位XOR(Java中的^运算符)将很容易理解

private void setLightStatusBar(Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); // get current flag
        flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;   // add LIGHT_STATUS_BAR to flag
        activity.getWindow().getDecorView().setSystemUiVisibility(flags); 
        activity.getWindow().setStatusBarColor(Color.GRAY); // optional
    }
}

private void clearLightStatusBar(Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); // get current flag
        flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // use XOR here for remove LIGHT_STATUS_BAR from flags
        activity.getWindow().getDecorView().setSystemUiVisibility(flags);
        activity.getWindow().setStatusBarColor(Color.GREEN); // optional
    }
}

说明

首先,看看SYSTEM_UI_FLAG_LIGHT_STATUS_BARsetSystemUiVisibility

/**
 * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
 * is compatible with light status bar backgrounds.
 */
public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;

public void setSystemUiVisibility(int visibility) {
    if (visibility != mSystemUiVisibility) {
        mSystemUiVisibility = visibility;
        ...
    }
}

我认为下面的2行代码很难理解

flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for set light status bar
flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for clear light status bar

乍一看,我认为我们可以使用简单的

flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; // for set light status bar
flags = 0; // for clear light status bar (0 <=> LIGHT_STATUS_BAR <=> default systemUiVisibility)

但我们应该使用|^因为 例如,我们要将状态栏和导航栏都设置为亮,然后我们将使用

flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR | View.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
activity.getWindow().getDecorView().setSystemUiVisibility(flags);

当我们不希望状态栏再亮时,我们可以使用

flags = View.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
activity.getWindow().getDecorView().setSystemUiVisibility(flags);

要么

flags = activity.getWindow().getDecorView().getSystemUiVisibility();
flags = flags ^ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 
activity.getWindow().getDecorView().setSystemUiVisibility(flags);

要了解更多为什么我们使用|^,我认为下面的教程可能有助于https://medium.com/@JakobUlbrich/flag-attributes-in-android-how-to-use-them-ac4ec8aee7d1这是我的理解。希望这有帮助


3
投票

我把这个简单的实用程序对象放在一起,允许您在任何片段中打开/关闭状态栏颜色和灯状态栏。但是,这依赖于使用Android Jetpack导航组件进行导航(Kotlin):

object StatusBarUtil {
    fun changeStatusBarColor(activity: Activity, @ColorInt color: Int, lightStatusBar: Boolean) {
        activity.window?.let { win ->
            val nav = Navigation.findNavController(activity, R.id.your_nav_host_fragmen /* TODO: Use the ID of your nav host fragment */)
            val currentDest = nav.currentDestination?.id
            val oldColor = win.statusBarColor
            val oldFlags = win.decorView.systemUiVisibility
            win.statusBarColor = color

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                var flags = oldFlags
                flags = if (lightStatusBar) {
                    flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
                } else {
                    flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
                }
                win.decorView.systemUiVisibility = flags
            }

            nav.addOnNavigatedListener { _, dest ->
                if (dest.id != currentDest) {
                    win.statusBarColor = oldColor
                    win.decorView.systemUiVisibility = oldFlags
                }
            }
        }
    }
}

要使用它,请在任何片段的onViewCreated中调用以下内容:

StatusBarUtil.changeStatusBarColor(requireActivity(), someDarkColor, false)

1
投票

我会在上面的答案中做一些改变。

上课

 public class DarkStatusBar {
    public static void setLightStatusBar(View view, Activity activity){

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            int flags = view.getSystemUiVisibility();
            flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
            view.setSystemUiVisibility(flags);
            activity.getWindow().setStatusBarColor(Color.WHITE);
        }
    }
}

并在任何地方调用它

        Window window = getWindow();
        View view = window.getDecorView();
        DarkStatusBar.setLightStatusBar(view,this);

0
投票

根据@phan-van-linh的回答,我为Xamarin Android编写了这个类

public static class ActivityExtensions
{
    public static void SetLightStatusBar(this Activity activity)
    {
        int flags = (int)activity.Window.DecorView.SystemUiVisibility; // get current flag
        flags |= (int)SystemUiFlags.LightStatusBar;   // add LIGHT_STATUS_BAR to flag
        activity.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)flags;
        //activity.Window.SetStatusBarColor(Color.GRAY); // optional
    }

    public static void ClearLightStatusBar(this Activity activity)
    {
        int flags = (int)activity.Window.DecorView.SystemUiVisibility; // get current flag
        flags = flags ^ (int)SystemUiFlags.LightStatusBar; // use XOR here for remove LIGHT_STATUS_BAR from flags
        activity.Window.DecorView.SystemUiVisibility = (StatusBarVisibility)flags;
        //activity.Window.setStatusBarColor(Color.GREEN); // optional
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.