覆盖自定义控件

时间:2015-07-02 15:28:12

标签: android android-library android-styles

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

在library / 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>

在app / styles.xml中:

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

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

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

3 个答案:

答案 0 :(得分:1)

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

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

这将在恢复background和textStyle时覆盖layout_margin。

答案 1 :(得分:1)

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

在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"/>

答案 2 :(得分:0)

您应该使用父attribute例如:

{{1}}