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

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


当前回答

下面是创建自定义属性和视图的官方文档

其他回答

目前最好的文档是源代码。您可以在这里查看它(attrs.xml)。

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

<attr>元素有两个xml属性名称和格式。name可以让你给它命名,这就是你在代码中引用它的方式,例如,r. attrt .my_attribute。format属性可以有不同的值,这取决于你想要的属性的“类型”。

引用——如果它引用了另一个资源id(例如,"@color/my_color", "@layout/my_layout") 颜色 布尔 维 浮动 整数 字符串 分数 Enum—通常隐式定义 标志-通常隐式定义

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

枚举属性的定义如下:

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

标志属性是相似的,除了值需要定义,以便它们可以被放在一起:

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

除了属性之外,还有<declare- stylesable >元素。这允许您定义自定义视图可以使用的属性。您可以通过指定<attr>元素来实现这一点,如果它是先前定义的,则不指定格式。如果你希望重用一个android attr,例如,android:gravity,那么你可以在名称中这样做,如下所示。

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

<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)方法签名来实例化首选项。在这种情况下,只需使用上下文即可。obtainStyledAttributes(attrs, r.s leable. mycustomview)来获取TypedArray。

Secondly it does not cover how to deal with plaurals resources (quantity strings). These cannot be dealt with using TypedArray. Here is a code snippet from my SeekBarPreference that sets the summary of the preference formatting its value according to the value of the preference. If the xml for the preference sets android:summary to a text string or a string resouce the value of the preference is formatted into the string (it should have %d in it, to pick up the value). If android:summary is set to a plaurals resource, then that is used to format the result.

// 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()。

下面是创建自定义属性和视图的官方文档

如果省略attr元素中的format属性,则可以使用它来引用XML布局中的类。

示例来自attrs.xml。 Android Studio理解类是从XML引用的 即。 重命名有效 找到用法 等等……

不要在…/src/main/res/values/attrs.xml中指定format属性

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

在布局文件/src/main/res/layout/activity__main_menu.xml中使用它

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

/src/main/java/…/MyCustomView.kt

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }