web-dev-qa-db-fra.com

Lorsque vous utilisez ActionMode, la barre d'état devient noire sur Lollipop.

J'ai une barre d'état avec les éléments suivants dans le thème défini:

<!-- Base Theme for all "Material"-esque styles. We use NoActionBar
     so we can use the Toolbar at runtime.
-->
<style name="Material" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="Android:windowDrawsSystemBarBackgrounds">true</item>
    <item name="Android:windowTranslucentStatus">true</item>
    ...
</style>

J'ai également une DrawerLayout pour la plupart de mes activités, ce qui définit la couleur de la barre d'état à mon goût en utilisant:

    mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.myapp_green));

J'utilise une Toolbar, plutôt que la valeur par défaut ActionBar, de sorte qu'elle existe dans ma mise en page (c'est-à-dire que le tiroir de navigation dessine dessus).

Tout fonctionne bien, sauf que dans l'une de mes activités, j'ai un mode de sélection multiple avec un ActionMode. Lorsque cette ActionMode est activée (en appuyant longuement), elle recouvre la Toolbar en utilisant:

<item name="Android:windowActionModeOverlay">true</item>
<item name="windowActionModeOverlay">true</item>
<item name="actionModeStyle">@style/Material.Widget.ActionMode</item>

Le style Material.Widget.ActionMode est:

<style name="Material.Widget.ActionMode" parent="@style/Widget.AppCompat.ActionMode">
    <item name="Android:background">@color/myapp_green</item>
    <item name="background">@color/myapp_green</item>
</style>

Le problème est que, chaque fois que cela se produit, la barre d'état passe de la couleur myapp_green au noir. C'est presque comme si la translucidité de la barre d'état était désactivée (j'utilise Android 5.0). Je me demande comment je pourrais peut-être faire en sorte que ce problème ne se produise pas et que la couleur/la translucidité de la barre d'état reste telle quelle.

J'ai essayé d'ajouter <item name="Android:windowTranslucentStatus">true</item> aux styles du mode action, ainsi que d'ajouter <item name="Android:statusBarColor">@color/myapp_green</item> dans le style de ActionMode, les deux sans succès.

Mettre à jour:

Je me demande si cela a quelque chose à voir avec la façon débridée de définir l'arrière-plan de la barre d'état. Toutes mes classes d'activité proviennent de NavigationDrawerActivity.Java:

/**
 * An {@link Activity} that supports a Navigation Drawer, which is a pull-out panel for navigation
 * menus. This drawer is pulled out from the left side of the screen (right side on RTL devices).
 */
public class NavigationDrawerActivity extends ActionBarActivity
  implements AdapterView.OnItemClickListener {

  private static final String LOGTAG = NavigationDrawerActivity.class.getSimpleName();

  private DrawerLayout mDrawerLayout;
  private ListView mDrawerList;
  private LayoutInflater mInflater;
  private NavigationDrawerItemAdapter mAdapter;
  private ActionBarDrawerToggle mDrawerToggle;

  private NavigationDrawerItem[] mNavigationDrawerItems;

  private Toolbar mAppBar;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
// We have to call super.setContentView() here because BaseActivity redefines setContentView(),
// and we don't want to use that.
super.setContentView(R.layout.navigation_drawer);

mInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    setupNavigationDrawer();
  }

  @Override
  protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);

    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    return true;
  }

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    switch(id) {
      case Android.R.id.home:
        return mDrawerToggle.onOptionsItemSelected(item);
    }

    return super.onOptionsItemSelected(item);
  }

  /**
   * Toggles the state of the navigation drawer (i.e. closes it if it's open, and opens it if
   * it's closed).
   */
  public void toggleNavigationDrawer() {
    if (mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
      closeNavigationDrawer();
    } else {
      openNavigationDrawer();
    }
  }

  /**
   * Opens the navigation drawer.
   */
  public void openNavigationDrawer() {
    mDrawerLayout.openDrawer(GravityCompat.START);
  }

  /**
   * Closes the navigation drawer.
   */
  public void closeNavigationDrawer() {
    mDrawerLayout.closeDrawer(GravityCompat.START);
  }

  /**
   * Initializes items specific to the navigation drawer.
   */
  private void setupNavigationDrawer() {
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.wiw_green));

        mAppBar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(mAppBar);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setDisplayShowHomeEnabled(false);

        mDrawerToggle = new ActionBarDrawerToggle(
          this,                  /* Our context (Activity that hosts this drawer) */
          mDrawerLayout,         /* The DrawerLayout where the nav drawer will be drawn */
          R.string.drawer_open,  /* Description of "open drawer", for accessibility */
          R.string.drawer_close  /* Description of "close drawer", for accessibility */
        ) {

          /**
           * Called when a drawer has settled in a completely closed state.
           */
          public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
            supportInvalidateOptionsMenu();
          }

          /**
           * Called when a drawer has settled in a completely open state.
           */
          public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            supportInvalidateOptionsMenu();
          }
        };

        mDrawerList = (ListView) mDrawerLayout.findViewById(R.id.drawer_list);

        mNavigationDrawerItems = buildNavDrawerItemsList();

        setupAdapter(mNavigationDrawerItems);

        setupNavigationDrawerHeader();

        mDrawerLayout.setDrawerListener(mDrawerToggle);
        mDrawerList.setOnItemClickListener(this);
      }

      @Override
      public void onItemClick(AdapterView<?> parent, View aView, int aPosition, long aId) {
        // Code not relevant
      }

      /**
       * Set the inner content view of this {@link NavigationDrawerActivity} to have a given layout.
       *
       * @param aLayoutId The id of the layout to load into the inner content view of this activity.
       */
      public void setDrawerContent(int aLayoutId) {
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ViewGroup root = (ViewGroup)findViewById(R.id.drawer_content);
        inflater.inflate(aLayoutId, root);
      }  
    }

