定义自定义attrs

我需要实现自己的属性,如com.android.R.attr

在官方文档中没有找到任何东西,所以我需要关于如何定义这些attrs以及如何从我的代码中使用它们的信息。

目前最好的文档是来源。 你可以在这里看看(attrs.xml) 。

您可以在顶部的<resources>元素或者<declare-styleable>元素中定义属性。 如果我要在不止一个地方使用attr,我把它放在根元素中。 请注意,所有属性共享相同的全局名称空间。 这意味着即使您在<declare-styleable>元素内创建了一个新属性,它也可以在其外部使用,并且不能创建具有不同类型的相同名称的另一个属性。

一个<attr>元素有两个xml属性nameformatname可以让你调用它,这就是你最终在代码中引用它,例如R.attr.my_attributeformat属性可以有不同的值,取决于你想要的属性的“类型”。

  • 参考 – 如果它引用另一个资源ID(例如,“@ color / my_color”,“@ layout / my_layout”)
  • 颜色
  • 布尔
  • 尺寸
  • 浮动
  • 整数
  • 分数
  • 枚举 – 通常是隐式定义的
  • 标志 – 通常是隐式定义的

您可以使用|将格式设置为多种类型 ,例如format="reference|color"

enum属性可以定义如下:

 <attr name="my_enum_attr"> <enum name="value1" value="1" /> <enum name="value2" value="2" /> </attr> 

flag属性是相似的,除了值需要被定义,所以它们可以被排在一起:

 <attr name="my_flag_attr"> <flag name="fuzzy" value="0x01" /> <flag name="cold" value="0x02" /> </attr> 

除了属性,还有<declare-styleable>元素。 这使您可以定义自定义视图可以使用的属性。 你可以通过指定一个<attr>元素来完成这个工作,如果这个元素是之前定义的,那么你不需要指定format 。 如果你想重复使用一个android attr,例如android:gravity,那么你可以这样做,如下所示。

自定义视图的示例<declare-styleable>

 <declare-styleable name="MyCustomView"> <attr name="my_custom_attribute" /> <attr name="android:gravity" /> </declare-styleable> 

在自定义视图中以XML格式定义自定义属性时,您需要执行一些操作。 首先,您必须声明一个名称空间来查找您的属性。 您在根布局元素上执行此操作。 通常只有xmlns:android="http://schemas.android.com/apk/res/android" 。 您现在必须添加xmlns:whatever="http://schemas.android.com/apk/res-auto"

例:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:whatever="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <org.example.mypackage.MyCustomView android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center" whatever:my_custom_attribute="Hello, world!" /> </LinearLayout> 

最后,为了访问这个自定义属性,你通常在自定义视图的构造函数中这样做,如下所示。

 public MyCustomView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0); String str = a.getString(R.styleable.MyCustomView_my_custom_attribute); //do something with str a.recycle(); } 

结束。 🙂

Qberticus的答案很好,但是缺少一个有用的细节。 如果您正在库中实现这些替换:

 xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage" 

有:

 xmlns:whatever="http://schemas.android.com/apk/res-auto" 

否则,使用该库的应用程序将有运行时错误。

除了一些事情之外,上面的答案涵盖了所有细节。

首先,如果没有样式,那么将使用(Context context, AttributeSet attrs)方法签名来实例化该偏好。 在这种情况下,只需使用context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)来获取TypedArray。

其次,不涉及如何处理版面资源(数量字符串)。 这些不能用TypedArray来处理。 以下是我的SeekBarPreference中的代码片段,它根据首选项的值设置首选项的格式设置摘要。 如果首选项的xml将android:summary设置为文本字符串或字符串资源,则首选项的值将被格式化为字符串(它应该包含%d,以获取值)。 如果android:summary被设置为一个plaurals资源,那么这个被用来格式化结果。

 // Use your own name space if not using an android resource. final static private String ANDROID_NS = "http://schemas.android.com/apk/res/android"; private int pluralResource; private Resources resources; private String summary; public SeekBarPreference(Context context, AttributeSet attrs) { // ... TypedArray attributes = context.obtainStyledAttributes( attrs, R.styleable.SeekBarPreference); pluralResource = attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0); if (pluralResource != 0) { if (! resources.getResourceTypeName(pluralResource).equals("plurals")) { pluralResource = 0; } } if (pluralResource == 0) { summary = attributes.getString( R.styleable.SeekBarPreference_android_summary); } attributes.recycle(); } @Override public CharSequence getSummary() { int value = getPersistedInt(defaultValue); if (pluralResource != 0) { return resources.getQuantityString(pluralResource, value, value); } return (summary == null) ? null : String.format(summary, value); } 

  • 这只是一个例子,但是,如果您想要在首选项屏幕上设置摘要,则需要在首选项的onDialogClosed方法中调用notifyChanged()