web-dev-qa-db-fra.com

Matériau Android: la couleur de la barre d'état ne changera pas

Je développe une application simple pour tester la conception du matériau. J'utilise com.Android.support:appcompat-v7:21.0.0 et mon activité ressemble à:

public class MyActivity extends ActionBarActivity {
   ...
}

La mise en page est définie comme suit:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    tools:context=".MyActivity">

    <Android.support.v7.widget.Toolbar
        xmlns:Android="http://schemas.Android.com/apk/res/Android"
        Android:id="@+id/toolbar"
        Android:layout_width="match_parent"
        Android:layout_height="128dp"
        Android:minHeight="?attr/actionBarSize"
        Android:background="?attr/colorPrimaryDark"/>
</LinearLayout>

Maintenant, j'ai défini mon thème en suivant les directives matérielles:

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary500</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark700</item>
</style>

J'aimerais modifier la couleur de la barre d'état dans la version antérieure à Android 5 et la définir sur colorPrimaryDark, mais je ne trouve pas le chemin. J'ai essayé d'utiliser:

getWindow().setStatusBarColor(..)

mais la couleur setStatusBar est disponible à partir du niveau 21. Pourquoi si je définis un colorPrimaryDark dans mon thème et que j'utilise appcompact, la barre d'état ne change pas de couleur? Tout le monde peut aider?

53
FrancescoAzzola

La barre d'état est une fenêtre système appartenant au système d'exploitation. Sur les appareils Android antérieurs à la version 5.0, les applications n’étant pas autorisées à modifier sa couleur, la bibliothèque AppCompat ne peut pas en prendre en charge les versions plus anciennes de la plateforme. Le meilleur qu'AppCompat puisse faire est de prendre en charge la coloration de ActionBar et d'autres widgets d'interface utilisateur courants au sein de l'application.

60
Alex Lockwood

Bien que la couleur de la barre d'état ne soit pas prise en charge <5.0, vous pouvez utiliser une solution de contournement pour obtenir une couleur plus sombre sous 4.4:

Rendre la barre d'état transparente 

<item name="Android:windowTranslucentStatus">true</item>

Utilisez ensuite la barre d’outils AppCompat pour votre barre d’application, en vous assurant qu’elle s’adapte aux fenêtres système:

<Android.support.v7.widget.Toolbar
    Android:id="@+id/toolbar"
    ...
    Android:fitsSystemWindows="true"/>

Assurez-vous de définir votre barre d'outils en tant que barre d'outils de votre activité:

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ...
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

La barre d'outils s'étend sous la barre d'état et la semi-translucidité de la barre d'état lui donne une couleur secondaire plus sombre. Si ce n'est pas la couleur que vous souhaitez, cette combinaison vous permet d'ajuster une vue sous votre barre d'état affichant la couleur d'arrière-plan de votre choix (même si elle est toujours plus foncée dans la barre d'état).

Une sorte de solution de contournement pour les cas Edge en raison de la version 4.4 uniquement, mais voilà.

59
Tom
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    getWindow().setStatusBarColor(getResources().getColor(R.color.actionbar));
}

Placez ce code dans la méthode onCreate de votre activité. Cela m'a aidé.

39
user998953

Comme d'autres l'ont également mentionné, cela peut être facilement résolu en ajoutant ce qui suit au onCreate () de l'activité:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.primary_dark));
    }

Cependant, le point important que je veux ajouter ici est que, dans certains cas, même la procédure ci-dessus ne modifie pas la couleur de la barre d'état. Par exemple, lorsque vous utilisez la bibliothèque MikePenz pour Navigation Drawer, elle remplace implicitement la couleur de la barre d'état. Vous devez donc ajouter manuellement les éléments suivants pour que cela fonctionne:

.withStatusBarColorRes (R.color.status_bar_color)

13
kingmehr

La coloration de la barre d'état n'est pas prise en charge dans AppCompat v7: 21.0.0.

À partir du Blog de développeur Android

Sur les anciennes plates-formes, AppCompat émule la thématisation des couleurs dans la mesure du possible. Pour le moment, cela se limite à colorier la barre d’action et certains widgets.

