Selectable/Highlightable List Item with custom background - android

I have a ListView item which has a set background. This overrides the default blue highlight that appears when the item is pressed/selected. Is there a way to have both the background and the selector?
This is my attempt at merging both a background and selector...
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/red"/>
</selector>
<item>
<shape
android:dither="true"
android:shape="rectangle" >
<solid android:color="#ccc" />
</shape>
</item>
<item android:bottom="2dp">
<shape
android:dither="true"
android:shape="rectangle" >
<corners android:radius="6dp" />
<solid android:color="#android:color/white" />
</shape>
</item>
</layer-list>
This is in my drawable folder, and I set it with this in my ListItem xml:
android:background="#drawable/my_background

To have a custom background and the default selector effect (another drawalbe when pressed / selected) is a little difficult, after a few tries, I made it.
You should define two selectors in separated xml file: listitem_background.xml and listitem_selector.xml.
The first one is used to the background of the list item, it will make the effect when the item is pressed and in normal state.
The second one is used to the selector of the list, it will get rid of the default selector of the list view by setting all the state to transparent.
The default selector effect is defined in the first xml file: listitem_background.xml.
First you need a xml file to define some drawable color: color_drawable.xml, in res/values directory:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- The color of the normal state. -->
<drawable name="listitem_normal">#E671B8</drawable>
<!-- The two color below show when the item is pressed, you should change that to the color you want. -->
<drawable name="listitem_pressed">#e7eeab</drawable>
<drawable name="listitem_selected">#e7eeab</drawable>
</resources>
Then, listitem_background.xml in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/listitem_pressed" android:state_enabled="true" android:state_pressed="true"/>
<item android:drawable="#drawable/listitem_selected" android:state_enabled="true" android:state_focused="true"/>
<item android:drawable="#drawable/listitem_selected" android:state_enabled="true" android:state_selected="true"/>
<item android:drawable="#drawable/listitem_normal"/>
</selector>
and, listitem_selector.xml in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/android:transparent" android:state_enabled="true" android:state_pressed="true"/>
<item android:drawable="#color/android:transparent" android:state_enabled="true" android:state_focused="true"/>
<item android:drawable="#color/android:transparent"/>
</selector>
set listitem_background to listitem:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/listitem_background" >
...
</RelativeLayout>
set listitem_selector to listview:
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:listSelector="#drawable/listitem_selector" />

Seeing as this is getting a bit of attention again, I will post the solution I found (which I had previously mentioned in a comment):
I found android:drawSelectorOnTop="true" in the ListView solved the problem.

Just use of this in ListView to match the color combination
android:cacheColorHint="#e7eeab"

Related

How to highlight pressed items in a ListView?

I am using this code below, but it doesn't work properly: If I select an item, the background is changed. But the background change also if I put only focus on the item without selecting it. Why ?
Added to my listview:
android:listSelector="#drawable/bg_key"
#drawable/bg_key
<?xml version="1.0" encoding="utf-8"?>
<selector
android:id="#+id/myselector"
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_activated="false"
android:drawable="#color/activated_color" />
</selector>
color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="activated_color">#1d1d1d</color>
</resources>
You can highlight/provide ripple effect to your list items using the following :
Create a selector item_ripple.xml in your drawable :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#color/activated_color"></solid>
</shape>
</item>
<item >
<shape>
<solid android:color="#android:color/transparent"></solid>
</shape>
</item>
</selector>
Create a selector item_ripple.xml in your drawable-v21
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/activated_color">
<item
android:id="#android:id/mask"
android:drawable="#android:color/white" />
</ripple>
You need to add these selector as background of your item layout :
android:background="#drawable/item_ripple"
You can use pressed state in your selector file
/drawable/list_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/holo_red_light" android:state_pressed="true"/>
</selector>
then set following attribute in your listView
android:listSelector="#drawable/list_selector"

?attr/selectableItemBackground effect shows only on longtap

