rgv*_*rgv 4 android-custom-view android-layout android-styles android-textinputlayout android-textinputedittext
我有一个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>
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
这是view_outlined_textinput我根据上面的原始 xml 改编的,用于自定义视图:
<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>
Run Code Online (Sandbox Code Playgroud)
这里有两件事需要注意:
布局使用合并标签来避免视图层次结构中的冗余视图。
应用自定义样式至关重要。使用 style= 语法在原始 xml 中应用样式。但是,由于合并标签用于自定义视图,因此无法以这种方式完成。
我尝试按如下方式设置样式,但没有成功:
class OutlinedTextInput @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.TextInputLayoutAppearance
) : TextInputLayout(context, attrs, defStyleAttr) {
Run Code Online (Sandbox Code Playgroud)
我认为上述解决方案应该有效,因为构造函数中的第三个参数是传递样式。
另一种选择是在我的自定义视图中以编程方式设置所有属性init {},但这违背了在样式文件中声明样式的目的。
我有什么选择?
目前视图有 4 个构造函数
public View (Context context) -> 从代码创建视图时使用的简单构造函数。
public View (Context context, AttributeSet attrs) -> 从 XML 扩充视图时调用的构造函数
public View (Context context, AttributeSet attrs, int defStyleAttr) -> 从 XML 执行膨胀并从主题属性应用特定于类的基本样式。
public View (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)在 API 级别 21 中添加
如果子类想要指定包含默认样式的属性,或者直接指定默认样式(在四参数构造函数的情况下),则第三个和第四个构造函数由子类调用
例如,Button 类的构造函数将调用此版本的超类构造函数,并为 defStyleAttr 提供 R.attr.buttonStyle;这允许主题的按钮样式修改所有基本视图属性(特别是其背景)以及 Button 类的属性。从文档
因此,当您创建自定义视图并将该视图添加到 XML 中时,android 将始终调用第二个构造函数,其底层如下所示
public TextInputLayout(Context context, AttributeSet attrs) {
this(context, attrs, attr.textInputStyle);
}
Run Code Online (Sandbox Code Playgroud)
第三个参数attr.textInputStyle是直接从应用程序主题获取特定样式。
因此,要实现您正在寻找的结果,您可以执行以下操作。
attrs.xml添加中<attr name="attribute_name" format="reference" />例如。属性.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="attribute_name" format="reference" />
</resources>
Run Code Online (Sandbox Code Playgroud)
style.xml <item name="attribute_name">@style/your_style</item>例如。样式.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>
Run Code Online (Sandbox Code Playgroud)
最后,在自定义视图的第二个构造函数中,将该属性作为参数传递
constructor(context: Context, attrs: AttributeSet) :
super(
context,
attrs,
R.attr.attribute_name
)
Run Code Online (Sandbox Code Playgroud)我希望它有帮助!