首页 文章

Android材质:状态栏颜色不会改变

提问于
浏览
53

我'm developing an simple app to test the material design. I'使用 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(..)

但是从第21级可以获得setStatusBar颜色 . 为什么我在我的主题中定义 colorPrimaryDark 并使用appcompact状态栏不会改变颜色?有人可以帮忙吗?

9 回答

  • 8

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

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

    然后,将工具栏放在顶部

  • 13

    此解决方案设置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);
    }
    
  • 9

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

  • -1

    虽然不支持着色状态栏<5.0,但在4.4中你可以使用一种解决方法来获得更暗的颜色:

    使状态栏保持半透明状态

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

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

    <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只有一种边缘情况解决方法,但是你去了 .

  • 39
    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 方法中 . 这对我有帮助 .

  • 0

    正如其他人也提到过的,可以通过将以下内容添加到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));
        }
    

    但是,我想在这里添加的重点是,在某些情况下,即使上面也不会改变状态栏颜色 . 例如,当使用MikePenz库导航抽屉时,它会明确地覆盖状态栏颜色,因此您需要手动添加以下内容才能使其工作:

    .withStatusBarColorRes(R.color.status_bar_color)

  • 2

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

    来自Android developers blog post

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

    这意味着AppCompat lib将仅对Lollipop及更高版本上的状态栏进行着色 .

  • 59

    使Theme.AppCompat样式为parent

    <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();
    }
    
  • 60

    我知道这不回答这个问题,但是使用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 ,我们可以在其中定义颜色,否则使用默认值 .

相关问题