?android:attr/selectableItemBackground with another existing background
Asked Answered
P

1

8

I have a 9patch set as the background of my layout. However I still want to provide touch feedback by using the selectableItemBackground attr.

I've tried using a <layer-list> with the 9patch and selectableItemBackground as the android:drawable of the second <item>, however that did not work.

I could also try making a selector and overlay the gradient drawable android uses for selectableItemBackground in list_selector_background_pressed.xml with a <layer-list>. But in 4.4 KitKat the selected background color is actually gray instead of blue in JellyBeans, so I can't really hardcode it :(

There has to be an easier way, right guys? D:

Polygynous answered 28/11, 2013 at 15:34 Comment(0)
M
16

I've tried using a with the 9patch and selectableItemBackground as the android:drawable of the second , however that did not work.

Yes, drawable attribute in a layer-list (or state-list) does not accept an attr value. You would see a Resource.NotFoundException. A look at LayerDrawable's (or StateListDrawable's) source code explains why: the value that you provide is assumed to be a drawable's id.

But, you can retrieve a theme and platform-specific drawable for an attribute in code:

// Attribute array
int[] attrs = new int[] { android.R.attr.selectableItemBackground };

TypedArray a = getTheme().obtainStyledAttributes(attrs);

// Drawable held by attribute 'selectableItemBackground' is at index '0'        
Drawable d = a.getDrawable(0);

a.recycle();

Now, you can create a LayerDrawable:

LayerDrawable ld = new LayerDrawable(new Drawable[] {

                       // Nine Path Drawable
                       getResources().getDrawable(R.drawable.Your_Nine_Path), 

                       // Drawable from attribute  
                       d });

// Set the background to 'ld'
yourLayoutContainer.setBackground(ld);

You'll also need to set yourLayoutContainer's clickable attribute:

android:clickable="true"
Misguidance answered 2/12, 2013 at 22:17 Comment(8)
This looks interesting. Will try.Polygynous
@JasonHu Sorry, I didn't go over your comment fully, was on a call. If you have a question, go ahead.Misguidance
Amazing. Works like a charm. I initially thought I would have to make a selector for the selected states (9patch only on default and the LayerDrawable when selected). But it seems the drawable you get back from the selectableItemBackground is actually the selector itself. Thank you.Polygynous
One thing to note for people that might attempt to do this. Make sure to save your padding on the view before you set the background dynamically with a 9patch, and set it back after the background has been set. Apparently the 9patch will make you lose the paddings on the view. #10095696Polygynous
@JasonHu Exactly. And since we're creating a LayerDrawable --> state-changes are passed to both drawables. selectableItemBackground is transparent when state-less. And that's why, this works.Misguidance
I will give the bounty to you after the 1st day lock on it goes away.Polygynous
@JasonHu Interesting bit of info. I wasn't aware of the padding issue. Thanks!Misguidance
Vikram & @JasonHu, both of you guys just saved me loads of hours. Thanks!Continual

© 2022 - 2024 — McMap. All rights reserved.