ListView item won't stay "selected" - android

I want to change the background of a listview item when the user clicks it. Kind of like the Honeycomb settings page (Although I'm not dealing with just settings so I'm not using PreferenceActivity) I have this functionality working through a resource state selector state selector except for the cases when clicking on the listview menu changes the linear layout to the right of the listview (sort of a split screen view). I'm guessing the listview looses focus so state_pressed is no longer true.
<item android:state_pressed="true">
<shape >
<solid android:color="#color/blue1" />
</shape>
</item>
Any tips to keep that listview item colored until another listview item is selected? Thanks!
EDIT:
I was able to get the background changed in a setOnItemClickListener with
view.setBackgroundResource(R.color.red);
I only need one selected at a time so when the other list items are clicked, I tried lv.invalidate() and lv.getChildAt(0).invalidate() but neither worked and the second causes null pointer exception. Any ideas for putting the color back?

When you release your finger from the cell it no longer registers as pressed. What you are going to want to do is actually change the background of the individual row when a users selects is. This means implementing an onItemClick or onItemTouch and flagging the adapter to redraw the row with the new background. If you are already using a custom list adapter you can just implement a check against a boolean in your getView() method. You will also need to keep track which rows are 'selected' and which are not.
pseudocode:
public View getView(int pos, View convertView, ViewGroup parent) {
if(isChecked[pos]) //set background to checked color
}

Hope this help,
1.- Create a shape file for focused item: \drawable\list_selector_focused.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:angle="90" android:startColor="#f5c98c" android:endColor="#f7ddb8"/>
</shape>
2.- Create a shape file for pressed item: \drawable\list_selector_pressed.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:angle="90" android:startColor="#fb9d23" android:endColor="#ffc579" />
</shape>
3.- Create list selector file: \drawable\list_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#drawable/list_selector_pressed" />
<item android:state_focused="true" android:drawable="#drawable/list_selector_focused" />
<item android:drawable="#drawable/list_selector_focused" />
</selector>
4.- Add this attribute to your ListView in the layout file:
android:choiceMode="singleChoice"
android:listSelector="#drawable/list_selector"
You can use colors instead of gradient shapes,

This is implementation of sgarman idea:
package com.mypackage;
import java.util.Vector;
import com.myapp.R;
import com.myapp.data.Address;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class AddressesListAdapter extends BaseAdapter{
protected Context context;
protected LayoutInflater mInflater;
protected int itemResourceId;
protected Vector<Address> contentItems = new Vector<Address>();
protected Vector<Boolean> selectedStates;
private static final String TAG = "myapp";
public AddressesListAdapter(Context context, Vector<Address> contentItems) {
this.context = context;
this.contentItems = contentItems;
mInflater = LayoutInflater.from(context);
itemResourceId = R.layout.address_list_item;
selectedStates = new Vector<Boolean>();
//initial fill
clearSelectedState();
}
#Override
public int getCount() {
return contentItems.size();
}
#Override
public Object getItem(int position) {
return contentItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(itemResourceId, null);
holder = new ViewHolder();
holder.addressName = (TextView) convertView.findViewById(R.id.addressName);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Address address = (Address) contentItems.get(position);
holder.addressName.setText(address.getAddressName());
holder.addressName.setOnClickListener(new SetFocusListener(position));
//restore saved position from saving vector
if (selectedStates.get(position)) holder.addressName.setBackgroundColor(Color.BLUE);
else holder.addressName.setBackgroundColor(Color.TRANSPARENT);
return convertView;
}
private void clearSelectedState () {
selectedStates.clear();
for (int i = 0 ; i <= contentItems.size(); i++) {
selectedStates.add(new Boolean(false));
}
}
private class SetFocusListener implements View.OnClickListener {
private int position;
public SetFocusListener(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
//clear selected state vector
clearSelectedState();
//set selected position
selectedStates.set(position, new Boolean(true));
//refresh adapter to redraw focus
notifyDataSetChanged();
}
}
static class ViewHolder {
TextView addressName;
}
}
Th only concern that it may be to costly to setup new listener for every getView() iteration

