我有一个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中。但是,由于merge标记用于自定义视图,因此不能以这种方式进行。
我试着如下设置样式,但没有成功:
class OutlinedTextInput @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.TextInputLayoutAppearance
) : TextInputLayout(context, attrs, defStyleAttr) {
我认为上面的解决方案应该起作用,因为构造函数中的第三个参数是传入样式。
另一种选择是在我的自定义视图的init {}
中用程序设置所有属性,但这与在Styles文件中声明样式的目的背道而驰。
我有什么选择?
目前有4个视图的构造函数
-
公共视图(上下文上下文(->从代码创建视图时使用的简单构造函数。
-
public View(Context Context,AttributeSet attrs(->从XML 扩展视图时调用的构造函数
-
public View(Context Context,AttributeSet attrs,int defStyleAttribute(->从XML执行膨胀,并从主题属性应用特定于类的基本样式。
-
公共视图(上下文上下文、AttributeSet属性、int defStyleAttribute、int defStyleRes(添加到API 21级
第三个&如果子类想要指定包含默认样式的属性,或者直接指定默认样式(在四参数构造函数的情况下(,则第四构造函数由子类调用
例如,Button类的构造函数将调用这个版本的超类构造函数,并为defStyleAttribute提供R.attr.buttonStyle;这允许主题的按钮样式修改所有基本视图属性(特别是其背景(以及button类的属性。来自文档
因此,当您创建自定义视图并将该视图添加到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 )
我希望它能有所帮助!