【问题标题】:Android Material: Status bar color won't changeAndroid Material:状态栏颜色不会改变
【发布时间】:2014-12-17 06:01:44
【问题描述】:

我正在开发一个简单的应用程序来测试材料设计。我正在使用com.android.support:appcompat-v7:21.0.0,我的活动看起来像:

public class MyActivity extends ActionBarActivity {
   ...
}

布局定义为:

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

现在我按照材料指南定义了我的主题:

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

我想在 Android 5 之前更改状态栏颜色并将其设置为colorPrimaryDark,但我找不到方法。我尝试使用:

getWindow().setStatusBarColor(..)

但是 setStatusBar 颜色从 21 级开始可用。 为什么如果我在主题中定义 colorPrimaryDark 并使用 appcompact 状态栏不会改变颜色? 有人可以帮忙吗?

【问题讨论】:

标签: android statusbar material-design


【解决方案1】:

状态栏是操作系统拥有的系统窗口。在 5.0 之前的 Android 设备上,应用程序无权更改其颜色,因此 AppCompat 库不支持旧平台版本。 AppCompat 可以做的最好的事情是为应用程序中的ActionBar 和其他常见的 UI 小部件着色提供支持。

【讨论】:

    【解决方案2】:

    虽然

    使状态栏半透明

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

    然后为您的应用栏使用 AppCompat 的工具栏,确保它适合系统窗口:

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

    确保将您的工具栏设置为活动的工具栏:

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

    工具栏在状态栏下方延伸,状态栏的半透明使其看起来是一种较暗的辅助颜色。如果这不是您想要的颜色,此组合可让您在状态栏下方放置一个显示您选择的背景颜色的视图(尽管状态栏仍将其染成较暗的颜色)。

    由于仅适用于 4.4,这是一种边缘情况的解决方法,但你去吧。

    【讨论】:

      【解决方案3】:
      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));
      }
      

      将此代码放入 Activity 的 onCreate 方法中。这对我有帮助。

      【讨论】:

        【解决方案4】:

        正如其他人也提到的,这可以通过在 Activity 的 onCreate() 中添加以下内容来轻松解决:

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

        但是,我想在这里补充的重要一点是,在某些情况下,即使是上述内容也不会改变状态栏的颜色。例如,在为 Navigation Drawer 使用 MikePenz 库时,它会隐式覆盖状态栏颜色,因此您需要手动添加以下内容才能使其工作:

        .withStatusBarColorRes(R.color.status_bar_color)

        【讨论】:

          【解决方案5】:

          AppCompat v7:21.0.0 不支持状态栏着色。

          来自Android developers blog post

          在旧平台上,AppCompat 会尽可能模拟颜色主题。目前这仅限于为操作栏和一些小部件着色。

          这意味着 AppCompat 库只会在 Lollipop 及更高版本上为状态栏着色。

          【讨论】:

          • 因此,它是强制性的(它出现在其他答案中): if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {...
          【解决方案6】:

          切换到 AppCompatActivity 并在工具栏上添加一个 25 dp 的 paddingTop 并打开

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

          然后,将工具栏向上顶

          【讨论】:

          • 这只能在 API 19+ 上工作,因为上面不起作用
          【解决方案7】:

          此解决方案设置 Lollipop、Kitkat 和一些前 Lollipop 设备(三星和索尼)的状态栏颜色。 SystemBarTintManager 正在管理 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);
          }
          

          【讨论】:

            【解决方案8】:

            我知道这不能回答问题,但是使用 Material Design (API 21+) 我们可以通过在 styles.xml 的主题声明中添加这一行来更改状态栏的颜色:

            <!-- MAIN THEME -->
            <style name="AppTheme" parent="@android:style/Theme.Material.Light">
                <item name="android:actionBarStyle">@style/actionBarCustomization</item>
                <item name="android:spinnerDropDownItemStyle">@style/mySpinnerDropDownItemStyle</item>
                <item name="android:spinnerItemStyle">@style/mySpinnerItemStyle</item>
                <item name="android:colorButtonNormal">@color/myDarkBlue</item>
                <item name="android:statusBarColor">@color/black</item>
            </style>
            

            注意android:statusBarColor,我们可以在这里定义颜色,否则使用默认值。

            【讨论】:

            • 我建议这是因为“我知道这并不能回答问题,但是......”,当问题明确表示“我想更改 Android 前的状态栏颜色5……”。您将此作为问题的答案提交,但显然不是。不是在抨击你,因为我知道你试图提供帮助,但希望这能帮助你理解那里的问题,以便你以后避免它。
            【解决方案9】:

            制作Theme.AppCompat 样式父

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

            并将getSupportActionBar().getThemedContext() 放入onCreate()

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

            【讨论】:

            • 在使用 AppCompat 时,不要在颜色中使用 android: 前缀。
            • 这段代码与问题无关。前缀适用于 API 21+,代码不执行任何操作。
            • getter 调用应该如何改变任何东西?
            【解决方案10】:

            **

            顽皮棒棒糖的解决方案

            **

            你好,我遇到了比我的颜色更深的问题...所以这是避免使用 TranslucentStatus 解决方案的状态栏后面的阴影的解决方案...

            所以在你所有的 java 活动中你都需要这个:

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

            您需要在您的styles.xml 中设置背景颜色(此颜色将是您的状态栏颜色):

            <style name="AppCompat" parent="Theme.AppCompat">
                <item name="android:colorBackground">@color/YOUR_STATUS_BAR_COLOR</item>
            </style>
            

            在所有布局中,您都需要添加作为背景的布局:

            <LinearLayout
                android:background="@color/YOUR_BACKGROUND_COLOR"
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="bottom"
                />
            

            当然,如果您想使用 @color/just name... 您需要在 colors.xml 中进行设置:

            <color name="YOUR_STATUS_BAR_COLOR">#cf031c</color>
            <color name="YOUR_BACKGROUND_COLOR">#383838</color>
            

            这是我们如何做到这一点的整个过程:Whats the right approach to create or change color of a status bar?

            【讨论】:

              猜你喜欢
              • 2017-03-05
              • 2022-11-28
              • 2015-11-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-03
              • 2016-05-23
              相关资源
              最近更新 更多