【问题标题】:Accessing attrs in AttributeSet for custom components访问自定义组件的 AttributeSet 中的属性
【发布时间】:2011-11-28 20:59:40
【问题描述】:

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

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

【问题讨论】:

    标签: java android textview android-relativelayout


    【解决方案1】:

    是的,这是可能的;

    假设您的 RelativeLayout 声明(在 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
    

    太好了……

    现在您还需要确保您的自定义视图覆盖了接受 AttributeSet 的构造函数,如下所示:

    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 目录下)中声明属性名称,以便无论您在何处使用自定义视图,从这些属性收集的值都将传递给您的构造函数。

    那么让我们看看您是如何按照您的要求声明这些自定义属性的: 这是我的整个 attrs.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 中设置 TextView 的大小,但不能在布局中声明命名空间,方法如下:

    <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 属性集中的第一行。

    我希望这可以帮助乔希,

    【讨论】:

    • 如果我想简单地使用现有 android 命名空间中的属性,例如 android:textSize。实际上,我只想读取该属性是什么(即使RelativeLayout会忽略它)并使用数值(来自“14sp”的14)以编程方式设置子视图中的文本大小。有没有办法在不需要创建另一个模式的情况下获取该集合中现有的 android 属性?
    • 嘿乔希,我已经添加了如何在我的答案之上还检索 android 命名空间属性值。最好的,-serkan
    • 优秀。我几乎做对了:) 在我之前的尝试中我没有使用完整的命名空间。通过textSizeAttribute = textSizeAttribute.replaceAll("[^\\d\\.]+", ""); textSize = Float.parseFloat(textSizeAttribute); 发送,然后就可以了。它不是最强大的,但应该可以很好地与常规 textSize 输入一起使用。
    • 确保在使用完 typedArray 后回收它a.recycle()
    【解决方案2】:

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

    1。创建自定义属性

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

    <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 的使用。在您的自定义视图中只使用像素。如果您需要转换为不同的维度,请参阅this answer

    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();
        }
    
        // ...
    }
    

    注意事项

    【讨论】:

      猜你喜欢
      • 2013-06-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多