12

I'm trying to programmatically set the "android:checkMark" attribute on CheckedTextView items I have in a ListView. When running my application I get the following exception:

android.content.res.Resources$NotFoundException: Resource ID #0x101021a

The resource with ID #0x101021a corresponds to android.R.attr.listChoiceIndicatorMultiple, which is exactly the value I am passing to my CheckedTextView:

mCheckedTextView.setCheckMarkDrawable(android.R.attr.listChoiceIndicatorMultiple)

Isn't this the way to do it from Java? I tried (and succeeded) to trigger the desired behaviour from XML layout:

<CheckedTextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:id="@android:id/text1" />

The thing is that I don't know at compile time if it should be

android:checkMark="?android:attr/listChoiceIndicatorMultiple"

or

android:checkMark="?android:attr/listChoiceIndicatorSingle"

Hence, I need to set these values at runtime.

dbm
  • 10,376
  • 6
  • 44
  • 56

2 Answers2

27

I would guess that programmatically setting an attribute reference rather than a Drawable reference is the problem.

In this case, android.R.attr.listChoiceIndicatorMultiple corresponds to android.R.drawable.btn_check, so you could try setting that instead.


Or, if you can obtain the attributes, you could call getDrawable() on the TypedArray to dynamically fetch the Drawable value.

Edit:
Since the value of listChoiceIndicatorMultiple depends on the current theme, you need to ask the current theme to resolve the reference:

int[] attrs = { android.R.attr.listChoiceIndicatorMultiple };
TypedArray ta = getContext().getTheme().obtainStyledAttributes(attrs);
Drawable indicator = ta.getDrawable(0);
view.setCheckMarkDrawable(indicator);
ta.recycle();

Be sure to cache the drawables, rather than performing this manoeuvre for every item in your ListView.

That's just a very basic example, but it works with the default theme. I'm not exactly sure what needs to be done to resolve attrs fully if you have a custom theme.

Christopher Orr
  • 110,418
  • 27
  • 198
  • 193
  • 1
    That's a really good answer (since I've already walked down that path :-), however, it seems like there is no "android.R.drawable.btn_check" drawable. If I browse the file system I do indeed find it (it's in the "[path_to_android_SDK]/platforms/android-9/data/res/drawable" folder and it's an XML file), but when writing my code accordingly I get compile errors complaining about "btn_check cannot be resolved or is not a valid field". – dbm Jan 25 '11 at 07:34
  • The other suggestion (the one about "getDrawable()") is, however, new to me. I'll have to do some "homework" on that one though, since I haven't done such a manoeuvre before :-) – dbm Jan 25 '11 at 07:34
  • Ah yes, you're right. I've added a very basic code example that works for me. – Christopher Orr Jan 25 '11 at 08:56
  • Thanks! Your code works like a charm! I will most likely implement a fall-back solution for those cases where there is a custom theme on the device and no drawable for the "...Multiple" respective "...Single" indicators can be obtained from the theme. Thanks again for high quality help (I would up-vote this answer over and over again if I could :-) – dbm Jan 25 '11 at 09:12
  • 1
    A quick comment on @Christopher's caching suggestion: I haven't found a safe way of caching the drawables as recommended. If I do cache, it seems like all my list items will get the same state as the item I clicked on. And yes, I have called "indicator.mutate()". Currently I'm relying on my adapter and that it succeeds to reuse the "convertView" correctly when creating/reusing list items in order to reduce unnecessary drawable obtaining. – dbm Jan 25 '11 at 10:41
1

If using the appcompat library simple alternatives would be:

setCheckMarkDrawable(android.support.v7.appcompat.R.drawable.abc_btn_check_material);

or:

setCheckMarkDrawable(android.support.v7.appcompat.R.drawable.abc_btn_radio_material);  
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Martin
  • 685
  • 7
  • 13