ListView With Nine-Patch Item Background Issues - android

WARNING: The XML in this question is wrong, read the answer before you confuse yourself!
I have been banging my head on the wall for a while now. The following posts have shed light on the subject, but failed to solve my issue: Android ListView State List not showing default item background and ListView item background via custom selector
The proper nine-patch background shows perfectly when I select the list item, but I can not get the default nine-patch background to show initially. It seems to me that I need to set the default item background somehow, but I can't figure out how to do so.
List View:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/shopListHeader"
/>
<ListView
android:id="#+id/shopList"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:dividerHeight="0px"
android:divider="#FFFFFFFF"
android:listSelector="#drawable/shop_list_selector"
/>
</LinearLayout>
Selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:visible="true">
<!-- the list items are enabled and being pressed -->
<item
android:state_pressed="true"
android:drawable="#drawable/shop_list_item_pressed" />
<item
android:state_selected="true"
android:textColor="#FFFFFFFF" />
</selector>
Background:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:visible="true">
<item
android:state_selected="true"
android:drawable="#android:color/transparent" />
<item
android:drawable="#drawable/shop_list_item" />
</selector>
As you can see, I have dumbed down the examples from the references.
You may also notice that the Background selector isn't being referenced anywhere. I started tossing it in random places (if the app compiled the addition either had no effect or cause a forced close)
I have also made an attempt to stop the color of the text from changing to black and grey when an item is selected but not pressed (can be done by scrolling through the list). Since my background will be black in the center, the text becomes partially invisible when selected. That addition (the last item node in the Selector) does nothing, as far as I can tell.
Does anyone have any thoughts on getting this ridiculously time consuming functionality working?

