При использовании ActionMode строка состояния становится черной на Lollipop

У меня есть строка состояния со следующим в теме, установленной на ней:

<!-- 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> 

У меня также есть DrawerLayout для большинства моих действий, который устанавливает цвет строки состояния по своему вкусу, используя:

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

Я использую Toolbar , а не ActionBar по умолчанию, поэтому он существует в моем макете (т. Е. Ящик навигации рисует поверх него).

Все работает отлично, за исключением того, что в одном из моих действий у меня есть режим множественного выбора с ActionMode . Когда этот ActionMode активирован (используя длительное нажатие), он накладывает Toolbar используя:

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

Стиль Material.Widget.ActionMode :

 <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> 

Проблема в том, что всякий раз, когда это происходит, строка состояния переходит от цвета myapp_green к черному. Это почти так, как если бы прозрачность состояния была отключена (я использую Android 5.0). Мне интересно, как я могу заставить это поведение не произойти, а также сохранить цвет / полупрозрачность строки состояния как есть.

Я попытался добавить в стиль режима действия <item name="android:windowTranslucentStatus">true</item> , а также добавить <item name="android:statusBarColor">@color/myapp_green</item> в Стиль для ActionMode , оба без успеха.

Обновить:

Интересно, связано ли это с неуклюжим способом, который я устанавливаю на фоне строки состояния. Все мои классы активности происходят из 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 (ie 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); } } 

Мне действительно нужно запустить DrawerLayout.setStatusBarBackgroundColor() чтобы он имел эффект. Просто изменение colorPrimaryDark в values-v21/styles.xml не влияет на строку состояния. Я чувствую, что это может быть причиной проблемы … Эти классы преобразуются из темы, отличной от материала, в новую, подобную материалу тему, поэтому мне интересно, пропустил ли я что-то, когда я сделал переход на colorPrimaryDark который будет распознан правильно.

Solutions Collecting From Web of "При использовании ActionMode строка состояния становится черной на Lollipop"