I've noticed that the effect created by the attribute ?attr/selectableItemBackground only shows when I long tap the view. But I want it to be shown on every tap.
View is clickable and has on click listener.
How to do that?
I've noticed there was a change in the behavior between Lollipop and Marshmallow:
Lollipop - it would start the ripple on press.
Marshmallow - the ripple starts on release.
Could that be the issue?
I would stick to the device Look & Feel but you could
try this suggested solution:
https://stackoverflow.com/a/34167312/348378
Or use instead a library instead, maybe like this one:
https://github.com/balysv/material-ripple
You can achieve this by setting the background of a view. First of all you have to make an item_selector.xml drawable in drawable and drawable-v21.
For drawable folder-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/item_pressed" android:state_focused="true" android:state_pressed="true"/>
<item android:drawable="#drawable/item_pressed" android:state_focused="false" android:state_pressed="true"/>
<item android:drawable="#drawable/item_normal" android:state_focused="true"/>
<item android:drawable="#drawable/item_normal" android:state_focused="false" android:state_pressed="false"/>
</selector>
For drawable-v21 folder-
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight" >
<item>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="#drawable/item_pressed"
android:state_focused="true"
android:state_pressed="true"/>
<item
android:drawable="#drawable/item_pressed"
android:state_focused="false"
android:state_pressed="true"/>
<item
android:drawable="#drawable/item_normal"
android:state_focused="true"/>
<item
android:drawable="#drawable/item_normal"
android:state_focused="false"
android:state_pressed="false"/>
</selector>
</item>
</ripple>
Now all you need to do is put android:background="#drawable/item_selector" in the view tag. For example-
<LinearLayout
android:id="#+id/traveller_select_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/item_selector"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingTop="5dp">
<TextView
android:id="#+id/textTravellers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:text="#string/passengers"
android:textColor="#color/baggage_grey"
android:textSize="12sp"/>
</LinearLayout>
Now make item_pressed.xml in the drawable folder-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#color/filter_bg"/>
</shape>
And the item_normal in the drawable folder-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<solid android:color="#color/white"/>
</shape>
Without your code, it's hard to know where goes wrong. But since I have just got this implemented, share with you what I've done, and perhaps you just follow, would help you figure out the issue.
In your view that need the click for ripple
<TextView
android:id="#+id/your_view_id"
android:layout_width="match_parent"
android:layout_height="wrap_content
android:test="Testing View"
android:background="#drawable/below_drawable">
In your /drawable-v21 folder, you have your below_drawable.xml with content
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/your_click_background_color">
<item android:id="#android:id/mask">
<shape android:shape="rectagle" >
<solid android:color="#android:color/your_mask_color" />
</shape>
</item>
</ripple>
Since the above for Lollipop (v21) only, if you want some impact to your non-lollipop (just show the color, but no ripple). You could have the below in /drawable folder the below_drawable.xml file.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="rectangle">
<solid android:color="#color/your_click_background_color" />
</shape>
</item>
</selector>
Hope this helps.

Is there a way to set drawable's Alpha using XML?