Je dois en fait exécuter DrawerLayout.setStatusBarBackgroundColor() pour que cela ait un effet. Le fait de changer colorPrimaryDark dans values-v21/styles.xml n'a aucun effet sur la barre d'état. Je pense que cela pourrait être la racine du problème ... Ces classes sont en train d'être converties d'un thème non matériel à un nouveau thème ressemblant à un matériau, alors je me demande si j'ai oublié quelque chose lors de la conversion en. colorPrimaryDark pour être reconnu correctement.

25
jwir3

Je poste une réponse ici car, alors que les autres solutions étaient utiles, aucune d’entre elles ne répondait exactement à la question. J'ai pu découvrir que l'appel à DrawerLayout.setStatusBarBackgroundColor() était à l'origine du problème. Ma solution est la suivante:

  1. Activez windowTranslucentStatus et windowDrawsSystemBarBackgrounds dans le thème principal.
  2. Supprimez l'appel de DrawerLayout.setStatusBarBackgroundColor() dans ma NavigationDrawerActivity, d'où proviennent toutes les classes Activity.
  3. Définissez les styles suivants dans mon thème de base values-v21/styles.xml:
 @ color/app_green 
 @ color/app_green 
 @ color/app_green_dark 
 @ color/app_green_dark 
? attr/colorPrimaryDark 
 ? attr/colorPrimaryDark 
  1. À l'intérieur de la classe NavigationDrawerActivity, dans sa méthode onCreate(), j'exécute ce qui suit (merci @Tinadm pour cette partie de la réponse): getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

  2. A l'intérieur de ma classe qui présente la ActionMode, j'ai ajouté les méthodes suivantes:

 @Override 
 Public boolean onPrepareActionMode (mode ActionMode, menu Menu) {
 If (Build.VERSION.SDK_INT> = Build.VERSION_CODES.Lollipop) {
 GetActivity () .getWindow (). clearFlags (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 
 // Ceci met en surbrillance la barre d'état et la distingue de la barre d'action, 
 // étant la barre d'action tant que Dans le mode Action, la couleur est app_green_dark 
 getActivity (). getWindow (). setStatusBarColor (getResources (). getColor (R.color.app_green_darker)); 
} 
 
 // Autres éléments ... 
 Renvoient true; 
} 
 
 @Override 
 Public void onDestroyActionMode (mode ActionMode) {
 mActionMode = null; 
 if (Build.VERSION.SDK_INT> = Build.VERSION_CODES.Lollipop) {
 getActivity (). getWindow (). addFlags (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STANSUS); 
 getActivity (). getWindo w (). setStatusBarColor (getResources (). getColor (R.color.app_green_dark)); 
} 
} 

La réactivation de la barre d'état translucide lorsque la ActionMode est détruite permet de dessiner mon tiroir de navigation sous la barre d'état. Il convient également de noter que la variable ActionMode superpose la barre d'action. Elle recouvre donc le tiroir de navigation si elle est retirée lorsque la variable ActionMode est activée (en effectuant un balayage de gauche à droite). Je vais désactiver cette fonctionnalité lorsque la ActionMode est activée, afin de ne pas dérouter les utilisateurs.

5
jwir3

bien votre solution temporaire est d'appeler ce code lorsque vous en avez le plus besoin ou lorsque le problème commence

if(Build.VERSION.SDK_INT == Build.VERSION_CODES.Lollipop){
    getWindow().setStatusBarColor(Color.BLUE); 
    // or Color.TRANSPARENT or your preferred color
}

MODIFIER

avez-vous essayé cela 

// actionMode.getCustomView().setBackgroundColor.(Color.TRANSPARENT);

@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {    
    //but this time you let the actionmode's view change the statusbar's
    // visibility
    actionMode.getCustomView().setSystemUiVisibility(
        View.SYSTEM_UI_FLAG_LOW_PROFILE); //or preferred one
    return true;
}

lorsque votre actionMode est détruite, la barre d'état est restaurée, donc remplacez-la également et redéfinissez la couleur de votre statusBar.

j'espère que ça aide

4
Elltz

J'ai rencontré le même problème il y a quelque temps et ma résolution était de définir et de restaurer la couleur de la barre d'état dans onCreateActionMode & onDestroyActionMode. 

//onCreateActionMode
mStartColor =  activity.getWindow().getStatusBarColor();
getWindow().setStatusBarColor(color);

//onDestroyActionMode
activity.getWindow().setStatusBarColor(mStartColor);

Bien sûr, vous devrez vérifier que c'est bien sur lolipop avant d'utiliser la méthode setStatusBarColor car ce n'est pas disponible avant L.

Extra: Si vous utilisez DrawerLayout, vous devez également lui attribuer le statusBarColor.

mDrawerLayout.setStatusBarBackground(new ColorDrawable(color));

J'espère que cela pourra aider!

3
zoltish

J'avais exactement le même problème que vous. J'ai réussi à le résoudre en utilisant une solution de contournement. 

  1. La première chose que j'ai faite a été de supprimer windowTranslucentStatus=true de mon thème.
  2. Ensuite, j'ai utilisé getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); pour que le contenu remplisse la zone située sous la barre d'état.
  3. J'ai mis <item name="Android:colorPrimaryDark">@color/primary_dark</item> où primary_dark est "# 51000000". Notez la valeur alpha pour obtenir la même transparence que celle fournie par windowTranslucent. Puisque ma barre d’outils est bleue, ma barre d’état est maintenant bleu foncé.
  4. Cela seul n'a pas résolu le problème. Lorsque le mode d'action est activé, la barre d'état était toujours noire dans mon cas. Mais maintenant, n'utilisant pas translucentStatusBar, je peux appliquer des couleurs à ma barre d'état, alors j'ai utilisé: 

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        getActivity().getWindow().setStatusBarColor(Color.parseColor("#026592"));
        return true;
    }
    

