使用动作模式时,状态栏在棒棒糖上变黑

我有一个状态栏,其中的主题设置如下:

<!-- 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颜色变成黑色。 这几乎就像状态栏半透明closures(我正在使用Android 5.0)。 我想知道如何能够得到这种行为不会发生,并保持状态栏颜色/半透明原样。

我尝试添加<item name="android:windowTranslucentStatus">true</item>到动作模式的样式,以及添加<item name="android:statusBarColor">@color/myapp_green</item> ActionMode的风格,都没有成功。

更新:

我想知道这是否与我设置状态栏背景的不可思议的方式有关。 我所有的Activity类都是从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()才能产生效果。 只需更改values-v21/styles.xml colorPrimaryDark对状态栏没有影响。 我觉得这可能是问题的根源…这些类正在从一个非物质主题转换到一个新的,类似于材料的主题,所以我想知道如果我错过了一些东西,当我做了转换colorPrimaryDark被正确识别。

Solutions Collecting From Web of "使用动作模式时,状态栏在棒棒糖上变黑"

我在这里发布答案,因为虽然其他解决scheme是有帮助的,但他们没有一个完全回答这个问题。 我能够发现,调用DrawerLayout.setStatusBarBackgroundColor()是造成麻烦。 我的解决scheme如下:

  1. 在主要主题中启用windowTranslucentStatuswindowDrawsSystemBarBackgrounds
  2. 移除我的NavigationDrawerActivity内的DrawerLayout.setStatusBarBackgroundColor()的调用,所有的Activity类都从中派生出来。
  3. 在我的values-v21/styles.xml基本主题中设置以下样式:
         @色/ app_green
         @色/ app_green
         @色/ app_green_dark
         @色/ app_green_dark
         ?ATTR / colorPrimaryDark
         ?ATTR / colorPrimaryDark
  1. NavigationDrawerActivity类的onCreate()方法内部,我执行下面的内容(谢谢@Tinadm的这部分答案): getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

  2. 在提供ActionMode类的ActionMode ,我添加了以下方法:

     @覆盖
     public boolean onPrepareActionMode(ActionMode mode,Menu menu){
       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))。。
       }

       // 其他的东西...
      返回true;
     }

     @覆盖
     public void onDestroyActionMode(ActionMode mode){
       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被启用时,我将禁用这个function,所以它不会混淆用户。

当你最需要的时候或者问题开始的时候,你的临时解决scheme就是调用这个代码

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

当你的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; } 

(请注意,我使用的颜色没有alpha,这是与我的深蓝色半透明状态栏完全匹配的RGB颜色)。

我刚才遇到同样的问题,我的解决scheme是在onCreateActionMode&onDestroyActionMode设置和恢复状态栏的颜色。

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

当然你需要在使用setStatusBarColor方法之前检查它是否在lolipop上,因为它不可用。

额外:如果你使用DrawerLayout你也需要设置statusBarColor。

 mDrawerLayout.setStatusBarBackground(new ColorDrawable(color)); 

希望有所帮助!

透过半透明系统栏上的Android文件

如果您要创build自定义主题,请将其中一个主题(Theme.Holo.NoActionBar.TranslucentDecor和Theme.Holo.Light.NoActionBar.TranslucentDecor)设置为父主题,或者在主题中包含windowTranslucentNavigation和windowTranslucentStatus样式属性。

因此,如果您使用支持库,则您的样式必须扩展一些AppCompat样式,并在您的ActionBarStyle上使用windowTranslucentNavigation和windowTranslucentStatus。

问题可能在这里。

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

“android:background”是一个合适的语法,我不认为“背景”是。 为什么你需要指定背景颜色两次吗? 删除第二个,应该没问题。 如果没有,那么我希望我的2分以下的setBackgroundColor方法的主题帮助。

$ 0.02

根据我的经验,我发现Android中的setBackgroundColor()方法不时performance奇怪。 当发生这种情况时,我使用setBackground()来代替,并以可绘制的forms指定颜色: getResources().getDrawable(R.color.xxxx) 。 我从来没有发现为什么这个问题解决了我过去的类似问题,但是我迄今为止使用了这个解决方法,没有任何明显的副作用。 这可能不是最好的解决scheme(尤其是如果你已经设置了一个可绘制的背景),但是当没有其他东西可以工作时,它就派上用场了。

我得到了同样的问题,我通过以下方式解决了这个问题

问题是覆盖所有views.But相同的颜色,但我无法去与R.color.mycolorColor.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); } } 

虽然我早些时候使用了以前的解决scheme,但是在添加抽屉式导航器时,如果您希望抽屉在系统栏后面绘制,以及与设置和清除窗口标志或状态栏颜色有关的许多小故障(即使是官方Gmail应用程序有这些毛刺!)

以下是我现在使用的解决scheme:

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

这显然是一个很大的破解,它不像上下文的动作栏那样animation,但它对我来说是个诀窍。 支持https://stackoverflow.com/a/38702953/1317564提出这个想法&#x3002;

请注意,只有在您使用导航抽屉时才需要,或者在values-v21 / theme.xml中设置以下属性:

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

否则,它可能会工作,只需在onSupportActionModeStarted()onSupportActionModeFinished()调用setStatusBarColor(...) onSupportActionModeFinished() ,这是我在添加导航抽屉之前所做的。