The android state checked is best used to resolve this issue.
Someone mentioned using android:background="?android:attr/activatedBackgroundIndicator".
This just points to one of the activated_background_* resources in frameworks/base/core/res/res/drawable of the android source code. For example activated_background_holo_dark.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:drawable="#android:drawable/list_activated_holo" />
<item android:drawable="#color/transparent" />
</selector>
So essentially you want to use state_activated to represent when the user presses the button as well when it is in a checked (i.e. in a persistent selected state) state. Note that activated was only introduced after Honeycomb, if you are targeting older devices you'll need to rely on state_checked (more details here).
Now if you want to set an item as checked, you need to call listView.setItemChecked(position, true). You'll likely want to set the android:choiceMode property on your ListView to the appropriate value (e.g. if you want only one thing selected at a time use singleChoice). You don't need to invalidate, the call to setItemChecked will trigger a relayout which will update the view.
Also be careful if you allow reordering items in your ListView as the current checked item(s) will need to be updated. If you use stable Ids, this will be handled automatically.
To see an example of this in action, check out the NavigationDrawer sample code found in the training series: http://developer.android.com/training/implementing-navigation/nav-drawer.html.

By default, 'Selected' isn't the same as 'Clicked' when you're using a touch interface - something that cause me some real headaches when I started Android development.
To support both users that navigate by touch and users that use scrollwheels/trackballs, you might want to use setSelection, and do your manipulation in an AdapterView.OnItemSelectedListener implementation (set with setOnItemSelectedListener).
Another gotcha is that setSelection won't highlight an item if the last event was a touch event.
I'd recommend that you create a custom View for your list items, and handle highlighting in there.
Hope this helps,
Phil Lello

Ok, so I tried the solution above from where it says "This is implementation of sgarman idea:" This only works if SetFocusListener is an OnTouchListner. Ohterwise the onClick method consumes the click. I had to pair this solution with an OnItemClick listener on my list item to get the list to actually show the highlighted item.

I used android:state_activated="true" instead of state_selected. It works like a charm!

If you keep your listView through the whole activity you can do a mListView.isItemChecked(position) in the getView() method. And them set the background color depending on the result.

Have you tried android:state_selected="true" ?

try
android:background="?android:attr/activatedBackgroundIndicator"
;)

Related

Select items in RecyclerView

Similar question have been asked, but i can't get any of them work.
What i want is to select item in RecyclerView, change the background of that item view, and store the position of item selected.
The main problem is that you have onCreateViewHolder (in adapter), onBindViewHolder (in adapter) and ViewHolder constructor and everybody is working with different methods.
Now, i don't even know where to put onClickListener (in previous projects i've put it in ViewHolder), because people are suggesting the other two methods too.
My idea was to store each ViewHolder (or View) in list, so i can have reference to each row, and change the background from there. But that didn't work for me, because when i try to add to list of View(or ViewHolders), from any of three places (onCreateVH, onBindVH, VH class), my app crashes for some reason (null pointer ex).
Any suggestions? Where and how to implement it?
Make global variable to store position and handle click listener in ViewHolder. Onclick of item, change the global position value like
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
globalPosition=getAdapterPosition();
notifyDataSetChanged();
}
});
then in onBindViewHolder
if(postion==globalPosition)
{
//change color like
textview.setTextColor(Color.RED);
}
else
{
//revert back to regular color
textview.setTextColor(Color.WHITE);
}
with this code, the item you clicked get red colored and all other wiil be in white.
First of all, you asked where to put the onClickListener - you should put it in the onBindViewHolder. You can also attach a onClickListener in the ViewHolder class of your item like so:
public class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
As to implementing a single selection behaviour, the answers given here work but calling onNotifyDatasetChanged is bad for performance if you have a lot of items as it rebinds all views from scratch each time.
The link given by denvercoder9 is a good tutorial to understand a lot of things about setting up RecyclerView, but I think it makes single selection behaviour complicated. I am going to answer comprehensively giving everything one might need to make it work. Here's how I implemented the single selection behaviour:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final YourItemViewHolder itemViewHolder = (YourItemViewHolder) holder;
//This will remember which one was selected
itemViewHolder.getItemSelectionIndicator()
.setSelected(position == mSelectedPosition);
itemViewHolder.getItemWrapperView()
.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(mLogTag, "Tapped on " + position);
//This is the previous selection
notifyItemChanged(mSelectedPosition);
itemViewHolder.getItemSelectionIndicator().setSelected(true);
mSelectedPosition = position;
//This is the new selection
notifyItemChanged(position);
}
});
getItemSelectionIndicator() and getItemWrapperView() are methods inside the item's ViewHolder that return specific views from the item layout. A ItemWrapperView could be the top most Linear/RelativeLayout that wraps the entire item. Setting a click listener on it will ensure clicks work if user taps anywhere in the item's view.
ItemSelectionIndicator can be a Linear or RelativeLayout that has been set a state list drawable background. This means when it is set as selected, it shows a shape drawable automatically to indicate selection. When it is set as unselected, the drawable will be removed automatically. This is what the indicator view looks like:
<RelativeLayout
android:id="#+id/selection_indicator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/selection_indicator_state_list"/>
This is selection_indicator_state_list.xml in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Selected background -->
<item android:state_selected="true"
android:drawable="#drawable/item_selection_shape"/>
<!-- Unselected background -->
<item android:state_selected="false"
android:drawable="#color/transparent"/>
</selector>
And this is item_selection_shape.xml in res/drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
//22 is value of transparency, BDBDBD is the color
<solid android:color="#22BDBDBD"/>
<stroke android:width="2dp" android:color="#color/md_blue_600"/>
<corners
android:radius="3dp"/>
</shape>

