it-swarm.com.ru

Строка состояния Android M Light and Dark программно - как снова сделать ее темной?

В 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);

Так как это можно сделать правильно?

22
udenfox

Решение, опубликованное @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 | НЕВИДИМ) с экрана. 

36
Carlos Hernández Gil

По проекту Ника Батчера "Плед" 

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

Вы можете найти проект Здесь

26
Aracem

Я базируюсь на @Aracem и @Carlos Hernández Gil, но думаю, что это будет легко понять, если мы будем использовать оператор bitwise 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_BAR и setSystemUiVisibility

/**
 * 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);

OR

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 Вот мое понимание. Надеюсь это поможет

7
Linh

Я собрал этот простой служебный объект, который позволяет вам менять цвет строки состояния и подсветку строки состояния для любого фрагмента. Однако это зависит от использования компонента навигации Jetpack для Android (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)
3
hsson

я сделаю некоторые изменения в ответах выше.

сделать класс

 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);
1
roshan posakya

Основываясь на ответе @ phan-van-linh, я написал этот класс для Android Xamarin

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
    }
}
0
gianlucaparadise