(Notez que la couleur que j'ai utilisée n'a pas d'alpha. Il s'agit de la couleur RVB qui correspond exactement à ma barre d'état semi-transparente bleu foncé).

2
Tinadm

En parcourant la documentation Android sur Les barres système translucides

Si vous créez un thème personnalisé, définissez l'un de ces thèmes (Theme.Holo.NoActionBar.TranslucentDecor et Theme.Holo.Light.NoActionBar.TranslucentDecor) comme thème parent ou incluez les propriétés de style windowTranslucentNavigation et windowTranslucentStatus dans votre thème.

Donc, si vous utilisez les bibliothèques de support, votre style doit étendre certains des styles AppCompat et utiliser à la fois windowTranslucentNavigation et windowTranslucentStatus sur votre ActionBarStyle.

1
Eduardo

Le problème pourrait être ici.

<item name="Android:background">@color/myapp_green</item>
<item name="background">@color/myapp_green</item>

"Android: background" est une syntaxe correcte, je ne pense pas que "background" l’appelle. Pourquoi avez-vous besoin de spécifier deux fois la couleur de fond? Retirez le second et ça devrait aller. Si non, alors j'espère que mes 2 cents ci-dessous sur le sujet des méthodes setBackgroundColor aident.

0,02 $

D'après mon expérience, j'ai constaté que de temps en temps la méthode setBackgroundColor() sous Android se comportait étrangement. Lorsque cela se produit, j'utilise plutôt setBackground() et spécifie la couleur sous une forme dessinable: getResources().getDrawable(R.color.xxxx). Je n'ai jamais su pourquoi cela résolvait des problèmes similaires à ceux que j'avais rencontrés dans le passé, mais j'ai utilisé cette solution de contournement jusqu'à présent sans aucun effet secondaire évident. Ce n'est peut-être pas la meilleure solution (surtout si vous définissez déjà un fond dessinable), mais c'est pratique quand rien d'autre ne semble fonctionner.

0
user3829751

J'ai eu le même problème et je l'ai résolu de la manière suivante

Le problème était de remplacer la même couleur pour toutes les vues. Mais je ne peux pas utiliser R.color.mycolor et Color.parseColor("#412848") m'a sauvé.

0
Karthika PB

Bien que j'utilisais les solutions précédentes précédemment, l'ajout d'un tiroir de navigation pose plus de problèmes, si vous voulez que le tiroir dessine derrière la barre système, et de nombreux problèmes liés à la définition et à la suppression des indicateurs de fenêtre ou à la couleur de la barre d'état (même les couleurs officielles). L'application Gmail a ces défauts!)

Voici la solution que j'utilise maintenant:

@Override
public void onSupportActionModeStarted(@NonNull ActionMode mode) {
    super.onSupportActionModeStarted(mode);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        // Post this so it ideally happens after the window decor callbacks.
        new Handler().post(new Runnable() {
            @Override
            public void run() {
                try {
                    final AppCompatDelegate delegate = getDelegate();
                    final Class clazz = Class.forName("Android.support.v7.app.AppCompatDelegateImplV7");
                    final Field mStatusGuardField = clazz.getDeclaredField("mStatusGuard");
                    mStatusGuardField.setAccessible(true);
                    final View mStatusGuard = (View) mStatusGuardField.get(delegate);
                    if (mStatusGuard != null) {
                        mStatusGuard.setBackgroundColor(/* Should match your desired status bar color when the action mode is showing, or alternatively you could use Color.TRANSPARENT here and just update the colors through getWindow().setStatusBarColor() below. The key is to avoid the black status guard from appearing. */);
                    }
                } catch (Exception e) {
                    /* Log or handle as desired. */
                }
            }
        });
        // Also set the status bar color. This is to avoid a momentary frame or 
        // two where the black will still be visible.
       getWindow().setStatusBarColor(/* Should match your desired status bar color when the action mode is showing. */);
    }
}

