在自定义组件的属性集中访问 attrs

我有一个包含两个 TextView 的自定义组件,它们具有自定义大小设置方法(两个文本视图的比例约为 1:2)。由于这是相对布局的子类,因此它没有textSize属性,但我想知道是否仍然可以在XML实例化中为此组件设置该属性,然后从属性集中获取该属性以用于构造函数中的自定义方法。android:textSizetextSizesetSize()

我已经看到了使用自定义属性执行此操作的技术,但是如果我想获取已经在Android词典中的属性怎么办?


答案 1

是的,这是可能的;

让我们假设您的相对布局声明(在 xml 中)具有用 14sp 定义的 textSize:

android:textSize="14sp"

在自定义视图的构造函数(采用 AttributeSet 的构造函数)中,您可以从 Android 的命名空间中检索属性,如下所示:

String xmlProvidedSize = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "textSize");

xmlProvidedSize 的值将类似于“14.0sp”,也许只需进行一点字符串编辑,您就可以提取数字。


声明自己的属性集的另一个选项会有点冗长,但它也是可能的。

因此,您有自定义视图,并且您的 TextViews 声明了如下内容:

public class MyCustomView extends RelativeLayout{

    private TextView myTextView1;
    private TextView myTextView2;

// rest of your class here

伟大。。。

现在,您还需要确保您的自定义视图覆盖了采用属性集的构造函数,如下所示:

public MyCustomView(Context context, AttributeSet attrs){   
    super(context, attrs);
    init(attrs, context);  //nice, clean method to instantiate your TextViews// 
}

好的,现在让我们看看init()方法:

private void init(AttributeSet attrs, Context context){
    // do your other View related stuff here //


    TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView);
    int xmlProvidedText1Size = a.int(R.styleable.MyCustomView_text1Size);
    int xmlProvidedText2Size = a.int(R.styleable.MyCustomView_text2Size);

    myTextView1.setTextSize(xmlProvidedText1Size);
    myTextView2.setTextSize(xmlProvidedText2Size);

    // and other stuff here //
}

你可能想知道R.styleable.MyCustomView,R.styleable.MyCustomView_text1Size和R.styleable.MyCustomView_text2Size来自哪里;请允许我详细阐述这些。

您必须在attrs.xml文件(在 values 目录下)中声明属性名称,以便无论何时何地使用自定义视图,从这些属性收集的值都将在构造函数中传递。

因此,让我们看看您如何像您所问的那样声明这些自定义属性:这是我的全部吸引力.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="text1Size" format="integer"/>
        <attr name="text2Size" format="integer"/>
    </declare-styleable>
</resources>

现在,您可以在 XML 中设置 TextViews 的大小,但如果不在布局中声明命名空间,则无需执行以下操作:

<com.my.app.package.MyCustomView
    xmlns:josh="http://schemas.android.com/apk/res-auto"
    android:id="@+id/my_custom_view_id"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    josh:text1Size="15"
    josh:text2Size="30"     
    />

请注意,我如何将命名空间声明为“josh”作为 CustomView 属性集中的第一行。

我希望这对乔希有所帮助,


答案 2

接受的答案有点长。这是一个精简版本,我希望很容易理解。要将属性(或任何使用 / 的特性)添加到自定义视图中,请执行以下步骤。textSizedpsp

1. 创建自定义属性

创建(或添加以下部分)到attrs.xml。请注意维度格式。

<resources>
    <declare-styleable name="CustomView">
        <attr name="textSize" format="dimension" />
    </declare-styleable>
</resources>

2. 在 xml 布局中设置属性。

请注意自定义命名空间。app

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <com.example.myproject.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:textSize="20sp" /> 

</RelativeLayout>

3. 在自定义视图中获取属性值

请注意 ..在自定义视图中,只需处理像素。如果您需要转换为其他维度,请参阅此答案getDimensionPixelSize

public class CustomView extends View {

    private float mTextSize; // pixels

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.CustomView, 0, 0);
        try {
            mTextSize = a.getDimensionPixelSize(R.styleable.CustomView_textSize, 0);
        } finally {
            a.recycle();
        }
    }

    /**
     * @param size in SP units
     */
    public void setTextSize(int size) {
        mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
                size, getResources().getDisplayMetrics());
        mTextPaint.setTextSize(mTextSize);
        invalidate();
        requestLayout();
    }

    // ...
}

笔记


推荐