源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

分析Android多主题颜色的相关问题

  • 时间:2020-05-28 11:20 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:分析Android多主题颜色的相关问题
如果您通过以下的代码来获取定义的颜色值
context.getResources().getColor(R.color.some_color_resource_id);
在 Android Studio 中会有一个 lint 警告,提示您 [code]Resources#getColor(int)[/code] 在 [code]Marshmallow [/code]中被废弃了,建议使用主题可知的 [code]Resources#getColor(int, Theme[/code]) 函数。 为了避免该警告,则可以使用 [code]ContextCompat[/code]:
ContextCompat.getColor(context, R.color.some_color_resource_id);
该函数的实现是这样的:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 return context.getResources().getColor(id, context.getTheme());
} else {
 return context.getResources().getColor(id);
}
看起来很简单。但是为什么会这样呢? 为什么会开始使用带主题的函数而废弃之前的函数呢? [b]Resources#getColor(int) & Resources#getColorStateList(int) 的问题[/b] 首先来看看这两个被废弃的函数是干啥的:       – [code]Resources#getColor(int) [/code]返回一个资源 id 对应的颜色值,如果该资源为 [code]ColorStateList [/code]则返回 [code]ColorStateList [/code]的默认颜色值       –[code] Resources#getColorStateList(int) [/code]返回对应的 [code]ColorStateList[/code] [b]上面的代码在什么情况下会破坏我的代码呢?[/b] 要理解为何废弃这两个函数,来看个 ColorStateList 的例子。 当在 TextView 中使用自定义的 ColorStateList 的时候, TextView 不可用状态和可用状态的文字颜色分别使用 [code]R.attr.colorAccent[/code] 和 [code]R.attr.colorPrimary [/code]表示。 XHTML
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="?attr/colorAccent" android:state_enabled="false"/>
  <item android:color="?attr/colorPrimary"/>
</selector>
现在如果您通过如下的代码来获取这个[code]ColorStateList[/code]
ColorStateList csl = context.getResources().getColorStateList(R.color.button_text_csl);
上面的代码会抛出一个异常(查看logcat 可以看到如下的信息)
W/Resources: ColorStateList color/button_text_csl has unresolved theme attributes!
       Consider using Resources.getColorStateList(int, Theme)
       or Context.getColorStateList(int)
    at android.content.res.Resources.getColorStateList(Resources.java:1011)
    ...
[b]哪里出错了呢? [/b] 问题的根源在于 [code]Resources [/code]对象并没有和一个 [code]Theme [/code]对象关联,当使用 [code]R.attr.colorAccent [/code]和[code] R.attr.colorPrimary [/code]指代颜色的时候,在代码中通过上面的函数解析的时候没有指定对应的 Theme导致无法解析出结果。 所以在 [code]Marshmallow [/code]中添加了 [code]ColorStateList [/code]对 Theme 的支持并且添加了这两个新的函数:[code]Resources#getColor(int, Theme) [/code]和 [code]Resources#getColorStateList(int, Theme),[/code]并使用 Theme 参数来解析里面的 [code]attributes [/code]属性。 在新版本的 Support 库中也有对应的实现,分别位于 [code]ResourcesCompat [/code]和 [code]ContextCompat [/code]类中。 [b]如何解决该问题呢?[/b] 使用 AppCompat v24+ 版本可以很容易的解决该问题。
ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.button_text_csl);
在 23+ 版本上直接使用系统的函数,在之前的版本上 AppCompat 自己解析这些 xml 文件从里面提取 attr 属性指代的数值。 AppCompat 同时还支持 ColorStateList 新的 [code]android:alpha [/code]属性。 [b]Resources#getDrawable(int) 的问题[/b] [code]Resources#getDrawable(int) [/code]和前面的两个函数的问题是类似的。 在 Lollipop 之前的版本中无法支持 Theme attr 。 [b]为啥我这样用也没有出现异常呢?[/b] 异常并不总是会出现。 [code]VectorDrawableCompat[/code] 和 [code]AnimatedVectorDrawableCompat [/code]类中添加了和 [code]AppCompatResources [/code]类类似的功能。比如在 矢量图中你可以使用 [code]?attr/colorControlNormal [/code]来设置矢量图的颜色,[code]VectorDrawableCompat [/code]会自动完成解析该 属性的工作: XHTML
<vector 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:width="24dp"
  android:height="24dp"
  android:viewportWidth="24.0"
  android:viewportHeight="24.0"
  android:tint="?attr/colorControlNormal">
 
  <path
    android:pathData="..."
    android:fillColor="@android:color/white"/>
