覆盖自定义控件的某些属性



假设在Android库项目中有一个自定义控件和相关样式。使用此库的应用程序希望覆盖该控件的某些属性,同时继承其他属性。在我目前的方法中,我有以下代码:

在库/styles.xml:中

<style name="CreditCardInputField">
    <item name="android:layout_margin">10dp</item>
    <item name="android:background">@drawable/border</item>
    <item name="android:textStyle">bold|italic</item>
</style>

应用程序内/styles.xml:

<style name="CreditCardInputField">
    <item name="android:layout_margin">50dp</item>
</style>

我得到的结果是,应用程序中的样式完全覆盖了库中的样式。即,我丢失了backgroundtextStyle属性,同时正确地覆盖了layout_margin。这不是我想要的,我想保留库中定义的backgroundtextStyle。这可能吗?如果可能,怎么做?

编辑:为了澄清,我不想直接在应用程序中使用样式,只想使用库中使用该样式的自定义控件。因此,在应用程序中创建一个新样式(使用库中的父样式)实际上没有任何作用。

在app/styles.xml中为您的样式使用不同的名称,并将另一个样式作为其父样式。

<style name="newCreditCardInputField" parent="CreditCardInputField">
    <item name="android:layout_margin">50dp</item>
</style>

这将在恢复背景和文本样式时覆盖您的layout_margin。

我找到了一种通过自定义属性实现我想要的东西的方法。没有样式那么方便,但更灵活。简而言之,在库中声明自定义属性,在控件的代码中读取它们,在应用程序中提供。以下是几乎完整的代码,也许这会对某人有所帮助:

在lib/values/attrs.xml中(此处声明自定义属性):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="test_view">
        <attr name="field_margins" format="dimension">50dp</attr>
        <attr name="field_background" format="reference">@drawable/border</attr>
        <attr name="name_field_hint" format="reference"/>
        <attr name="number_field_hint" format="reference"/>
    </declare-styleable>
</resources>

在lib/layout/credit_card_view.xml(这是自定义控件的布局)中:

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
    <EditText
        style="@style/CreditCardInputField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <EditText
        style="@style/CreditCardInputField"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
</merge>

在lib/java/TestView.java(自定义控件本身)中:

public class TestView extends LinearLayout {
    public TestView(Context context) {
        super(context);
    }
    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.test_view, 0, 0);
        int margins = (int)a.getDimension(R.styleable.test_view_field_margins, 0f);
        int background = a.getResourceId(R.styleable.test_view_field_background, R.drawable.border);
        int nameFieldHint = a.getResourceId(R.styleable.test_view_name_field_hint, R.string.name_field_hint_lib);
        int numberFieldHint = a.getResourceId(R.styleable.test_view_number_field_hint, R.string.number_field_hint_lib);
        a.recycle();
        LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.credit_card_view, this, true);
        setOrientation(LinearLayout.VERTICAL);
        setGravity(Gravity.CENTER_VERTICAL);
        TextView title = (TextView) getChildAt(0);
        title.setHint(nameFieldHint);
        title.setBackgroundResource(background);
        LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(context, attrs);
        p.setMargins(margins, margins, margins, margins);
        title.setLayoutParams(p);
        TextView number = (TextView) getChildAt(1);
        number.setHint(numberFieldHint);
        number.setBackgroundResource(background);
        number.setLayoutParams(p);
    }
}

最后在app/layout/main_activity.xml中,自定义控件的使用和配置:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" 
xmlns:custom="http://schemas.android.com/apk/res-auto"
...>
<com.example.testlibrary.TestView
    custom:field_margins="20dp"
    custom:field_background="@drawable/field_background"
    custom:name_field_hint="@string/name_field_hint"
    custom:number_field_hint="@string/number_field_hint"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

您应该使用父属性,例如:

<style name="CreditCardInputField" parent="parentStyle">
    <item name="android:layout_margin">10dp</item>
    <item name="android:background">@drawable/border</item>
    <item name="android:textStyle">bold|italic</item>
</style>

相关内容

  • 没有找到相关文章

最新更新