How to allow a custom View's XML attributes to be specified by either resource id or value?

I am implementing my own custom DialogPreference subclass, like so:

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");

        ...
    }

    ...
}

As you can see, I get the dialogMessage XML attribute and save it in the member variable mDialogMsg.

My problem is: my current code does not allow for the dialogMessage XML attribute to be specified as a string resource id in the XML.

In other words, this works:

android:dialogMessage="Hello world!"

But this doesn't:

android:dialogMessage="@string/hello_world"

If I specify it as a resource id in the XML, the resource id gets saved to mDialogMsg, not the string resource itself. Now, I know I could do:

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

But then the user would not be able to enter a normal string in the XML (i.e. a non-resource id). I want to give the user the option of doing both. How do I do this?

Upvotes: 4

Views: 3299

Answers (3)

theb1uro
theb1uro

Reputation: 546

1) Declare custom attribute:

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

2) Obtain its value:

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) Use it in layout:

<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!"
  />

Upvotes: 0

faylon
faylon

Reputation: 7450

int resId = attrs.getAttributeResourceValue(androidns, "dialogMessage", 0);
if(resId != 0){
    mDialogMsg = getContext().getResources().getString(resId);
} else{
    mDialogMsg = attrs.getAttributeValue(androidns, "dialogMessage");
}

Upvotes: 7

codeMagic
codeMagic

Reputation: 44571

I'm not sure if I completely understand your problem but if I do, string resources actually get saved as an integer value. I created the following function in an application to get the string value

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

        return toast;
    }

Then I can pass the resource and the context to get the value

Upvotes: 0

Related Questions