web-dev-qa-db-ja.com

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を使用しているので、レイアウトに存在します(つまり、ナビゲーションドロワーがその上に描画されます)。

私のアクティビティの1つで、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>_を追加しようとしましたが、ActionModeのスタイルに_<item name="Android:statusBarColor">@color/myapp_green</item>_を追加しようとしましたが、どちらも成功しませんでした。

更新:

これは、ステータスバーの背景を設定するという奇妙な方法と関係があるのだろうか。私のアクティビティクラスはすべて、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);
      }  
    }
_

効果を得るには、実際にDrawerLayout.setStatusBarBackgroundColor()を実行する必要があります。 _values-v21/styles.xml_のcolorPrimaryDarkを変更するだけでは、ステータスバーには影響しません。これが問題の原因である可能性があると思います...これらのクラスは、非マテリアルテーマから新しいマテリアルのようなテーマに変換されているので、変換を行ったときに何かを見逃したのではないかと思います。 colorPrimaryDarkが正しく認識されるようにします。

25
jwir3

他の解決策は役に立ちましたが、どれも質問に正確に答えなかったので、ここに回答を投稿します。 DrawerLayout.setStatusBarBackgroundColor()の呼び出しが問題の原因であることがわかりました。私の解決策は次のとおりです。

  1. メインテーマでwindowTranslucentStatuswindowDrawsSystemBarBackgroundsを有効にします。
  2. すべてのNavigationDrawerActivityクラスの派生元であるActivity内のDrawerLayout.setStatusBarBackgroundColor()への呼び出しを削除します。
  3. _values-v21/styles.xml_ベーステーマで次のスタイルを設定します。
 @ color/app_green 
 @ color/app_green 
 @ color/app_green_dark 
 @ color/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を提示するクラス内に、次のメソッドを追加しました。

 @ Override 
 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)); 
} 
 
 //その他... 
 return true; 
} 
 
 @ Override 
 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()。getWindo w()。setStatusBarColor(getResources()。getColor(R.color.app_green_dark)); 
} 
} 

ActionModeが破棄されたときに半透明のステータスバーを再度有効にすると、ナビゲーションドロワーをステータスバーの下に描画できるようになります。 ActionModeはアクションバーをオーバーレイするため、ActionModeが有効になっているときに(左から右にスワイプして)引き出した場合、ナビゲーションドロワーがオーバーレイされることにも注意してください。 ActionModeが有効になっているときにこの機能を無効にして、ユーザーを混乱させないようにします。

5
jwir3

一時的な解決策は、最も必要なとき、または問題が発生したときにこのコードを呼び出すことです。

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の色を再設定します。

それが役に立てば幸い

4
Elltz

しばらく前に同じ問題が発生しました。解決策は、onCreateActionModeとonDestroyActionModeを設定し、ステータスバーの色を復元することでした。

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

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

もちろん、Lより前ではsetStatusBarColorメソッドを使用できないため、使用する前に、ロリポップでそれを確認する必要があります。

追加:DrawerLayoutを使用する場合は、statusBarColorも設定する必要があります。

mDrawerLayout.setStatusBarBackground(new ColorDrawable(color));

お役に立てば幸いです。

3
zoltish

私はあなたとまったく同じ問題を抱えていました。私は回避策を使用してそれを解決することができました。

  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」です。 windowTranslucentが提供するのと同じ透明度を実現するために、アルファ値に注意してください。ツールバーが青色なので、ステータスバーが濃い青色になりました。
  4. これだけでは問題は解決しませんでした。アクションモードがアクティブなとき、私の場合、ステータスバーはまだ黒でした。しかし今では、translucentStatusBarを使用せずに、ステータスバーに色を適用できるので、次を使用しました。

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

(使用した色にはアルファがないことに注意してください。これは、ダークブルーの半透明のステータスバーと完全に一致するRGB色です)。

2
Tinadm

Androidドキュメント 半透明のシステムバー

カスタムテーマを作成する場合は、これらのテーマの1つ(Theme.Holo.NoActionBar.TranslucentDecorおよびTheme.Holo.Light.NoActionBar.TranslucentDecor)を親テーマとして設定するか、テーマにwindowTranslucentNavigationおよびwindowTranslucentStatusスタイルプロパティを含めます。

したがって、サポートライブラリを使用している場合、スタイルはAppCompatスタイルの一部を拡張し、ActionBarStyleでwindowTranslucentNavigationとwindowTranslucentStatusの両方を使用する必要があります。

1
Eduardo

問題はここにあるかもしれません。

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

「Android:background」は適切な構文ですが、「background」は適切な構文ではないと思います。とにかく背景色を2回指定する必要があるのはなぜですか? 2番目のものを削除すると問題ないはずです。そうでない場合は、setBackgroundColorメソッドに関する以下の2セントがお役に立てば幸いです。

$ 0.02

私の経験では、AndroidのsetBackgroundColor()メソッドがおかしな動作をすることがあります。その場合は代わりにsetBackground()を使用します。描画可能な形式で色を指定します:getResources().getDrawable(R.color.xxxx)。これが過去に発生した同様の問題を解決した理由はわかりませんでしたが、これまでこの回避策を使用しましたが、明らかな副作用はありませんでした。最善の解決策ではありませんが(特に、背景の描画可能ファイルを既に設定している場合)、他に何も機能していないように見える場合に役立ちます。

0
user3829751

同じ問題が発生し、次の方法で解決しました

問題は、すべてのビューで同じ色をオーバーライドすることでした。しかし、_R.color.mycolor_を使用することができず、Color.parseColor("#412848")が私を救いました。

0
Karthika PB

以前に以前のソリューションを使用しましたが、ナビゲーションドロワーを追加するとき、ドロワーをシステムバーの後ろに描画する場合はさらに問題があり、ウィンドウフラグやステータスバーの色(公式の場合でも)の設定とクリアに関連する多くの不具合があります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()を呼び出すだけで機能する可能性があります。これは、ナビゲーションドロワーを追加する前に行っていたことです。

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