Cela signifie que la bibliothèque AppCompat ne colorera que les barres d'état sur Lollipop et au-dessus.

9
Anup Cowkur

Basculez vers AppCompatActivity et ajoutez un dp paddingTop de 25 dp dans la barre d’outils et activez-le. 

<item name="Android:windowTranslucentStatus">true</item>

Ensuite, la barre d’outils va monter en haut en haut

8
alvarlagerlof

Cette solution définit la couleur de la barre d'état de Lollipop, KitKat et de certains périphériques antérieurs à Lollipop (Samsung et Sony) . Le SystemBarTintManager gère les périphériques KitKat;) 

@Override
protected void onCreate( Bundle savedInstanceState ) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    hackStatusBarColor(this, R.color.primary_dark);
}

@SuppressLint("NewApi")
@SuppressWarnings("deprecation")
public static View hackStatusBarColor( final Activity act, final int colorResID ) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Lollipop) {
        try {

            if (act.getWindow() != null) {

                final ViewGroup vg = (ViewGroup) act.getWindow().getDecorView();
                if (vg.getParent() == null && applyColoredStatusBar(act, colorResID)) {
                    final View statusBar = new View(act);

                    vg.post(new Runnable() {
                        @Override
                        public void run() {

                            int statusBarHeight = (int) Math.ceil(25 * vg.getContext().getResources().getDisplayMetrics().density);
                            statusBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, statusBarHeight));
                            statusBar.setBackgroundColor(act.getResources().getColor(colorResID));
                            statusBar.setId(13371337);
                            vg.addView(statusBar, 0);
                        }
                    });
                    return statusBar;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    else if (act.getWindow() != null) {
        act.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        act.getWindow().setStatusBarColor(act.getResources().getColor(colorResID));
    }
    return null;
}

private static boolean applyColoredStatusBar( Activity act, int colorResID ) {
    final Window window = act.getWindow();
    final int flag;
    if (window != null) {
        View decor = window.getDecorView();
        if (decor != null) {
            flag = resolveTransparentStatusBarFlag(act);

            if (flag != 0) {
                decor.setSystemUiVisibility(flag);
                return true;
            }
            else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KitKat) {
                act.findViewById(Android.R.id.content).setFitsSystemWindows(false);
                setTranslucentStatus(window, true);
                final SystemBarTintManager tintManager = new SystemBarTintManager(act);
                tintManager.setStatusBarTintEnabled(true);
                tintManager.setStatusBarTintColor(colorResID);
            }
        }
    }
    return false;
}

public static int resolveTransparentStatusBarFlag( Context ctx ) {
    String[] libs = ctx.getPackageManager().getSystemSharedLibraryNames();
    String reflect = null;

    if (libs == null)
        return 0;

    final String SAMSUNG = "touchwiz";
    final String SONY = "com.sonyericsson.navigationbar";

    for (String lib : libs) {

        if (lib.equals(SAMSUNG)) {
            reflect = "SYSTEM_UI_FLAG_TRANSPARENT_BACKGROUND";
        }
        else if (lib.startsWith(SONY)) {
            reflect = "SYSTEM_UI_FLAG_TRANSPARENT";
        }
    }

    if (reflect == null)
        return 0;

    try {
        Field field = View.class.getField(reflect);
        if (field.getType() == Integer.TYPE) {
            return field.getInt(null);
        }
    } catch (Exception e) {
    }

    return 0;
}

@TargetApi(Build.VERSION_CODES.KitKat)
public static void setTranslucentStatus( Window win, boolean on ) {
    WindowManager.LayoutParams winParams = win.getAttributes();
    final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
    if (on) {
        winParams.flags |= bits;
    }
    else {
        winParams.flags &= ~bits;
    }
    win.setAttributes(winParams);
}
2
bapho

Marque Theme.AppCompa parent de style

<style name="AppTheme" parent="Theme.AppCompat">
     <item name="Android:colorPrimary">#005555</item>
     <item name="Android:colorPrimaryDark">#003333</item>
</style>

Et mettez getSupportActionBar().getThemedContext() dans onCreate().

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);
        getSupportActionBar().getThemedContext();
}
0
Ausama