库的样式属性没有值,即使它们已明确设置
Library's style attributes have no values even though they are explicitly set
我制作了一个带有自定义视图的库,该视图在创建时会扩充布局。布局中的视图使用 style="?attr/labelStyle"
或任何其他属性设置样式。
属性声明为库的attrs.xml
:
<attr name="myViewStyle" format="reference"/>
<declare-styleable name="MyView">
<attr name="labelStyle" format="reference|color"/>
</declare-styleable>
我已经在库的 styles.xml
:
中为此属性设置了默认值
<style name="MyViewStyle">
<item name="labelStyle">@style/LabelStyle</item>
</style>
<style name="LabelStyle">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="...">...</item>
</style>
最后在图书馆的 themes.xml
:
<style name="MyViewStyleLight" parent="Theme.AppCompat.Light">
<item name="myViewStyle">@style/MyViewStyle</item>
</style>
现在这是库的默认样式,但它在主项目中被覆盖了 styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="myViewStyle">@style/MyViewStyleCustom</item>
</style>
<style name="MyViewStyleCustom" parent="MyViewStyleLight">
<item name="android:textColor">@color/gray</item>
<item name="...">...</item>
</style>
自定义视图代码:
public MyView(Context context) {
this(context, null, R.attr.myViewStyle, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.myViewStyle, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(createThemeWrapper(context, R.attr.myViewStyle, R.style.MyViewStyleLight),
attrs, defStyleAttr, defStyleRes);
initLayout();
}
private static Context createThemeWrapper(Context context, int styleAttr, int defaultStyle) {
final TypedArray ta = context.obtainStyledAttributes(new int[]{styleAttr});
int style = ta.getResourceId(0, defaultStyle);
ta.recycle();
return new ContextThemeWrapper(context, style);
}
private void initLayout() {
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.my_view, this);
...
}
我在下面解释一下 ContextThemeWrapper。现在应用程序在布局膨胀的那一行崩溃了。这是崩溃日志的重要部分:
android.view.InflateException: Binary XML file line #0: Binary XML file line #0: Error inflating class com.example.MyView
at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
[...]
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f030057 a=-1}
at android.content.res.TypedArray.getDrawable(TypedArray.java:867)
[...]
布局充气器找不到属性值。当我试图通过代码获取属性时,它 returns 什么都没有。该属性确实存在,只是它没有设置值,即使我已经明确设置了一个。
我应该如何为我的图书馆设计风格?我几乎可以肯定,我所做的每件事都与 SublimePicker library 相同,但它就是行不通。与 ContextThemeWrapper 的部分略有不同,但这可能不是问题所在。感觉好像忘记了什么地方的一个小东西,使得属性没有值,东西没有连接,我不知道。
我知道这是一个很长的问题,但是再简洁不过了,我尽可能地简化了一切。我更改了以前版本问题中的大部分信息,使其完全不同。这两个答案现在根本不相关,过去也不相关。赏金已自动奖励
如果这对某人有帮助,我可以将下载添加到我的实际项目中,但正如我所说,这个简化示例与我的项目具有完全相同的形式。
这个答案是基于我从你的问题中了解到的。如果我误解了
,请指正。
首先 myTextColor
是您库中的属性名称。不是属性值。当你使用这个库时,你应该给 myTextColor
一个值。否则可能会出现 'InflateException'
。您可以通过以下方式避免这种情况。
<YourCustomeView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:myTextColor="#000"/>
1。库外使用直接设置myTextColor
值
OR
在您使用此 myTextColor
属性的库中,检查此属性是否具有值。如果它没有任何值,则使用 myTextColor
的默认值
private void init(@Nullable AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes(attrs,
R.styleable.MyLibrary);
boolean hasRawRes = ta.hasValue(R.styleable.myTextColor);
if(hasRawRes){
// Use `myTextColor` attr here
}else{
// use default color
}
}
UPDATE ANSWER
这个更新问题的答案
首先,您尝试使用 ?attr/
从您的库中获取一个 attr
值到您的项目中。这不会起作用。因为
您的项目使用 Theme.AppCompat
主题作为(我猜)您活动的父主题。当你在 activity 中使用 ?attr
时,你只能获取 Theme.AppCompat
的属性值。但是您正在尝试获取 ?attr/labelStyle
这不是 Theme.AppCompat
的属性,而不是您的库属性。这就是你遇到崩溃的原因。如果您想将您的库中的任何样式用于您的项目,您可以使用 @style
标签
例如
style="@style/labelStyle"
如果这不是你要找的,请分享你的来源code.So我可以了解更多关于这个问题的信息。
这是我的猜测:我怀疑,尽管 <style>
在上面标记了你 post,但从你的库中膨胀时实际上没有定义该属性,可能是因为你的库项目正在使用 Context
在展开对话框时使用 "bad" 主题。
?attr
语法意味着变量的值是从上下文的 主题 中读取的,而不是从视图的样式或属性中读取的。来自 Google 开发者博客 post:
This ?attr/ format allows you to pull any attribute out of your theme, making it easy to consolidate your theming into a single place and avoid finding/replacing across many files.
因此,您必须确保处理扩充上下文主题未定义此属性的情况,或者仅使用定义该属性的主题来扩充此对话框。
这个答案是基于我从你的问题和你与 Vinayak B 的对话中了解到的。如果我理解有误,请纠正我。
style.xml 在应用程序和库中存在差异。另外,我已经删除了 theme.xml 以及 MyView.java 的默认样式
的构造函数的更改
我更改了以下内容
在主项目中覆盖styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="myViewStyle">@style/MyViewStyleCustom</item>
</style>
<style name="MyViewStyleCustom" parent="MyViewStyle">
<item name="labelStyle">@style/LabelStyle123</item>
</style>
<style name="LabelStyle123">
<item name="android:textColor">#f00</item>
</style>
库styles.xml
<resources>
<style name="MyViewStyle">
<item name="labelStyle">@style/LabelStyle</item>
<item name="TextStyle">@style/textStyle</item>
</style>
<style name="LabelStyle">
<item name="android:textColor">#00f</item>
</style>
<style name="textStyle">
<item name="android:textColor">#009</item>
</style>
</resources>
MyView.java - 如果应用程序没有任何属性,则更改构造函数并设置默认 MyViewStyle。
public MyView(Context context) {
this(context, null, R.attr.myViewStyle, R.style.MyViewStyle);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.myViewStyle, R.style.MyViewStyle);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, R.style.MyViewStyle);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(createThemeWrapper(context, defStyleAttr,defStyleRes), attrs, defStyleAttr, defStyleRes);
initLayout();
}
private static Context createThemeWrapper(Context context, int styleAttr, int defaultStyle) {
final TypedArray ta = context.obtainStyledAttributes(new int[]{styleAttr});
int style1 = ta.getResourceId(0, defaultStyle);
ta.recycle();
return new ContextThemeWrapper(context, style1);
}
因此,如果未在主要 activity 样式中覆盖它,它将采用默认的 labelStyle 或覆盖 labelStyle
我制作了一个带有自定义视图的库,该视图在创建时会扩充布局。布局中的视图使用 style="?attr/labelStyle"
或任何其他属性设置样式。
属性声明为库的attrs.xml
:
<attr name="myViewStyle" format="reference"/>
<declare-styleable name="MyView">
<attr name="labelStyle" format="reference|color"/>
</declare-styleable>
我已经在库的 styles.xml
:
<style name="MyViewStyle">
<item name="labelStyle">@style/LabelStyle</item>
</style>
<style name="LabelStyle">
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="...">...</item>
</style>
最后在图书馆的 themes.xml
:
<style name="MyViewStyleLight" parent="Theme.AppCompat.Light">
<item name="myViewStyle">@style/MyViewStyle</item>
</style>
现在这是库的默认样式,但它在主项目中被覆盖了 styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="myViewStyle">@style/MyViewStyleCustom</item>
</style>
<style name="MyViewStyleCustom" parent="MyViewStyleLight">
<item name="android:textColor">@color/gray</item>
<item name="...">...</item>
</style>
自定义视图代码:
public MyView(Context context) {
this(context, null, R.attr.myViewStyle, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.myViewStyle, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(createThemeWrapper(context, R.attr.myViewStyle, R.style.MyViewStyleLight),
attrs, defStyleAttr, defStyleRes);
initLayout();
}
private static Context createThemeWrapper(Context context, int styleAttr, int defaultStyle) {
final TypedArray ta = context.obtainStyledAttributes(new int[]{styleAttr});
int style = ta.getResourceId(0, defaultStyle);
ta.recycle();
return new ContextThemeWrapper(context, style);
}
private void initLayout() {
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.my_view, this);
...
}
我在下面解释一下 ContextThemeWrapper。现在应用程序在布局膨胀的那一行崩溃了。这是崩溃日志的重要部分:
android.view.InflateException: Binary XML file line #0: Binary XML file line #0: Error inflating class com.example.MyView
at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
[...]
Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 13: TypedValue{t=0x2/d=0x7f030057 a=-1}
at android.content.res.TypedArray.getDrawable(TypedArray.java:867)
[...]
布局充气器找不到属性值。当我试图通过代码获取属性时,它 returns 什么都没有。该属性确实存在,只是它没有设置值,即使我已经明确设置了一个。
我应该如何为我的图书馆设计风格?我几乎可以肯定,我所做的每件事都与 SublimePicker library 相同,但它就是行不通。与 ContextThemeWrapper 的部分略有不同,但这可能不是问题所在。感觉好像忘记了什么地方的一个小东西,使得属性没有值,东西没有连接,我不知道。
我知道这是一个很长的问题,但是再简洁不过了,我尽可能地简化了一切。我更改了以前版本问题中的大部分信息,使其完全不同。这两个答案现在根本不相关,过去也不相关。赏金已自动奖励
如果这对某人有帮助,我可以将下载添加到我的实际项目中,但正如我所说,这个简化示例与我的项目具有完全相同的形式。
这个答案是基于我从你的问题中了解到的。如果我误解了 ,请指正。
首先 myTextColor
是您库中的属性名称。不是属性值。当你使用这个库时,你应该给 myTextColor
一个值。否则可能会出现 'InflateException'
。您可以通过以下方式避免这种情况。
<YourCustomeView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:myTextColor="#000"/>
1。库外使用直接设置myTextColor
值
OR
在您使用此
的默认值myTextColor
属性的库中,检查此属性是否具有值。如果它没有任何值,则使用myTextColor
private void init(@Nullable AttributeSet attrs) { TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.MyLibrary); boolean hasRawRes = ta.hasValue(R.styleable.myTextColor); if(hasRawRes){ // Use `myTextColor` attr here }else{ // use default color }
}
UPDATE ANSWER
这个更新问题的答案
首先,您尝试使用 ?attr/
从您的库中获取一个 attr
值到您的项目中。这不会起作用。因为
您的项目使用 Theme.AppCompat
主题作为(我猜)您活动的父主题。当你在 activity 中使用 ?attr
时,你只能获取 Theme.AppCompat
的属性值。但是您正在尝试获取 ?attr/labelStyle
这不是 Theme.AppCompat
的属性,而不是您的库属性。这就是你遇到崩溃的原因。如果您想将您的库中的任何样式用于您的项目,您可以使用 @style
标签
例如
style="@style/labelStyle"
如果这不是你要找的,请分享你的来源code.So我可以了解更多关于这个问题的信息。
这是我的猜测:我怀疑,尽管 <style>
在上面标记了你 post,但从你的库中膨胀时实际上没有定义该属性,可能是因为你的库项目正在使用 Context
在展开对话框时使用 "bad" 主题。
?attr
语法意味着变量的值是从上下文的 主题 中读取的,而不是从视图的样式或属性中读取的。来自 Google 开发者博客 post:
This ?attr/ format allows you to pull any attribute out of your theme, making it easy to consolidate your theming into a single place and avoid finding/replacing across many files.
因此,您必须确保处理扩充上下文主题未定义此属性的情况,或者仅使用定义该属性的主题来扩充此对话框。
这个答案是基于我从你的问题和你与 Vinayak B 的对话中了解到的。如果我理解有误,请纠正我。
style.xml 在应用程序和库中存在差异。另外,我已经删除了 theme.xml 以及 MyView.java 的默认样式
的构造函数的更改我更改了以下内容
在主项目中覆盖styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light"> <item name="myViewStyle">@style/MyViewStyleCustom</item> </style> <style name="MyViewStyleCustom" parent="MyViewStyle"> <item name="labelStyle">@style/LabelStyle123</item> </style> <style name="LabelStyle123"> <item name="android:textColor">#f00</item> </style>
库styles.xml
<resources> <style name="MyViewStyle"> <item name="labelStyle">@style/LabelStyle</item> <item name="TextStyle">@style/textStyle</item> </style> <style name="LabelStyle"> <item name="android:textColor">#00f</item> </style> <style name="textStyle"> <item name="android:textColor">#009</item> </style> </resources>
MyView.java - 如果应用程序没有任何属性,则更改构造函数并设置默认 MyViewStyle。
public MyView(Context context) { this(context, null, R.attr.myViewStyle, R.style.MyViewStyle); } public MyView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, R.attr.myViewStyle, R.style.MyViewStyle); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { this(context, attrs, defStyleAttr, R.style.MyViewStyle); } public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(createThemeWrapper(context, defStyleAttr,defStyleRes), attrs, defStyleAttr, defStyleRes); initLayout(); } private static Context createThemeWrapper(Context context, int styleAttr, int defaultStyle) { final TypedArray ta = context.obtainStyledAttributes(new int[]{styleAttr}); int style1 = ta.getResourceId(0, defaultStyle); ta.recycle(); return new ContextThemeWrapper(context, style1); }
因此,如果未在主要 activity 样式中覆盖它,它将采用默认的 labelStyle 或覆盖 labelStyle