我创建了一个带有自定义视图的库,该视图在创建时会扩展布局。布局中的视图使用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)
[...]
布局inflater无法找到属性的值。当我试图通过代码获取属性时,它什么都不返回。该属性实际存在,只有它没有设置值,即使我已经明确设置了一个。
我应该如何设计我的图书馆风格?我几乎可以肯定我做的每一件事都和SublimePicker library一样,但它只是不起作用。这部分与ContextThemeWrapper略有不同,但它可能不是问题所在。我觉得我忘记了一个小东西,它使得属性没有价值,某些东西没有联系,我不知道。
我知道这是一个很长的问题,但它不能更简洁,我尽可能地简化了所有内容。我更改了上一版本问题中的大部分信息,使其完全不同。这两个答案现在根本不相关,而不是它们曾经是。赏金得到了自动奖励。
如果这可以帮助某些人,我可以将下载添加到我的实际项目中,但正如我所说,这个简化示例与我的项目具有完全相同的形式。
答案 0 :(得分:5)
这个答案是基于我对你和Vinayak B之间的问题和对话的理解。如果我曲解,请纠正我。
在地方应用程序和lib中,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>
lib 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);
}
因此,如果未在主要活动样式中覆盖或覆盖labelStyle
,它将采用默认labelStyle答案 1 :(得分:4)
这个答案是基于我从你的问题中理解的。如果我误解了 ,请纠正我。
首先,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
}
}
更新答案
更新问题的答案
首先,您尝试使用attr
从库中获取?attr/
值到您的项目。哪些不起作用。因为
您的项目使用Theme.AppCompat
主题作为(我猜测)您的活动的主题。在该活动中使用?attr
时,您只能获取Theme.AppCompat
的属性值。但您尝试获取的?attr/labelStyle
Theme.AppCompat
不是@style
的属性,而不是它的库属性。这就是你崩溃的原因。如果您想使用库中的任何样式到项目,可以使用 style="@style/labelStyle"
标记
例如
alertController.setValue(NSAttributedString(string: "test", attributes: [NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 15),NSAttributedStringKey.foregroundColor : UIColor.red]), forKey: "attributedTitle")
如果它不是您想要的,请分享您的源代码。所以我可以更多地了解这个问题。
答案 2 :(得分:0)
以下是我的猜测:我怀疑,尽管您在上面发布了<style>
标记,但是当您从库中进行膨胀时,该属性实际上并未定义,可能是因为您的图书馆项目正在使用带有“Context
的”在膨胀对话框时出现“糟糕的主题”。
?attr
语法表示变量的值是从上下文的主题中读取的,而不是从视图的样式或属性中读取的。来自Google开发博文:
这种?attr / format允许您从主题中提取任何属性,从而可以轻松地将主题整合到一个位置,并避免在多个文件中查找/替换。
因此,您必须确保处理膨胀上下文主题未定义此属性的情况,或者仅使用定义属性的主题来扩充此对话框。