在合并布局根标记的自定义视图中应用样式



我有一个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需要注意的事项:

  1. 布局使用合并标记来避免视图层次结构中的冗余视图。

  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个视图的构造函数

  1. 公共视图(上下文上下文(->从代码创建视图时使用的简单构造函数。

  2. public View(Context Context,AttributeSet attrs(->从XML 扩展视图时调用的构造函数

  3. public View(Context Context,AttributeSet attrs,int defStyleAttribute(->从XML执行膨胀,并从主题属性应用特定于类的基本样式。

  4. 公共视图(上下文上下文、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是直接从应用程序主题中获取特定样式。

因此,为了达到你想要的结果,你可以做以下事情。

  1. 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>
  1. 在文件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>

  1. 最后,在您的自定义视图第二个构造函数中,您将该属性作为参数传递

    constructor(context: Context, attrs: AttributeSet) : 
    super(
    context,
    attrs,
    R.attr.attribute_name
    )
    

我希望它能有所帮助!

相关内容

  • 没有找到相关文章

最新更新