ListView Clicked Item Highlight not working properly

I have a ListView and have a onClickListener for this ListView.
ListView is using the SimpleAdapter, and populating the Data via a map.
Whenever Item is clicked, that List Item is getting highlighted.
But the problem is, Suppose I click the 4th Item on the List and scroll the list, then every 4th element is highlighted. I'm using a Selector xml to implement the highlight functionality
I know the problem is due to the screen refresh.
But how can I avoid this problem?
Searching for the answers from about a month now. I need a solution now.
Thanks in advance.
Selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/drawer_icon_normal" android:state_selected="false" android:state_pressed="false"/>
<item android:drawable="#drawable/drawer_icon_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/drawer_icon_activated" android:state_selected="true"/>
</selector>
Below is the code for populating the listView and onclick functionality.
//Note this code is not using the selector, how with this code also, functionality is same.
public void populateListView() {
//Populate the List View Here
//Set the adapter
SimpleAdapter flvadapter = new SimpleAdapter(getActivity(), finalSongList, android.R.layout.simple_list_item_1, new String[]{"filename"}, new int[]{android.R.id.text1});
fileListView.setAdapter(flvadapter);
fileListView.setBackgroundColor(Color.WHITE);
fileListView.setTextFilterEnabled(true);
fileListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//Registering the OnItemClicklistener
fileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3) {
//TODO Auto-generated method stub
//fileListView.getItemAtPosition(position);
updateView(position);
index = position;
#SuppressWarnings("unchecked")
HashMap<String, String> hm = (HashMap<String, String>) fileListView.getItemAtPosition(position);
if (hm.get("fileuri") == null) {
AlertDialog.Builder adb = new AlertDialog.Builder(getActivity());
adb.setTitle("ListView OnClick");
adb.setMessage("Selected Item is = " + hm.get("fileuri"));
adb.setPositiveButton("Ok", null);
adb.show();
} else {
//Processing the Selected File
}
}
});
}
private void updateView(int index){
//View v=fileListView.getChildAt(index-fileListView.getFirstVisiblePosition());
selectedListViewItem=fileListView.getChildAt(index);
fileListView.setBackgroundColor(Color.WHITE);
if (selectedListViewItem != null) {
selectedListViewItem.setBackgroundColor(Color.CYAN);
}
}
In your updateView() function, you are changing the selectedListViewItem's background color. up to this point everything works like you would assume however when you scroll, every so ofter another row will already be "selected" even though you didn't do it yourself.
That is caused by view recycling, a function of Listview adapters that allow them to load faster by taking a row that has been scrolled out of the screen, fill it with new data and present it as is (without needing to inflate it from XML again.
Basically it will take your old blue row that is not on the screen anymore, put a new string in and display it as the new row.
The way you fix it is by implementing your own Adapter and overriding the getView method. there are a ton of resources that will show you how to do that. Here is one
One thing to keep in mind, once you implement your custom Adapter is that you will have to keep track of which items have been clicked so you can un-highlight and re-highlight items correctly.
you are changing the background color of the selected item but not reset it in the adapter
try to post your adapter code
so check in adapter getView method
if item is selected
setBackgroudColor for selected row
else
setBackgroundColor for normal row

list item row color issue android

I have implemented custom adapter for list items. I have two requirements
1) list items should have alternate colors. To implement that, i have below code
private final int[] bgColors = new int[] {R.color.list_bg_1, R.color.list_bg_2};
int colorPosition = position % bgColors.length;
convertView.setBackgroundResource(bgColors[colorPosition]);
2) when you click on list item, it should highlight
Drawable selectedBackground;
selectedBackground = context.getResources().getDrawable(R.color.backgroundColor);
if (selectedPos == position) {
convertView.setBackgroundDrawable(selectedBackground);
} else {
convertView.setBackgroundDrawable(null);
}
// this method is called in onItemClick in Activity.
public void setSelectedPosition(int pos){
selectedPos = pos;
notifyDataSetChanged();
}
Problem: when I put both code, either of the functionality doesn't work. How can I make sure that both functionality works with above code?
You should create a selector.xml file for the background and then set the background of the view to that selector name. The selector lets you choose a background for each state of the view; whether or not the view is selected, pressed, etc.
i.e.,
You have a xml file called my_views_background_selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true"
android:drawable="#drawable/selectedBackground" />
<item android:state_pressed="true"
android:drawable="#drawable/pressedBackground" />
<item android:drawable="#drawable/regularBackground"/>
</selector>
And then you can either set the background programatically by doing
convertView.setBackgroundResource(R.drawable.my_views_background_selector)
Or in the xml file that you used to inflate your convertedView

