2014-10-21 73 views
52

我正在开发一个简单的应用程序来测试材质设计。我使用com.android.support:appcompat-v7:21.0.0和我的活动是这样的:Android材质:状态栏颜色不会改变

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

我想:

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

现在我下面的材料管理准则定义我的主题:

public class MyActivity extends ActionBarActivity { 
    ... 
} 

为布局定义喜欢在Android 5之前更改状态栏颜色,并将其设置为colorPrimaryDark,但我找不到方法。我试着使用:

getWindow().setStatusBarColor(..) 

但setStatusBar颜色可从21级 为什么,如果我定义我的主题colorPrimaryDark和使用appcompact状态栏不变色? 任何人都可以提供帮助吗?

+1

似乎就像appcompat-v7中的一个bug。您是否介意在https://code.google.com/p/android/issues/list/上提交问题,以便我们跟踪该问题?请在问题中包含您的布局和样式XML。谢谢! – alanv 2014-10-21 23:00:01

+0

还应该有setStatusBarColor()的WindowCompat方法。随意在问题中提及或单独提出问题。 – alanv 2014-10-21 23:01:05

+0

Thx alanv为您的答案。我会在这个问题上进行更多的调查,检查我是否犯了错误,如果我找不到解决问题的方法。的 – FrancescoAzzola 2014-10-22 07:12:16

回答

59

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

+11

任何想法,为什么这并不5.0工作。 1? – Radu 2015-09-03 19:12:04

9

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

Android developers blog post

在旧平台上,程序兼容性模拟色彩主题化在可能的情况。目前这仅限于着色动作栏和一些小部件。

这意味着AppCompat lib将只在棒棒糖和以上的颜色状态栏。

+0

出于这个原因,它是强制性的(和它出现在其他的答案): 如果(Build.VERSION.SDK_INT> = Build.VERSION_CODES.LOLLIPOP){... – 2017-03-01 18:43:03

0

Theme.AppCompa吨风格父

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

而且在onCreate()getSupportActionBar().getThemedContext()

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

使用AppCompat时,请勿使用带有颜色的android:前缀。 – Michiel 2015-01-19 11:24:26

+0

此代码与问题无关。前缀用于API 21+,代码不做任何事情。 – 2015-07-19 19:22:48

+3

getter调用应该如何改变任何东西? – Ostkontentitan 2015-08-11 14:44:17

59

虽然着色状态栏不支持< 5.0,4.4,你可以使用周围的工作,实现了较深的颜色:

让状态栏半透明

<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的边缘案例解决方法的种类,但有雅去。

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

将此代码放入您的活动的onCreate方法中。这帮助了我。

8

切换到AppCompatActivity和工具栏上添加一个25 DP paddingTop和打开

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

然后,将工具栏上去顶顶部

+2

这将在API的工作19+只以上不工作 – Sniper 2016-03-21 19:06:43

-1

我知道这并不能回答这个问题,但与材料设计(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> 

诺蒂奇e android:statusBarColor,我们可以在其中定义颜色,否则使用默认值。

+0

为什么向下票呢? – Apostrofix 2015-11-18 07:22:16

+1

我建议这是因为“我知道这并不回答这个问题,但是......”,当问题明确说“我想在Android 5之前更改状态栏颜色...”时。你提交这个作为问题的答案,当它显然不是。不要抨击你,因为我意识到你*试图*是有帮助的,但希望这有助于你理解那里的问题,以便将来避免它。 – themightyjon 2015-11-30 14:57:38

2

此解决方案设置棒棒糖,奇巧和一些预棒棒糖设备(三星和索尼)的状态栏颜色。 该SystemBarTintManager是管理奇巧器件;)

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

正如其他人也提到的,这可以容易地通过加入以下所述的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库抽屉式导航时,implicityly覆盖状态栏的颜色,让你需要手动添加以下为它工作:

.withStatusBarColorRes(R.color.status_bar_color)