Easy like itself . I wanna make an alpha button , which would have a selected drawable this way:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Play/Pause -->
<item android:state_selected="false" android:drawable="#drawable/item" />
<item android:state_selected="true" android:drawable="#drawable/item" />
</selector>
I would wanna make something like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Play/Pause -->
<item android:alpha="125" android:state_selected="false" android:drawable="#drawable/item" />
<item android:alpha="255" android:state_selected="true" android:drawable="#drawable/item" />
</selector>
Thanks for all .
It's been a while since the OP, but personally found a solution that worked a lot better for me than the suggested answers. Creating a BitmapDrawable makes is easily possible to set the alpha:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/your_drawble"
android:alpha="77">
</bitmap>
Alpha can be any value between 0 and 255. Note that it is sort of the inverse of the HEX color value alpha, as for example 70% alpha would be B3 in HEX and 77 in the BitmapDrawable.
I achieved the same using a drawable
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#5000ddff" />
</shape>
Over here used the alpha 50, which sets the opacity level.
I have been looking for the same thing. Even though this is posted over four years ago, this is the top post when googling the issue, so I'll reply here.
This is my solution
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<bitmap android:alpha="#integer/not_pressed_alpha" android:src="#drawable/item"/>
</item>
<item android:state_pressed="true" android:drawable="#drawable/item" />
</selector>
For those who have the same problem as OP, AppCompat now allows you to set 'alpha' parameter, as he wished in his target code:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Play/Pause -->
<item android:alpha="125" android:state_selected="false" android:drawable="#drawable/item" />
<item android:alpha="255" android:state_selected="true" android:drawable="#drawable/item" />
</selector>
More info here.
My goal was to make a button have it's selected and pressed states at a different alpha - but using the same (png) resource and affecting as few files as possible.
My solution is similar to altering the alpha in a BitmapDrawable - but it does it from the selector so only one file is affected.
Use the tint function of Bitmap, remember that the tint will color the existing pixels so use a white color.
Eg, #80FFFFFF - to keep color as original but reduce alpha by 50%
This could also be used to change color of the icon when pressed.
This is my drawable XML file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true">
<bitmap
android:src="#drawable/ic_camera"
android:tint="#80FFFFFF">
</bitmap>
</item>
<item android:state_pressed="true">
<bitmap
android:src="#drawable/ic_camera"
android:tint="#80FFFFFF">
</bitmap>
</item>
<item>
<bitmap
android:src="#drawable/ic_camera">
</bitmap>
</item>
</selector>
I'm using the following for a custom radio button which should be diagonally strikethrough when it is disabled.
Example Image of 5 radio buttons where 4 of them are enabled
<item android:state_enabled="false">
<layer-list>
<item>
<shape android:shape="rectangle">
<size
android:height="35dp"
android:width="35dp"/>
<stroke
android:color="#color/someGrey"
android:width="1dp"/>
<corners android:radius="1dp"/>
</shape>
</item>
<item>
<rotate
android:fromDegrees="135"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="135">
<shape android:shape="line">
<stroke
android:color="#color/someGrey"
android:width="1dp"/>
</shape>
</rotate>
</item>
</layer-list>
</item>
I agree with Kasium sugest, so for some Android versions the especification to Alpha is in percent.
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/your_drawble"
android:alpha="0.5">
</bitmap>
i think you could create your own drawable which could take this argument as a parameter. i've never done such a thing though.
check out this link :
How to set alpha value for drawable in a StateListDrawable?
if that's not possible, you can always do it in code...
here are 2 links i've found about it, in case you wish to use bitmaps instead:
https://plus.google.com/+RomanNurik/posts/FZQcNW8G75K
https://gist.github.com/romannurik/5779875
Its not that simple but its possible:
First you have to define color in color folder of your resources like this:
color/inst_control_pressed_transp.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:alpha="0.5" android:color="?attr/inst_control_pressed" />
</selector>
Now you can reference that color from some shape:
drawable/background_clear_pressed.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/inst_control_pressed_transp" />
</shape>
Tha you can use it in drawable:
drawable/background_bordered_clear_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/background_clear_pressed" android:state_pressed="true" android:state_selected="false" />
<item android:drawable="#drawable/background_clear_active" android:state_activated="true" />
<item android:drawable="#drawable/background_clear_selected" android:state_selected="true" />
<item android:drawable="#drawable/background_bordered_clear_round" />
</selector>

Custom tabs are not responding to pressed state

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:drawable="#drawable/tab_profile_pressed_mdpi" />
<item android:drawable="#drawable/tab_profile_unselected_mdpi" />
</selector>
And how I set them:
((ImageView)tabHost.getTabWidget().getChildTabViewAt(i).findViewById(R.id.single_tab_img)).setImageResource(unselected_img[i]);
You need to use setBackgroundResource not setImageResource. State drawables work on the background image, not the foreground image.
I believe you need another xml file that lays out what will happen when the tab is pressed.
Example:
tab.xml
<item android:state_focused="true" android:state_selected="true"
android:state_pressed="false" android:drawable="#drawable/tab_bg_selected" />
tab_bg_selected
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#A8A8A8" android:centerColor="#7F7F7F"
android:endColor="#696969" android:angle="-90" />
</shape>

Selector color on LinearLayout

I'm trying to assing a color selector to an extended class of LinearLayout, so, i think its like if we speak about linearLayout.
i followed the instructions on this post, the answer talking about shapes.
Now i have 3 xml on drawables folders:
normal.xml file
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ffffffff" />
</shape>
pressed.xml file
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#00000000" />
</shape>
and finally, bg.xml file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/pressed" />
<item android:state_focused="true" android:drawable="#drawable/pressed" />
<item android:state_selected="true" android:drawable="#drawable/pressed" />
<item android:drawable="#drawable/normal" />
</selector>
I am accessing this in the following way:
Drawable d = getResources().getDrawable(context.getResources().getIdentifier("mypackageuri.tProject:drawable/bg", null, null));
view.setBackgroundDrawable(d);
The "normal" state its fine, with the color set at "normal.xml", but no way with the other ones, I press my view and nothing happens, it's not changing color in any way...
I can't see what i'm doing wrong...
Thank you
Your view needs to be clickable in order to get the state pressed when you click on it.
Use :
view.setClickable(true);
or in the layout xml :
android:clickable="true"

Categories

Resources