如何在语法上将样式更改为膨胀视图
how to grammatically change style to an inflated view
我创建了一个自定义视图,里面只有几个视图。
我想设置一个自定义属性来设置它的样式。
我如何在语法上做到这一点,因为我不是动态创建内部视图,而是来自 xml。
我看到您只能在通过代码(而不是通过 xml)创建视图时以语法方式设置样式?
RelativeLayout someLayout = new RelativeLayout(context, null, R.style.LightStyle);
我想提出几个可能的解决方案,但由于 Android
中这部分的设计,它们并非完美无缺
通过代码配置内部视图
无法将内部 TypedArray
包装为另一个 TypedArray
的参数,我认为创建 AttrbiteSet
的实例不是合理的方法(应该在这个参数下)在代码中设置视图。相反,只需使用不带 xml 属性的默认构造函数 new RelativeLayout(context)
并自己提供所有必需的值(您仍然可以在 declare-styleable
资源中声明自定义属性以利用基于 XML 的样式,并将它们用作您内心观点的一部分,但这将是您的 'manual' 设置)。理由如下:
AttributeSet
并非设计为内置代码。检查
文档,你会看到这个的唯一实现
接口是 XmlResourceParser
.
Android代码本身
不会在代码中构建此参数,即使它可能是合理的。
例如这里是构造函数的代码的第一行
View(Context context)
class:
public View(Context context) {
mContext = context;
mResources = context != null ? context.getResources() : null;
mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
...
setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
mUserPaddingStart = UNDEFINED_PADDING;
mUserPaddingEnd = UNDEFINED_PADDING;
...
}
如您所见,没有以编程方式创建 Xml 属性的情况,而是在代码中设置相应的值。
通过外部布局配置内部视图
您可以创建一个指向外部布局的自定义属性,应该与您正在使用的内部视图兼容。不幸的是,我不知道是否有办法限制这种布局的类型,所以你的 class 的消费者可以提供他想要的任何参考,而你在这里唯一能做的就是抛出一个运行时异常让他成为意识到出了点问题。
在您的自定义视图样式属性中声明一个自定义引用属性:
<resources>
<declare-styleable name="CustomView">
<attr name="inner_layout" format="reference" />
</declare-styleable>
</resources>
在您的自定义视图构造函数中,使用检索到的布局 ID 扩充所需的布局:
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyle, 0);
try {
int resource = a.getResourceId(R.styleable.CustomView_inner_layout, 0);
RelativeLayout layout = LayoutInflater.from(context).inflate(resource, this, false);
} finally {
a.recycle();
}
我创建了一个自定义视图,里面只有几个视图。
我想设置一个自定义属性来设置它的样式。
我如何在语法上做到这一点,因为我不是动态创建内部视图,而是来自 xml。
我看到您只能在通过代码(而不是通过 xml)创建视图时以语法方式设置样式?
RelativeLayout someLayout = new RelativeLayout(context, null, R.style.LightStyle);
我想提出几个可能的解决方案,但由于 Android
中这部分的设计,它们并非完美无缺通过代码配置内部视图
无法将内部 TypedArray
包装为另一个 TypedArray
的参数,我认为创建 AttrbiteSet
的实例不是合理的方法(应该在这个参数下)在代码中设置视图。相反,只需使用不带 xml 属性的默认构造函数 new RelativeLayout(context)
并自己提供所有必需的值(您仍然可以在 declare-styleable
资源中声明自定义属性以利用基于 XML 的样式,并将它们用作您内心观点的一部分,但这将是您的 'manual' 设置)。理由如下:
AttributeSet
并非设计为内置代码。检查 文档,你会看到这个的唯一实现 接口是XmlResourceParser
.Android代码本身 不会在代码中构建此参数,即使它可能是合理的。 例如这里是构造函数的代码的第一行
View(Context context)
class:public View(Context context) { mContext = context; mResources = context != null ? context.getResources() : null; mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO; ... setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); mUserPaddingStart = UNDEFINED_PADDING; mUserPaddingEnd = UNDEFINED_PADDING; ... }
如您所见,没有以编程方式创建 Xml 属性的情况,而是在代码中设置相应的值。
通过外部布局配置内部视图
您可以创建一个指向外部布局的自定义属性,应该与您正在使用的内部视图兼容。不幸的是,我不知道是否有办法限制这种布局的类型,所以你的 class 的消费者可以提供他想要的任何参考,而你在这里唯一能做的就是抛出一个运行时异常让他成为意识到出了点问题。 在您的自定义视图样式属性中声明一个自定义引用属性:
<resources>
<declare-styleable name="CustomView">
<attr name="inner_layout" format="reference" />
</declare-styleable>
</resources>
在您的自定义视图构造函数中,使用检索到的布局 ID 扩充所需的布局:
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyle, 0);
try {
int resource = a.getResourceId(R.styleable.CustomView_inner_layout, 0);
RelativeLayout layout = LayoutInflater.from(context).inflate(resource, this, false);
} finally {
a.recycle();
}