Multi-pane layout

I'd like to create an application for tablets using 2 panels. The left one as a menu and the right one as a content presenter. In fact the behavior I expect is similar to the one in Gmail app.
I'm currently using 2 fragments. One is basically a ListView with room names plus some buttons. The other one (the content) includes some information about the selected room.
The room I select in the left panel should stay highlighted - like in the Gmail app. I was trying for many hours to achieve this effect using selectors, but failed.
Moreover I found 2 different opinions about this approach..
1) "Do not try to keep the focus or selection in touch mode"
2) "In general, use the pane on the right to present more information about the item you selected in the left pane. Make sure to keep the item in the left pane selected in order to establish the relationship between the panels."
Can you tell me how to achieve this (just to keep the selected item distinguished from the rest)?
Maybe a ListView isn't the best approach here?
UPDATE
Thanks to Christoph Eberhardt's answer I created a sample project that works fine. It's available on github.
Create an xml file in res/drawable/list_item_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#drawable/list_pressed" />
<item android:drawable="#drawable/list_default" />
</selector>
For the list elements make an own xml file res/layout/list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingLeft="20dp"
android:background="#drawable/list_item_selector"
/>
Then when creating the list adapter do:
setListAdapter(new CustomAdapter<String>(getActivity(),
R.layout.list_item, stringArray));
Now all you have to do is providing the drawables list_default and list_pressed and list_altered
The CustomAdpater looks like:
package com.test.listview_keep_selected;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.StateListDrawable;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class CustomAdapter<T> extends ArrayAdapter<T> {
private Context m_cContext;
public CustomAdapter(Context context, int textViewResourceId,
T[] objects) {
super(context, textViewResourceId, objects);
this.m_cContext = context;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View returnView = super.getView(position, convertView, parent);
final ListView listView = (ListView) ((Activity) m_cContext).findViewById(R.id.listViewTest);
returnView.setOnClickListener(new OnClickListener(
) {
#Override
public void onClick(View v) {
for(int i = 0; i< listView.getChildCount(); i++)
listView.getChildAt(i).setSelected(false);
StateListDrawable states = new StateListDrawable();
states.addState(new int[] {android.R.attr.state_selected},
m_cContext.getResources().getDrawable(R.drawable.list_pressed));
states.addState(new int[] { },
m_cContext.getResources().getDrawable(R.drawable.list_altered));
v.setBackgroundDrawable(states);
v.setSelected(true);
}
});
return returnView;
}
}
Edit:
And if you don't have it already:
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
Edit:
Don't set the choice mode with a plain ListView, only makes sense if you have e.g. a ListFragment as I have in my code
It's not perfect now, but from now on you should be fine after playing around a bit.
What also might help is: ListView item background via custom selector
Edit:
Now it should work as you want it^^

How to highlight row in ListView in Android?

