如果你想设置你从代码创建的Button的样式,你必须做这样的事情;
Button btn = new Button (mActivity, null, R.attr.someattribute);
在attrs.xml中,您设置了一个引用
<attr name="someStyleRef" format="reference"/>
在styles.xml中,您可以定义主题
<resources>
<style name="Theme.SomeTheme" parent="android:style/Theme.Black">
<item name="someStyleRef">@style/someStyle</item>
</style>
</resources>
styles.xml中的lates定义为例如
<style name="someStyle">
<item name="android:layout_width">2px</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:background">@drawable/actionbar_compat_separator</item>
</style>
这是有效的,根据我的理解,这是从Android中的代码在视图上设置样式的方法。这似乎过于复杂。按钮的第三个构造函数Argument可以很容易地接受样式ID R.style.XXX
有谁能解释为什么需要这种额外的复杂性?
答案 0 :(得分:65)
它与使用Views的Android中的鼓励模式有关。这不是您想要做的事情的预期方法。首先,我将解释这种机制的用途,然后为您的应用建议一种方法。
获取attr资源的View构造函数的第三个参数通常在实现View子类时使用,如您所示,允许您指定一个theme属性作为View的默认样式的引用。如果你有一个名为AwesomeButton的特殊按钮,你可以实现它的构造函数:
public class AwesomeButton extends Button {
public AwesomeButton(Context context) {
this(context, null);
}
public AwesomeButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.awesomeButtonStyle);
}
public AwesomeButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr) {
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.AwesomeButton, defStyleAttr, 0);
// Read AwesomeButton-specific style attributes from a
a.recycle();
}
// More code
}
当Android的LayoutInflater
膨胀视图时,它使用带有参数(Context, AttributeSet)
的2参数构造函数。 R.attr常量传递给3参数版本,然后传递到Button
调用中super
的3参数构造函数。这意味着Button
将根据主题中指定的AwesomeButton
默认样式读取其封装内容的默认样式信息。 Android中的某些视图与其超类只有在他们使用的默认样式中不同。 (Button
实际上就是其中之一。)
您在自己的风格中指定android:layout_width
和android:layout_height
,但这可能会有问题。 LayoutParams
(以layout_
开头的任何属性)特定于父视图,而不是它们出现的视图。这就是为什么你总是将预期的父视图作为第二个参数传递给LayoutInflater#inflate
- 它告诉inflater哪个类应该负责解释LayoutParams
。如果你跳过这个,你会经常发现你的LayoutParams
没有按照你的预期行事,并且经常被忽略。按照惯例,我们不会将LayoutParams
置于样式中,即使在某些特殊情况下它也有效。
看起来你正试图将一种风格用作一种模板。有没有理由不为此使用布局资源并在那里指定样式?
final LayoutInflater inflater = LayoutInflater.from(mActivity);
Button btn = (Button) inflater.inflate(R.layout.styled_button, parentView, false);
RES /布局/ styled_button.xml:
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/my_button_background"
[...] />