我有一个TextInputLayout
,带有自定义样式,需要大量重用,因此我试图将其转换为自定义视图。
这里是要重用的xml:
<com.google.android.material.textfield.TextInputLayout
style="@style/TextInputLayoutAppearance"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
[TextInputLayoutAppearance
是我在styles.xml
中创建的自定义样式
这是我的自定义视图的类:
class OutlinedTextInput @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputLayout(context, attrs, defStyleAttr) {
init {
LayoutInflater.from(context).inflate(R.layout.view_outlined_textinput, this, true)
}
}
这是我从上面的原始xml改编而成的view_outlined_textinput
,用于自定义视图:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:parentTag="com.google.android.material.textfield.TextInputLayout">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</merge>
这里有2件事需要注意:
布局使用合并标签来避免视图层次结构中的冗余视图。
应用自定义样式至关重要。使用style =语法将样式应用于原始xml。但是,由于将合并标记用于自定义视图,因此无法以这种方式完成。
我尝试按照以下方式设置样式,但是没有用:
class OutlinedTextInput @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.TextInputLayoutAppearance
) : TextInputLayout(context, attrs, defStyleAttr) {
我认为上面的解决方案应该作为构造函数中的第3个参数传递样式。
另一种选择是在我的自定义视图的init {}
中以编程方式设置所有属性,但这违背了在样式文件中声明样式的目的。
我有什么选择?
当前一个视图有4个构造函数
public View(Context context)->从代码创建视图时使用的简单构造函数。
public View(上下文上下文,AttributeSet属性)->从XML扩展视图时调用的构造方法
public View(上下文上下文,AttributeSet属性,int defStyleAttr)->从XML执行充气,并从主题属性应用特定于类的基本样式。
公共视图(上下文上下文,AttributeSet属性,int defStyleAttr,int defStyleRes)在API级别21中添加
] >>如果子类要指定包含默认样式或直接包含默认样式的属性,则子类将调用它们的第四个构造函数(对于四参数构造函数,则为子类)
例如,Button类的构造函数将调用此版本的超类构造函数,并为defStyleAttr提供R.attr.buttonStyle;这允许主题的按钮样式修改所有基本视图属性(尤其是其背景)以及Button类的属性。 from the docs
因此,当您创建自定义视图并将该视图添加到XML android时,总是会调用第二个构造函数,如下所示:>
public TextInputLayout(Context context, AttributeSet attrs) { this(context, attrs, attr.textInputStyle); }
第三个参数attr.textInputStyle
直接从应用程序主题获取特定样式。
因此,要获得所需的结果,可以执行以下操作。
attrs.xml
中添加<attr name="attribute_name" format="reference" />
例如attrs.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="attribute_name" format="reference" /> </resources>
- 在文件
style.xml
<item name="attribute_name">@style/your_style</item>
中添加到AppTheme中>例如style.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <!-- Customize your theme here. --> ... <item name="attribute_name">@style/your_style</item> ... </style>
最后,在您的自定义视图第二个构造函数中,将该属性作为参数传递
constructor(context: Context, attrs: AttributeSet) : super( context, attrs, R.attr.attribute_name )
希望对您有帮助!