I need to highlight a row in a ListView that was selected (to show the user what he chose), so, it's not the one that is going to be chosen, it's the one he chose before.
I already have the location by:
ListView.setSelection(position);
And now what I want is to select this specific row and to highlight it.
The code of the onCreate() in the activity that contains the ListView:
public class CountryView extends Activity
{
protected static final String LOG_TAG = null;
/** Called when the activity is first created. */
String[] lv_arr = {};
ListAdapter adapter;
TextView t;
private ListView lvUsers;
private ArrayList<Coun> mListUsers;
String responce=null;
public int d;
int selectedListItem = -1;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.country);
Intent data =getIntent();
mListUsers = getCoun();
lvUsers = (ListView) findViewById(R.id.counlistView);
lvUsers.setAdapter(new ListAdapter(this, R.id.counlistView, mListUsers));
selectedListItem=data.getExtras().getInt("PositionInList");
lvUsers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvUsers.setOnItemClickListener(new OnItemClickListener()
{
int positionItem;
public void onItemClick(AdapterView<?> parent, View view,int position, long id)
{
Intent pongIntent = new Intent(getApplicationContext(),Trav.class);
int counId=mListUsers.get(position).id;
pongIntent.putExtra("response",mListUsers.get(position).p);
pongIntent.putExtra("responseCounID",counId);
//Put the position of the choose list inside extra
positionItem=position;
pongIntent.putExtra("PositionInListSet",positionItem);
setResult(Activity.RESULT_OK,pongIntent);
Log.i("CounID *******************************"," "+counId);
finish();
}
});
}
}
Since by default ListViews are set to a selection mode of NONE, in touch mode the setSelection method won't have visual effect.
For keeping the previous selection / visually display an explicit selection, first you must set your listview's choice mode appropriately:
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
It's useful to read the API Docs of these methods:
setSelection
void android.widget.AdapterView.setSelection(int position)
Sets the currently selected item. To
support accessibility subclasses that
override this method must invoke the
overriden super method first.
Parameters:
position Index (starting at 0) of the data item to be selected.
setChoiceMode
void android.widget.ListView.setChoiceMode(int choiceMode)
Defines the choice behavior for the
List. By default, Lists do not have
any choice behavior
(CHOICE_MODE_NONE). By setting the
choiceMode to CHOICE_MODE_SINGLE, the
List allows up to one item to be in a
chosen state. By setting the
choiceMode to CHOICE_MODE_MULTIPLE,
the list allows any number of items to
be chosen.
Parameters: choiceMode One of CHOICE_MODE_NONE,
CHOICE_MODE_SINGLE, or CHOICE_MODE_MULTIPLE
In case this is not enough (say you'd like to always show the last selection differently beside the current selection), you should store your last selected item (a data which populates the ListAdapter) as lastSelectedItem, and in your adapter's getView method assign a different background resource to the renderer if it equals this lastSelectedItem.
If your last selection wouldn't refresh on selection change, you should explicitly call the notifyDataSetChanged method on your adapter instance.
Update
Since your activity containing the ListView is a child of an activity which waits for this one's result (based on the setResult(Activity.RESULT_OK,pongIntent); part), the initial idea is correct, the last position should be passed through the intent when starting the activity:
selectedListItem = getIntent().getIntExtra("PositionInList", -1);
lvUsers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvUsers.setSelection(selectedListItem);
The ListView.CHOICE_MODE_SINGLE solution would work if you remain in the same activity, but you are finishing it on every itemClick (selection change), that's why the extra data should be passed to the starting Intent.
You can also set the previously selected item's background from your adapter -as mentioned above-, overriding its getView method:
lvUsers.setAdapter(new ArrayAdapter(this, R.id.counlistView, groups)
{
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
final View renderer = super.getView(position, convertView, parent);
if (position == selectedListItem)
{
//TODO: set the proper selection color here:
renderer.setBackgroundResource(android.R.color.darker_gray);
}
return renderer;
}
});
Just:
Set the correct choice mode in your list view. setChoiceMode
Set a background to support the selection state in you item layout, like:
android:background="?android:attr/activatedBackgroundIndicator"
FYI:
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
http://android-developers.blogspot.mx/2008/12/touch-mode.html
It's much easier to implement this in your layout files and let Android handle the rest...
1) Make sure you have android:choiceMode="" set on your ListView layout (singleChoice, multipleChoice, etc). By default it is set to none.
<ListView
android:id="#+id/invite_friends_fragment_contacts_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="multipleChoice"/> <!-- THIS LINE -->
2) Create a state selector XML file and save it in your drawables folder. In this example, we'll name it state_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/blue" android:state_selected="true"/>
<item android:drawable="#android:color/blue" android:state_activated="true"/>
<item android:drawable="#android:color/transparent"/>
</selector>
3) In your list item layout, add the state_selector.xml file as the background:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/state_selector"> <!-- THIS LINE -->
<!-- ALL OF YOUR ELEMENTS WILL GO HERE (TextViews, ImageViews, etc) -->
</RelativeLayout>
If you are using multipleChoice, you can override onItemClick()and set/unset selected items accordingly. Android will change the background color as specified in your state_selector.xml file.
I had a problem finding an easy solution to this because so many tutorials and answers contained information on single select via radio buttons (Which relied heavily on RadioGroup's).
My problem was that I could set the item to my "Highlighted" state but then couldn't reset the list when the next item was selected. Here is what I came up with:
listView.setOnItemClickListener(new ItemHighlighterListener ());
With this class:
private class ItemHighlighterListener implements OnItemClickListener{
private View lastSelectedView = null;
public void clearSelection()
{
if(lastSelectedView != null) lastSelectedView.setBackgroundColor(android.R.color.transparent);
}
#Override
public void onItemClick(AdapterView<?> arg0, View view, int arg2, long arg3) {
clearSelection();
lastSelectedView = view;
view.setBackgroundDrawable(view.getContext().getResources().getDrawable(R.drawable.shape_selected_menu_item));
}
}
I solve this problem in the following way:
1. set a lastClickId, when click the item in listView, update the lastClickId to position value, then update the view's background.
After this, when we click one item, this item will be highlighted, but when we scroll the listView(make the item which we selected out of the screen) and scroll back, the highlight is gone, because the method getView() rerun in your adapter, so, we have to do the next thing.
2. in your adapter, change the background in the method getView(), here is the code:
private static int lastClickId = -1;
private OnItemClickListener listener = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
if ((lastClickId != -1) && (lastClickId != position)) {
parent.getChildAt(lastClickId).setBackgroundResource(
R.color.grey);
view.setBackgroundResource(R.color.blue);
}
if (lastClickId == -1) {
view.setBackgroundResource(R.color.blue);
}
lastClickId = position;
}
};
public static int getCurrentSelectedItemId() {
return lastClickId;
}
Adapter:
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = mInflater.inflate(R.layout.tweet_list_layout, null);
// set selected item's background to blue
if (position == MainUserFeedFragment.getCurrentSelectedItemId()) {
view.setBackgroundResource(R.color.blue);
}
}
Why dont you store the selections in an array, then pass that array in the constructor of the ListView Array Adapter, something like myArrayAdapter(context,layoutID,dataArray,selectionArray)
then in your getView method for the arrayadapter, just do a check. For example in pseudocode
if row was previously selected
change background color
You can use transition. Follow my code because i have achieved highlighting of specific listview item by choice
Lets say you want to highlight first item for 5 seconds.
if(position == 0){
viewHolderThubnail.relImage.setBackgroundResource(R.drawable.translate);
TransitionDrawable transition = (TransitionDrawable) viewHolderThubnail.relImage.getBackground();
transition.startTransition(1000);
}else{
viewHolderThubnail.relImage.setBackgroundResource(R.color.white);
}
translate.xml
<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<!-- The drawables used here can be solid colors, gradients, shapes, images, etc. -->
<item android:drawable="#drawable/new_state" />
<item android:drawable="#drawable/original_state" />
</transition>
new_state.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#92BCE7"/>
</shape>
original_state.xml
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF"/>
</shape>
If you understood this code, which is very simple i must say, then the listview item at zero'th position will highlight in blue color for 5 seconds and then it will slow fade to white color.
The SIMPLEST of all
View updatedview=null;
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//these two lines of code means that only one item can be selected at a time
if(updatedview != null)
updatedview.setBackgroundColor(Color.TRANSPARENT);
updatedview=view;
Toast.makeText(getApplicationContext(), " " + str[position],Toast.LENGTH_LONG).show();
view.setBackgroundColor(Color.CYAN);
}

Categories

Resources