【问题标题】:How to allow a custom View's XML attributes to be specified by either resource id or value?如何允许通过资源 id 或值指定自定义视图的 XML 属性?
【发布时间】:2012-11-29 03:17:46
【问题描述】:

我正在实现我自己的自定义 DialogPreference 子类,如下所示:

public class MyCustomPreference extends DialogPreference
{
    private static final String androidns = "http://schemas.android.com/apk/res/android";

    private String mDialogMsg;

    public MyCustomPreference(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        mDialogMsg = attrs.getAttributeValue(androidns, "dialogMessage");

        ...
    }

    ...
}

如您所见,我得到了dialogMessage XML 属性并将其保存在成员变量mDialogMsg 中。

我的问题是: 我当前的代码不允许在 XML 中将 dialogMessage XML 属性指定为字符串资源 ID。

换句话说,这是可行的:

android:dialogMessage="Hello world!"

但这不是:

android:dialogMessage="@string/hello_world"

如果我在 XML 中将其指定为资源 ID,则资源 id 将保存到 mDialogMsg,而不是字符串资源本身。现在,我知道我可以做到:

context.getString(attrs.getAttributeValue(androidns, "dialogMessage"))

但随后用户将无法在 XML 中输入普通字符串(即非资源 ID)。我想给用户两种选择。我该怎么做?

【问题讨论】:

    标签: android android-layout attributes android-xml android-custom-view


    【解决方案1】:
    int resId = attrs.getAttributeResourceValue(androidns, "dialogMessage", 0);
    if(resId != 0){
        mDialogMsg = getContext().getResources().getString(resId);
    } else{
        mDialogMsg = attrs.getAttributeValue(androidns, "dialogMessage");
    }
    

    【讨论】:

    • 这行得通。但是,经过进一步阅读,似乎不推荐直接从 AttributeSet 中读取属性值。相反,应该在res/values/attrs.xml 中定义一个declare-styleable,然后通过调用obtainStyledAttributes() 读取属性值。原因解释here
    【解决方案2】:

    我不确定我是否完全理解您的问题,但如果我理解了,字符串资源实际上会保存为整数值。我在应用程序中创建了以下函数来获取字符串值

    public static String getToastString(int res, Context c)
        {
            String toast = "";
            toast = c.getResources().getString(res);
    
            return toast;
        }
    

    然后我可以传递资源和上下文来获取值

    【讨论】:

    • 我希望 dialogMessage 属性可以指定为字符串或字符串资源 id,并让自定义 DialogPreference 找出它是哪一个。 attrs.getAttributeValue 不这样做,那怎么做呢?
    【解决方案3】:

    1) 声明自定义属性:

    <declare-styleable name="CustomItem">
      <attr name="item_text" format="string"/>
    </declare-styleable>
    

    2) 获取其值:

    public CustomItem(Context context, AttributeSet attrs) {
      super(context, attrs);
    
      mTextView = (TextView) findViewById(R.id.text_view);
    
      final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomItem);
      try {
        setText(a.getString(R.styleable.CustomItem_item_text));
      } finally {
        a.recycle();
      }
    }
    
    public final void setText(String text) {
      mTextView.setText(text);
    }
    
    public final void setText(@StringRes int resId) {
      mTextView.setText(resId);
    }
    

    3) 在布局中使用:

    <com.example.CustomItem
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:item_text="@string/welcome_text"
      />
    
    <com.example.CustomItem
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:item_text="Hello!"
      />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多