</vector>
[b]小测试[/b] 下面使用一个小测试来回顾一下前面介绍的内容。 假设有下面一个 ColorStateList: XHTML
<!-- res/colors/button_text_csl.xml -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:color="?attr/colorAccent" android:state_enabled="false"/>
  <item android:color="?attr/colorPrimary"/>
</selector>
在应用中定义了如下的 Theme: XHTML
<!-- res/values/themes.xml -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <item name="colorPrimary">@color/vanillared500</item>
  <item name="colorPrimaryDark">@color/vanillared700</item>
  <item name="colorAccent">@color/googgreen500</item>
</style>
 
<style name="CustomButtonTheme" parent="ThemeOverlay.AppCompat.Light">
  <item name="colorPrimary">@color/brown500</item>
  <item name="colorAccent">@color/yellow900</item>
</style>
在代码中有如下的函数用来解析颜色值并在代码中创建 ColorStateList:
@ColorInt
private static int getThemeAttrColor(Context context, @AttrRes int colorAttr) {
 TypedArray array = context.obtainStyledAttributes(null, new int[]{colorAttr});
 try {
  return array.getColor(0, 0);
 } finally {
  array.recycle();
 }
}
 
private static ColorStateList createColorStateList(Context context) {
 return new ColorStateList(
   new int[][]{
     new int[]{-android.R.attr.state_enabled}, // Disabled state.
     StateSet.WILD_CARD,            // Enabled state.
   },
   new int[]{
     getThemeAttrColor(context, R.attr.colorAccent), // Disabled state.
     getThemeAttrColor(context, R.attr.colorPrimary), // Enabled state.
   });
}
 看看是否能猜出在 API 19 和 API 23 版本上文字禁用状态和正常状态的颜色,实现代码如下(5和8的情况,在TextView xml 中指定了 [code]android:theme=”@style/CustomButtonTheme”[/code] ):
Resources res = ctx.getResources();
 
// (1)
int deprecatedTextColor = res.getColor(R.color.button_text_csl);
button1.setTextColor(deprecatedTextColor);
 
// (2)
ColorStateList deprecatedTextCsl = res.getColorStateList(R.color.button_text_csl);
button2.setTextColor(deprecatedTextCsl);
 
// (3)
int textColorXml = 
  AppCompatResources.getColorStateList(ctx, R.color.button_text_csl).getDefaultColor();
button3.setTextColor(textColorXml);
 
// (4)
ColorStateList textCslXml = AppCompatResources.getColorStateList(ctx, R.color.button_text_csl);
button4.setTextColor(textCslXml);
 
// (5)
Context themedCtx = button5.getContext();
ColorStateList textCslXmlWithCustomTheme =
  AppCompatResources.getColorStateList(themedCtx, R.color.button_text_csl);
button5.setTextColor(textCslXmlWithCustomTheme);
 
// (6)
int textColorJava = getThemeAttrColor(ctx, R.attr.colorPrimary);
button6.setTextColor(textColorJava);
 
// (7)
ColorStateList textCslJava = createColorStateList(ctx);
button7.setTextColor(textCslJava);
 
// (8)
Context themedCtx = button8.getContext();
ColorStateList textCslJavaWithCustomTheme = createColorStateList(themedCtx);
button8.setTextColor(textCslJavaWithCustomTheme);
下面是对应的实现截图: [img]http://files.jb51.net/file_images/article/201608/2016816100603592.png?201671610614[/img]   [b]总结 [/b] 以上就是关于分析Android多主题颜色的相关问题的全部内容,希望本文的内容对大家开发Android能有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部