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

问题描述 投票:0回答:1

我有一个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。但是,由于将合并标记用于自定义视图,因此无法以这种方式完成。

我尝试按照以下方式设置样式,但是没有用:

class OutlinedTextInput @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.TextInputLayoutAppearance
) : TextInputLayout(context, attrs, defStyleAttr) {

我认为上面的解决方案应该作为构造函数中的第3个参数传递样式。

另一种选择是在我的自定义视图的init {}中以编程方式设置所有属性,但这违背了在样式文件中声明样式的目的。

我有什么选择?

android-layout android-custom-view android-styles android-textinputlayout android-textinputedittext
1个回答
0
投票

当前一个视图有4个构造函数

  1. public View(Context context)->从代码创建视图时使用的简单构造函数。

  2. public View(上下文上下文,AttributeSet属性)->从XML扩展视图时调用的构造方法

  3. public View(上下文上下文,AttributeSet属性,int defStyleAttr)->从XML执行充气,并从主题属性应用特定于类的基本样式。

  4. 公共视图(上下文上下文,AttributeSet属性,int defStyleAttr,int defStyleRes)在API级别21中添加

    ] >>
  5. 如果子类要指定包含默认样式或直接包含默认样式的属性,则子类将调用它们的第四个构造函数(对于四参数构造函数,则为子类)

例如,Button类的构造函数将调用此版本的超类构造函数,并为defStyleAttr提供R.attr.buttonStyle;这允许主题的按钮样式修改所有基本视图属性(尤其是其背景)以及Button类的属性。 from the docs

因此,当您创建自定义视图并将该视图添加到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
           )
    

    希望对您有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.