Я пишу здесь ответ, потому что, хотя другие решения были полезны, никто из них не ответил на вопрос точно. Я смог узнать, что вызов DrawerLayout.setStatusBarBackgroundColor() вызывал проблемы. Мое решение таково:

  1. Включите windowTranslucentStatus и windowDrawsSystemBarBackgrounds в основной теме.
  2. Удалите вызов DrawerLayout.setStatusBarBackgroundColor() внутри моей NavigationDrawerActivity , из которого производятся все классы Activity .
  3. Задайте следующие стили в моих values-v21/styles.xml :
         @ Цвет / app_green
         @ Цвет / app_green
         @ Цвет / app_green_dark
         @ Цвет / app_green_dark
         ? Атр / colorPrimaryDark
         ? Атр / colorPrimaryDark
  1. Внутри класса NavigationDrawerActivity в его onCreate() я выполняю следующее (спасибо @Tinadm для этой части ответа): getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

  2. Внутри моего класса, который представляет ActionMode , я добавил следующие методы:

     @Override
     Public boolean onPrepareActionMode (режим ActionMode, меню меню) {
       If (Build.VERSION.SDK_INT> = Build.VERSION_CODES.LOLLIPOP) {
         .. GetActivity () GetWindow () clearFlags (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
         // Чтобы выделить строку состояния и отличить ее от панели действий,
         // поскольку панель действия в режиме действия цветна app_green_dark
         getActivity () GetWindow () setStatusBarColor (GetResources () GetColor (R.color.app_green_darker).)..;
       }

       // Другие вещи...
       Return true;
     }

     @Override
     Public void onDestroyActionMode (режим ActionMode) {
       MActionMode = null;
       If (Build.VERSION.SDK_INT> = Build.VERSION_CODES.LOLLIPOP) {
         .. GetActivity () GetWindow () addFlags (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
         getActivity () GetWindow () setStatusBarColor (GetResources () GetColor (R.color.app_green_dark).)..;
       }
     }

Повторное включение полупрозрачной строки состояния при уничтожении ActionMode позволяет сделать мой навигационный ящик под строкой состояния. Также стоит отметить, что ActionMode накладывает панель действий, поэтому он будет накладывать навигационный ящик, если он ActionMode , когда включен ActionMode (путем прокрутки слева направо). Я ActionMode эту функцию, когда ActionMode включен, поэтому он не путает пользователей.

Хорошо ваше временное решение вызывает этот код, когда вам это больше всего нужно или когда проблема начинается

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

РЕДАКТИРОВАТЬ

Вы пробовали это

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

,

 @Override public boolean onPrepareActionMode(ActionMode mode, 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; } 

Когда ваш ActionMode будет уничтожен, строка состояния будет восстановлена, поэтому переопределите это и снова установите цвет statusBar.

Надеюсь, поможет

У меня была такая же проблема, как и вы. Мне удалось решить это с помощью обходного пути.

  1. Первое, что я сделал, это удалить windowTranslucentStatus=true из моей темы;
  2. Затем я использовал getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); Чтобы содержимое заполнило область под строкой состояния.
  3. Я установил <item name="android:colorPrimaryDark">@color/primary_dark</item> где primary_dark – «# 51000000». Обратите внимание на значение alpha для достижения той же прозрачности, что и windowTranslucent. Поскольку моя панель инструментов синяя, моя строка состояния теперь синяя.
  4. Это само по себе не решило проблему. Когда режим действия активен, в моем случае строка состояния по-прежнему оставалась черной. Но теперь, не используя translucentStatusBar, я могу применить цвета к своей строке состояния, поэтому я использовал:

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

(Обратите внимание, что цвет, который я использовал, не имеет альфы. Это цвет RGB точно соответствует моей синей полупрозрачной строке состояния).

Некоторое время назад я столкнулся с одной проблемой, и моя резолюция заключалась в том, что в onCreateActionMode & onDestroyActionMode установлен и восстанавливается цвет статусной панели.

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

Конечно, вам нужно проверить, что его на lolipop, прежде чем использовать метод setStatusBarColor как его недоступный pre L.

Дополнительно: Если вы используете DrawerLayout, вам также нужно установить statusBarColor.

 mDrawerLayout.setStatusBarBackground(new ColorDrawable(color)); 

Надеюсь, это поможет!

Просмотр документации Android на прозрачных системных барах

Если вы создаете настраиваемую тему, установите одну из этих тем (Theme.Holo.NoActionBar.TranslucentDecor и Theme.Holo.Light.NoActionBar.TranslucentDecor) в качестве родительской темы или включите свойства стиля windowTranslucentNavigation и windowTranslucentStatus в своей теме.

Поэтому, если вы используете библиотеки поддержки, ваш стиль должен расширять некоторые стили AppCompat и использовать как windowTranslucentNavigation, так и windowTranslucentStatus на вашем ActionBarStyle.

Проблема может быть здесь.

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

«Андроид: фон» – это правильный синтаксис, я не думаю, что «фон» есть. Почему вам нужно указать цвет фона дважды? Удалите второй, и все должно быть хорошо. Если нет, то я надеюсь, что мои 2 цента ниже по теме методов setBackgroundColor помогут.

$ 0,02

По моему опыту, я обнаружил, что время от времени setBackgroundColor() в Android ведет себя странно. Когда это произойдет, вместо этого я использую setBackground() и setBackground() цвет в выпадающей форме: getResources().getDrawable(R.color.xxxx) . Я никогда не узнавал, почему это разрешило подобные проблемы, которые у меня были в прошлом, но я использовал этот обходной путь до сих пор без каких-либо очевидных побочных эффектов. Это может быть не лучшее решение (особенно если вы уже устанавливаете фоновый рисунок), но это пригодится, когда больше ничего не работает.

У меня такая же проблема, и я решил ее следующим образом

Проблема заключалась в том, чтобы переопределить один и тот же цвет для всех просмотров. Но я не могу пойти с R.color.mycolor и Color.parseColor("#412848") меня спас.

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

Хотя раньше я использовал предыдущие решения, при добавлении переносного ящика возникает больше проблем, если вы хотите, чтобы ящик рисовал за системной панелью, и так много сбоев, связанных с установкой и очисткой флагов окна или цветом строки состояния (даже официальные Приложение Gmail имеет эти сбои!)

Вот решение, которое я использую сейчас:

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

Это, очевидно, большой взлом, и он не оживляет точно так же, как это делает контекстная панель действий, но это делает трюк для меня. Подпишитесь на https://stackoverflow.com/a/38702953/1317564, чтобы придумать эту идею.

Обратите внимание, что это необходимо только в том случае, если вы используете ящик навигации или иначе эти атрибуты установлены в ваших значениях-v21 / theme.xml:

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

В противном случае, вероятно, будет работать только вызов setStatusBarColor(...) в onSupportActionModeStarted() и onSupportActionModeFinished() , и это то, что я делал перед добавлением навигационного ящика.