I was gonna delete this thread, but I can't so I'll see if I can't use this as an example of what not to do :)
First, in the ListView XML: android:listSelector="#drawable/shop_list_selector"
Don't do that!
What I was trying to do here was set the background of the list items and the android:background property didn't work. You may have noticed that the item XML is missing, and that is because it was missing from my head! (I never touched it over the countless hours I was hammering away at this 'issue') So the line android:background="#drawable/shop_list_selector" goes in the item's properties and everything is groovy. (Remember the XML above is very wrong so don't use it!)
...Well except that it doesn't look as good in real life as it did in my head :(
Back to the drawing board!!!

You havent defined a "normal" state, see this example
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/blue"
android:state_pressed="true" />
<item android:color="#color/red"
android:state_selected="true" />
<item android:color="#color/white" />
</selector>
in here white is the "normal" state, in here you can find some documentation about it.
I hope this helps

Related

How to have a android:background color and still retain the gray focus highlight for lists in Android?

I'm porting my app to Chrome OS and there are a few places in the app where arrow key navigation works, but the current focused element is not highlighted in any way. I've found that whenever I set a background color for an element like
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
...
android:background="#color/white" >
...
</LinearLayout>
then the default highlighting of the focused element will not show. Removing this will show the default background (which is not always the same as what I want).
Also, in cases where I use a selector in a ListView, the background is in front of the intended highlighting drawable (which can be seen if the color is somewhat transparent).
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime" >
<item android:state_pressed="false" android:state_focused="true" android:drawable="#drawable/list_focused" />
<item android:state_pressed="true" android:drawable="#drawable/list_pressed" />
<item android:drawable="#color/white" />
</selector>
This is even more strange since I was under the (possibly incorrect) impression that selectors will only pick one of the items.
I can't post too much code since this is work code, but this is happening throughout the app wherever there's a list.
If you have a selector defined for the views in your ListView, set the drawSelectorOnTop property to true on your ListView, as per the docs.

How to mark a listview item?

I know this has been discussed many times in questions like this question and this one.
But I have to say it doesn't work for me.
What I wanted to achieve is to mark a ListView item through my CustomAdapter in a special situation. So, not through the user and click listeners. I have a working solution by setting a background drawable to the convertView.
Now I want to change this and let do a selector the job, which is the cleaner solution. But I can't get it to work. There is no problem to set the behavior for pressing an item and set a different color. But I can't mark it as selected after I pressed the item.
I tried different combinations with my listview_item_selector and listview_selector. And I think, that I have missed something very general. That's why I made a setup just to figure out how to mark an item after it was pressed.
Here's my list_item_selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#android:color/transparent"/>
<item android:state_selected="true" android:drawable="#android:color/transparent"/>
<item android:drawable="#drawable/state_normal"/>
</selector>
And my listview_selector setted to the ListView as selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/state_pressed"></item>
<item android:state_selected="true" android:drawable="#drawable/selected_item"/>
</selector>
As I said state_pressed is working. But state_selected drives me nuts.
At least my layout for the custom items:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listview_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/listview_item_selector">
<TextView
android:id="#+id/list_tv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFFFEE"/>
<TextView
android:id="#+id/list_tv2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#FFEEEE"/>
</LinearLayout>
I would appreciate any suggestions.
because you are missing a state, you need to mark the row as activated and have the drawable that indicates the row as selected for the activated state
see my question for an example
Showing the current selection in a listview
then use
listview.setItemChecked(position,true);

Using Image in a Android Button with effects

(Now I have come across related questions on StackOverflow but unfortunately none of the solutions worked for me which is why I had to ask this separately)
I am a Novice to Android. The problem: I need to have an image that acts as a button. Now I understand that this can be achieved by either using an image on a standard button or by using something called as "ImageButton" (which I guess is highly recommended although I have no idea why).
Requirements: I need detailed guidance for going about this problem. Specifically, I thought the "putting-image-on-standard-button" was easier until I faced two major issues: I was unable to set the image in the center (thanks drawable-top,bottom,left6,right) and once I changed the background color to match that of the Activity screen's back-color, the button effect disappeared. Simply put, I need a moderately easy way of having an image act as a button or a button with an image which has all three effects: focussed, pressed and default. I used ImageButton but then I did not know how to make custom shapes or 9patch images to give it all the desired effects, I am pretty satisfied with the default button that android provided. All I simply need is something like a background hover over the image or something of that sort which indicates the user that the image is being pressed and the event has been generated!
Can someone please help me out with this? I need the UI to look decent and therefore, need the corresponding effects on my image/button. Thanks in Advance :)
This is my icon-image:
I wish to have some sort of hover effect around this that indicates that the image has been pressed just like any normal button.
Use ImageButton and StateList Drawable. You need selector for different button's states. You can assign different drawable for different state to imitate the onFocus or onPressed effect on normal button.
This is selector.xml in drawable folder under res:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="#color/cyan"/> <!-- pressed state -->
<item android:state_focused="true"
android:drawable="#color/cyan"/> <!-- focused state -->
<item android:drawable="#android:color/transparent"/> <!-- default state -->
</selector>
And this is color.xml in values folder under res:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="cyan">#33B5E5</color>
</resources>
Set the ImageButton's src to your image and set the background to selector.xml.
This is the final result:
There is a good tutorial here: Android ImageButton Selector Example
If someone also still has an issue with this.
I've created the selector but referred the drawable to two different image files, and used the XML in the imagebutton as a source. It worked like a charm.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/btn_add_pressed"
android:state_pressed="true" />
<item android:drawable="#drawable/btn_add"
android:state_focused="true" />
<item android:drawable="#drawable/btn_add" />
</selector>
And the image button looks like this:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/add_button_selector"
android:background="#null"/>
create xml view
<ImageView
android:id="#+id/imageview1"
android:background="#drawable/selector_xml_name"
android:layout_width="200dp"
android:layout_height="126dp"/>
create inside draw able folder selector_xml_name.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/numpad_button_bg_selected"android:state_selected="true"></item>
<item android:drawable="#drawable/numpad_button_bg_pressed" android:state_pressed="true"></item>
<item android:drawable="#drawable/numpad_button_bg_normal"></item>
create inside draw able folder numpad_button_bg_selected.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" android:padding="90dp">
<solid android:color="#color/selected"/>
<padding />
<stroke android:color="#000" android:width="1dp"/>
<corners android:bottomRightRadius="15dp" android:bottomLeftRadius="15dp" android:topLeftRadius="15dp" android:topRightRadius="15dp"/>

