覆盖自定义控件的某些属性 [英] Override certain attributes of a custom control

查看:104
本文介绍了覆盖自定义控件的某些属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,Android库项目中存在自定义控件和相关样式.使用该库的应用程序希望在继承其他控件的同时重写该控件的某些属性.在我目前的方法中,我有以下代码:

Let's say there's a custom control and related style in an Android library project. The application that uses this library wants to override certain attributes of that control, while inheriting the others. In my current approach, I have the following code:

在library/styles.xml中:

In 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中:

In app/styles.xml:

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

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

The result I have is that the style from the app completely overrides the style from the library. I.e. I lose the background and textStyle properties, while correctly overriding the layout_margin. This is not what I want, I want to keep the background and textStyle as they're defined in library. Is it possible, and, if yes, how?

为了明确起见,我不想直接在应用程序中使用样式,而只希望使用样式库中的自定义控件.因此,在应用程序中(与库中的父项一起)创建新样式实际上无济于事.

To clarify, I don't want to use the style directly in the app, only the custom control from the library that uses the style. Therefore creating a new style in the app (with a parent from the library) does effectively nothing.

推荐答案

我找到了一种通过自定义属性实现所需功能的方法.不像样式那样方便,但是更加灵活.简而言之,在库中声明自定义属性,在控件的代码中读取它们,然后在应用中提供.这是几乎完整的代码,也许这会对某人有所帮助:

I've found a way to achieve what I want through the custom attributes. Not as convenient as with a style, but more flexible. In short, declare custom attributes in the library, read them in the control's code, provide in the app. Here's the almost complete code, maybe this will help someone:

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

In lib/values/attrs.xml (custom attributes are declared here):

<?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中(这是自定义控件的布局):

In lib/layout/credit_card_view.xml (this is the custom control's layout):

<?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中(自定义控件本身):

In lib/java/TestView.java (the custom control itself):

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中,自定义控件的用法和配置:

And finally in app/layout/main_activity.xml, custom control's usage and configuration:

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

这篇关于覆盖自定义控件的某些属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