@Override
public void onSupportActionModeFinished(@NonNull ActionMode mode) {
    super.onSupportActionModeFinished(mode);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
        // Reset to the theme's colorPrimaryDark. This would normally result in 
        // the black status guard being seen momentarily, but because we set it 
        // to the same color as the action mode background, this intermediate 
        // state is not visible.
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
}

C’est évidemment un gros bidouillage, et cela n’anime pas exactement comme le fait la barre d’action contextuelle, mais c’est tout pour moi. Les accessoires à https://stackoverflow.com/a/38702953/1317564 pour avoir eu l'idée.

Notez que cela n’est nécessaire que si vous utilisez un tiroir de navigation ou si vous avez défini ces attributs dans votre fichier values-v21/theme.xml:

<item name="Android:windowDrawsSystemBarBackgrounds">true</item>
<item name="Android:statusBarColor">@Android:color/transparent</item>

Sinon, il suffira probablement d'appeler setStatusBarColor(...) dans onSupportActionModeStarted() et onSupportActionModeFinished() et c'est ce que je faisais avant d'ajouter un tiroir de navigation.

0
Learn OpenGL ES
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        super.onPrepareActionMode(mode, menu);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            Window w = getActivity().getWindow();
            w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            w.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        super.onDestroyActionMode(mode);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
            Window w = getActivity().getWindow();
            w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }
0
vusal.ahmadoglu