Android TextView links don't highlight when clicked

I have an android TextView which has a link in it. The link looks fine and performs the correct action when the user taps on it, but while the user's finger is down the link doesn't change color at all. Is that normal Android behavior? Seems like a highlight or indicator of some kind would be helpful, especially if I have small text and a bunch of links next to each other. Is this what other people are seeing, is there an easy fix for this?
Also the slash on the end of the URL isn't part of the link. Smells like a bug in their RegEx.
Here's the code I'm using:
textView.setAutoLinkMask(Linkify.WEB_URLS);
textView.setText("Hi welcome to http://www.plopfizz.com/ please enjoy.");
You could create an item selector with diff states, for example...
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#FEFEFE" /> <!-- highlight -->
<item android:state_focused="true" android:color="#000000" />
<item android:color="#FFFFFF" /> <!-- default -->
</selector>
And then in your layout...
<TextView
...
android:textColor="#color/above_selector"/>

Android ListView State List not showing default item background

Have read over a number of related questions here at SO, as well as looked through the Android docs and source to try to figure this out, but I am stumped, although given that the listSelector seems to only apply styles on selected items, I'm not shocked...
I have a Listview defined in main.xml here:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fadingEdgeLength="5dp"
android:divider="#000000"
android:dividerHeight="1dp"
android:listSelector="#drawable/list_selector" />
<TextView
android:id="#android:id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:singleLine="false"
android:text="#string/message_list_empty" />
</FrameLayout>
The listSelector referenced is here (borrowed largely from the default Android State List found in the SDK: /android/platforms/android-8/data/res/drawable/list_selector_background.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- the window has lost focus, disable the items -->
<item
android:state_window_focused="false"
android:drawable="#drawable/shape_row_disabled" />
<!-- the list items are disabled -->
<item
android:state_enabled="false"
android:state_focused="true"
android:state_pressed="true"
android:drawable="#drawable/shape_row_disabled" />
<item
android:state_enabled="false"
android:state_focused="true"
android:drawable="#drawable/shape_row_disabled" />
<item
android:state_enabled="false"
android:drawable="#drawable/shape_row_disabled" />
<!-- the list items are enabled and being pressed -->
<item
android:state_focused="true"
android:state_pressed="true"
android:drawable="#drawable/shape_row_transition" />
<item
android:state_focused="false"
android:state_pressed="true"
android:drawable="#drawable/shape_row_transition" />
<!-- the list items are enabled and being used -->
<item
android:state_focused="true"
android:drawable="#drawable/shape_row_selected" />
<!-- the default item -->
<item
android:drawable="#drawable/shape_row" />
</selector>
The drawables referenced are shapes, rounded rectangles, like so:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#EF6100"
android:centerColor="#FF8E00"
android:endColor="#EF6100"
android:angle="270" />
<corners
android:bottomRightRadius="7dp"
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp" />
</shape>
So, the end result should be a ListView with items with a #drawable/shape_row background by default, and then different colored backgrounds depending on the state. When I fire up my list, everything works fine in terms of when states are active, such as an item gets focus, is pressed, etc, but the items themselves have a transparent background when none are selected (i.e. the default view state). I had hoped that the last rule of the State List,
<item android:drawable="#drawable/shape_row" />
would capture that state, but for some reason it is not working. I have moved things around and tried different settings, and nothing. If I edit the row.xml file which I use to define the list items in the ListView and try to add a specific android:background that points to #drawable/shape_row, every row gets the correct background, BUT on pressed, on focus, etc states fail to process (or at least, can't be seen as the background never changes).
Can anyone point me in the right direction here? I am SO close to putting this one to bed, but after trying nearly everything, just can't get the ListView items to take a default background AND respond to the implemented State List via android:listSelector.
Thanks,
Paul
EDIT:
Also just tried adding android:itemBackground="#drawable/shape_row" to the ListView in main.xml, and unsurprisingly no luck (the docs state it should be used to specify menu items' backgrounds, but thought it was worth a shot with list items).
Another thing tried, adding android:visible="true" to each of the selector and item definitions. The StateListDrawable docs seem to indicate that the "Provides initial visibility state of the drawable; the default value is false", but adding this changed nothing.
EDIT2: So, based on the research done below by Qberticus, it seems that there can be only one set of list selectors per view, which confirms the list selector behavior. I can also confirm that setting the android:drawSelectorOnTop does move the selector IN FRONT of the selected item, but this of course obscures the item itself such that I only see the selector itself (which in my case is a colored shape).
Here is what the list looks like with backgrounds set:
Due to the set background, there is no change in appearance when items are selected. If I change the android:drawSelectorOnTop directive to true and select an item, I get:
And finally, if I set no background image for the list items, the selector works as expected, but of course, there are no background images as the last rule of the StateSelector does not appear to be followed (shouldn't it act as a catchall?) for non-selected items meaning no nice custom rounded shapes:
So, my problem remains; if I don't set a background for each list item, I can see the selector working BUT the items have no background when not selected. If I set a background for the item, they look great when not selected, but the background obscures the selector. Is it simply not possible to have a uniquely shaped list item with working selectors?
Thanks for anyone else who can weight in.
Figured this out, the issue was that while I was setting the listSelector for the ListView to the State List correctly via android:listSelector="#drawable/list_selector", I also needed to set the background for the list item to another State List via android:background="#drawable/list_background"
In the list_background.xml state list, I have:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:visible="true">
<!-- the list items are disabled -->
<item
android:state_window_focused="false"
android:drawable="#drawable/shape_row_disabled" />
<!-- the list items are enabled, in focus but not being touched/pressed (idle) -->
<item
android:state_window_focused="true"
android:state_pressed="false"
android:state_focused="false"
android:state_selected="false"
android:drawable="#drawable/shape_row" />
<!-- the catch-all -->
<item
android:drawable="#android:color/transparent" />
</selector>
Found the answer here:
Changing background color of ListView items on Android
In conjunction with my list selector above, it works perfectly.
The listSelector is only used to specify a View that will be drawn in the same place as the selected item View. I.e., there is only one instance of the listSelector per ListView. You can specify if it can draw on top or not using drawSelectorOnTop.
If you want all your Views to use a state list then you should specify that where the child Views are defined.
I'm using the source for AbsListView as reference. Specifically AbsListView#setSelector(Drawable), AbsListView#positionSelector, AbsListView#drawSelector, and AbsListView#dispatchDraw
AbsListView#drawSelector:
private void drawSelector(Canvas canvas) {
if (shouldShowSelector() && mSelectorRect != null && !mSelectorRect.isEmpty()) {
final Drawable selector = mSelector;
selector.setBounds(mSelectorRect);
selector.draw(canvas);
}
}
AbsListView#positionSelector:
void positionSelector(View sel) {
final Rect selectorRect = mSelectorRect;
selectorRect.set(sel.getLeft(), sel.getTop(), sel.getRight(), sel.getBottom());
positionSelector(selectorRect.left, selectorRect.top, selectorRect.right,
selectorRect.bottom);
final boolean isChildViewEnabled = mIsChildViewEnabled;
if (sel.isEnabled() != isChildViewEnabled) {
mIsChildViewEnabled = !isChildViewEnabled;
refreshDrawableState();
}
}
The source indicates that there is only one mSelector created/used and that it is positioned in the same bounding rect as the selected item.
You can assign default background for root layout and selector_background for child, in this case if item not selected then default background not obscures the selector. Its work for me.

Categories

Resources