假设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>
我得到的结果是应用程序的样式完全覆盖了库中的样式。即我丢失了background
和textStyle
属性,同时正确覆盖了layout_margin
。这不是我想要的,我想保留background
和textStyle
,因为它们在库中定义。是否有可能,如果可以,怎么样?
编辑:为了澄清,我不想直接在应用中使用该样式,只使用来自使用该样式的库的自定义控件。因此,在应用程序中创建一个新样式(使用库中的父项)实际上没有任何效果。
答案 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}}