Make ListView Item Selection remain Stable - android

How to make ListView Item Selection remain stable ?
<ListView
android:id="#+id/list_slidermenu"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="8"
android:layout_gravity="start"
android:scrollbars="none"
android:fastScrollEnabled="true"
android:choiceMode="singleChoice"
/>

You've to make getSelectedIndex() and setSelectedIndex() method in your adapter.
private int selectedIndex;
public int getSelectedIndex() {
return selectedIndex;
}
public void setSelectedIndex(int index) {
this.selectedIndex = index;
// Re-draw the list by informing the view of the changes
notifyDataSetChanged();
}
and then
#Override
public View getView(int position, View convertView, ViewGroup parent) {
.......
// Highlight the selected item in the list
if (selectedIndex != -1 && selectedIndex == position) {
v.setBackgroundResource(R.color.yourColor);
}
return v;
}
and used from onListItemClick(....)
adapter.setSelectedIndex(position);
Another way as #Sun said
Used gradient to make list selection remain stable
gradient_bg.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
gradient_bg_hover.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
list_selector.xml:-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="#drawable/gradient_bg_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg_hover" />
</selector>
finally in ListView, use listSelector property like below:
android:listSelector="#drawable/list_selector"

I have used gradient to make list selection remain stable
gradient_bg.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
gradient_bg_hover.xml:-
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#7ecce8"
android:centerColor="#7ecce8"
android:endColor="#7ecce8"
/>
</shape>
list_selector.xml:-
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg" />
<item android:state_pressed="true"
android:drawable="#drawable/gradient_bg_hover" />
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/gradient_bg_hover" />
</selector>
finally in ListView, use listSelector property like below:
android:listSelector="#drawable/list_selector"

You need to keep track of selected item and accordingly change the background of the list row.
1.Change the selected item's position in item click :
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,int position, long arg3) {
adapter.setSelectedItem(position);
}
2.Get selected item and set background :
public class AudioAdapter extends ArrayAdapter<Audio> {
Integer selected_position = -1;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Your Code
if (position == selected_position) {
// set selected color
v.setBackgroundResource(R.color.yourSelectedColor);
} else {
// set default color
v.setBackgroundResource(R.color.yourDefaultColor);
}
}
public int getSelectedItem() {
return selected_position;
}
public void setSelectedItem(int index) {
this.selected_position = index;
}
}
Hope it helps ツ

Related

How to make a View looks like it is being selected programmatically, if background is ?android:attr/selectableItemBackground (ListView in AlertDialog)

I pretty like the selector behavior generated in navigation drawer.
It has ripple effect.
Its ImageView and TextView has proper color, when being selected.
In my dialog, I try to achieve the same effect, by using the following layout.
label_array_adapter.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?android:attr/selectableItemBackground"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView
android:duplicateParentState="true"
android:id="#+id/image_view"
android:paddingStart="24dp"
android:paddingLeft="24dp"
android:paddingEnd="16dp"
android:paddingRight="16dp"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="?attr/labelIconSelector" />
<TextView
android:duplicateParentState="true"
android:textSize="16sp"
android:id="#+id/text_view"
android:layout_width="0dp"
android:width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:textColor="?attr/labelTextViewColorSelector" />
</LinearLayout>
labelIconSelector
<?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_label_white_24dp"
android:tint="#color/colorPrimaryBrown" />
</item>
<item>
<bitmap android:src="#drawable/ic_label_white_24dp"
android:tint="#ff757575" />
</item>
</selector>
labelTextViewColorSelector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="#color/colorPrimaryBrown" />
<item android:color="#color/primaryTextColorLight" />
</selector>
In my ArrayAdapter, I try to programmatically select the 1st item via view.setSelected(true)
public class LabelArrayAdapter extends ArrayAdapter<TabInfo> {
private static class ViewHolder {
public final ImageView imageView;
public final TextView textView;
public ViewHolder(View view) {
imageView = view.findViewById(R.id.image_view);
textView = view.findViewById(R.id.text_view);
Utils.setCustomTypeFace(textView, Utils.ROBOTO_REGULAR_TYPE_FACE);
}
}
public LabelArrayAdapter(#NonNull Context context, List<TabInfo> tabInfos) {
super(context, R.layout.label_array_adapter, tabInfos);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = null;
if (convertView == null) {
LayoutInflater inflator = LayoutInflater.from(this.getContext());
view = inflator.inflate(R.layout.label_array_adapter, null);
final ViewHolder viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
// Not sure why this is required.
view.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, Utils.dpToPixel(48)));
} else {
view = convertView;
}
ViewHolder holder = (ViewHolder) view.getTag();
TabInfo tabInfo = getItem(position);
if (tabInfo == null) {
holder.imageView.setVisibility(View.INVISIBLE);
holder.textView.setText("(No label)");
} else {
holder.imageView.setVisibility(View.VISIBLE);
holder.textView.setText(tabInfo.getName());
}
if (position == 0) {
view.setSelected(true);
} else {
view.setSelected(false);
}
return view;
}
}
This is how I try to show Dialog via DialogFragment.
return new AlertDialog.Builder(getActivity())
.setTitle("Move to")
.setAdapter(new LabelArrayAdapter(this.getContext(), customTabInfos), (dialog, which) -> {
})
.create();
However, it doesn't work as you can see in the following screenshot. The 1st item doesn't look like it is being selected.
May I know, is there anything I had missed out?
How to make a View looks like it is being selected programmatically, if its background is ?android:attr/selectableItemBackground (ListView in AlertDialog)
Update
Using
alertDialog.getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
alertDialog.getListView().setSelection(position);
wouldn't help either.
Here is an approach using a layer list drawable as the background for the view group that represents the item being selected.
First, for API 21+, we define a layer list drawable that displays the selected color when the item is selected. A call to View#setSelected() must be made for this to have an effect.
layer_list.xml (v21)
color/selected is #2000ffe5 for the demos.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector>
<item
android:drawable="#color/selected"
android:state_selected="true" />
</selector>
</item>
<item
android:id="#+id/selectableBackground"
android:drawable="?android:selectableItemBackground" />
</layer-list>
For API < 21, we cannot use android:drawable="?android:selectableItemBackground" in the layer list, so we will fall back to an alternate but similar visual cue.
layer_list < API 21
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<selector android:exitFadeDuration="#android:integer/config_shortAnimTime">
<item
android:drawable="#color/selected"
android:state_pressed="false"
android:state_selected="true" />
<item
android:drawable="#color/selectable_background"
android:state_pressed="true" />
</selector>
</item>
</layer-list>

Highlight selected item in ListView on Android

I have been making an application that works with ListViews in Android, and I can't make it so that the selected (chacked) item has a different background. I'm using CHOICE_MODE_SINGLE. This is how my code looks so far:
The ListView that I use:
(inside layout.xml)
<ListView
android:id="#+id/listView"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:choiceMode="singleChoice"
android:listSelector="#drawable/selector_test" >
</ListView>
The TextView layout I use in the adapter:
(listItem.xml)
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/listItem"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="23sp"
android:textStyle="bold" />
This is where I add the adapter:
mListAdapter = new ArrayAdapter<String>(this, R.layout.listItem, mList);
mListView = (ListView) findViewById(R.id.listView);
mListView.setAdapter(mAuthorAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
String selected = mList.get(position);
// ...
mListView.setItemChecked(position, true);
}
});
I'm sure that the proper item is checked on click, because when I call getCheckedItemPosition(), it returns the proper value.
And now, the two things I tried in order to highlight the checked item:
Selector drawable:
(selector_test.xml)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" android:enterFadeDuration="#android:integer/config_longAnimTime">
<item android:state_checked="true"><shape>
<solid android:color="#color/red" />
</shape></item>
<item android:state_selected="true"><shape>
<solid android:color="#color/blue" />
</shape></item>
<item android:state_pressed="true"><shape>
<solid android:color="#color/green" />
</shape></item>
</selector>
I add it to .xml with:
android:listSelector="#drawable/selector_test"
Background drawable:
(background_test.xml)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/red" android:state_checked="true"/>
<item android:drawable="#color/blue" android:state_selected="true"/>
<item android:drawable="#color/green"/>
</selector>
I add it to .xml with:
android:background="#drawable/background_test"
I've tried adding the selector and the background to both listView.xml and listItem.xml, but the only thing that changes is the default background color, and the color of the selector when the item is pressed (or held).
android:state_checked="true" and android:state_selected="true" seem to do nothing.
I can change the background by overriding the getView() method in ArrayAdapter and invoking setBackgroundColor() in it if the view is selected, and it does change the background, but also gets rid of the selector entirely. Also, I don't really like to override classes just to change one line of code, especially if that same thing can be achieved in a different way.
So what I'm asking is, is there a way to highlight checked item in ListView by adding a selector or background drawable to it, and I am just doing it wrong, or will I have to make it work some other way.
Thanks in advance! :)
add this line in onStart of your activity
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
where lv is instance of listView
then override this method and add the following lines to it.
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
// Set the item as checked to be highlighted
lv.setItemChecked(position, true);
v.setBackgroundColor(Color.BLUE);
conversationAdapter.notifyDataSetChanged();
}
and then change the color of previous selected item's background back to normal in getView method of your custom adapter
Try this:
listViewDay.setItemChecked(position, true);
listViewDay.setSelection(position);
listitem.xml
<?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="40dp"
android:background="#drawable/list_day_selector" >
<TextView
android:id="#+id/txtItemDay"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
android:text="22"
android:textColor="#android:color/white"
android:textSize="22sp" />
</LinearLayout>
list_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/list_item_bg_normal" android:state_activated="false"/>
<item android:drawable="#drawable/bg_with_left_arrow" android:state_pressed="true"/>
<item android:drawable="#drawable/bg_with_left_arrow" android:state_activated="true"/>
</selector>
Programmatically, use setSelector. For example:
lv.setSelector(R.color.abc_background_cache_hint_selector_material_dark);
After some hours of encountering one glitch after another (including the selector leaving a dirty stripe), I decided to do it myself:
class MyListAdapter extends ArrayAdapter<MyData> {
// !!! access to the current selection
int mSelected = 0;
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = super.getView(position, convertView, parent);
// !!! this is where the selected item is highlighted
v.findViewById(R.id.selectionSign).setVisibility(position == mSelected ? View.VISIBLE : View.INVISIBLE);
return v;
}
public CommandListAdapter(Context context, List<MyData> objects) {
super(context, R.layout.mylistitem, R.id.mytext, objects);
}
}
with the OnItemClickListener:
mMyListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
setSelectionPosNoUpd(position);
update();
}
});
and the functions defined as:
void setSelectionPosNoUpd(int n) {
mCommandListAdapter.mSelected = n;
//update();
}
void update() {
mListViewOfCommands.smoothScrollToPosition(getSelectionPos());
mCommandListAdapter.notifyDataSetChanged();
}
and the list item XML (res/layout/mylistitem.xml) is:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/mytext"
/>
</LinearLayout>
<View
android:id="#+id/selectionSign"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#10ff5000"
android:visibility="invisible"
/>
</FrameLayout>
The downside is that after changing the selection I have to update(): there is no easy way to unhighlight the previously highlighted view.
Set item state in selector like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true"
android:color="#color/XXX/>
</selector>
I don't know why state_checked not working. At first I thought it must be a Checkableview then I tried CheckedTextView. Still not working.
Anyway, state_activated will solve the problem.
I think you cann't use mListView inside anonymous class. You must use AdapterView arg0
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View view,
int position, long id) {
AnyObject obj=(AnyObject)arg0.getItemAtPosition(position);
........
.........
.........
}
});
This post has worked out for me: http://www.mynewsfeed.x10.mx/articles/index.php?id=14
The ListView (inside layout.xml):
<ListView
android:id="#+id/list"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="#drawable/list_custom"
android:choiceMode="singleChoice"/>
Selector drawable(list_custom.xml):
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#color/orange"/>
<item android:state_activated="true" android:drawable="#color/blue" />
<item android:drawable="#color/green" />
</selector>
Color.xml in values folder:
<resources>
<item name="blue" type="color">#FF33B5E5</item>
<item name="green" type="color">#FF99CC00</item>
<item name="orange" type="color">#FFFFBB33</item>
</resources>

Setting background programmatically overrides drawable

I have a ListView and I have a Drawable for each item in the ListView to highlight each row when it's selected/pressed. I also have a custom adapter where I'm programatically setting the background color of each row (I want to have alternating background colors). This is a new feature I added and before adding the code the rows would highlight blue, but after they do not highlight. Not sure how to fix it. Here is what I have:
ListView item layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:paddingTop="8dip"
android:paddingBottom="8dip"
android:background="#drawable/app_selector"
>
<TextView
android:id="#+id/text"
style="#style/ListingTitle"
android:layout_alignParentTop="true"
android:paddingBottom="2dip"
/>
</RelativeLayout>
Drawable
<?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/light_blue" />
<item android:state_selected="true" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_activated="true" android:state_selected="false" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_selected="false" android:state_pressed="false" android:drawable="#android:color/transparent" />
</selector>
Fragment
public class ListingFragment extends SherlockListFragment
{
public void onActivityCreated(final Bundle icicle)
{
ListView lv = getListView();
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mListView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
#Override
public void onItemCheckedStateChanged(android.view.ActionMode mode, int position, long id, boolean checked) {
}
#Override
public boolean onActionItemClicked(android.view.ActionMode mode, android.view.MenuItem item) {
}
}
}
/* ADAPTER */
private class CustomAdapter extends BaseAdapter
{
#Override
public View getView(final int position, View convertView, final ViewGroup parent)
{
final ViewHolder holder;
if (convertView == null)
{
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, parent, false);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
if (position % 2 == 0)
convertView.setBackgroundColor(Color.GRAY);
else
convertView.setBackgroundColor(Color.TRANSPARENT);
return(convertView);
}
}
}
Expanding on dum's answer, you don't need to do all that work in code.
Drawable A
<?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/light_blue" />
<item android:state_selected="true" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_activated="true" android:state_selected="false" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_selected="false" android:state_pressed="false" android:drawable="#android:color/transparent" />
</selector>
Drawable B
<?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/light_blue" />
<item android:state_selected="true" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_activated="true" android:state_selected="false" android:state_pressed="false" android:drawable="#color/light_blue" />
<item android:state_selected="false" android:state_pressed="false" android:drawable="#android:color/gray" />
</selector>
In your Adapter:
if (position % 2 == 0) {
convertView.setBackgroundResource(R.drawable.A);
} else {
convertView.setBackgroundResource(R.drawable.B);
}
instead of changing the drawable with plain color, first create a new drawable programmatically and set the states just like in your xml and then set colors for each state. then try replacing your background with your programmatically created drwable.

Change background color of selected item on a ListView

I want to know on how I can change the background color of the selected item on my listView. I only want to change the specific item clicked by the user, meaning if the user clicks another item it will be the one which is highlighted. Well since I want it to keep simple as possible and use the default android listview I used this code instead:
record_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
try{
for (int ctr=0;ctr<=record_items.length;ctr++){
if(i==ctr){
record_list.getChildAt(ctr).setBackgroundColor(Color.CYAN);
}else{
record_list.getChildAt(ctr).setBackgroundColor(Color.WHITE);
}
}
}
catch (Exception e){
e.printStackTrace();
}
Log.v("Selected item",record_list.getItemAtPosition(i));
}
});
Ok this one is working but the problem is that it's slow. Now I want to know if there's any other way around that I can do which will give the same output as I made.
I tried using record_list.getSelectedView().setBackgroundColor(Color.CYAN); but it gives me a null pointer exception.
I also tried the selector.xml but it also didn't do the trick.
Furthermore, there is one properties here on ListView which is called listSelector. It's a drawable as said by the documentation "Drawable used to indicate the currently selected item in the list." I also believe that this should do the trick and yes it do the trick on my emulator but not on my galaxy tab. I also tried the other methods but nothing works as I wanted it to be.
You can keep track the position of the current selected element:
OnItemClickListener listViewOnItemClick = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapter, View arg1, int position, long id) {
mSelectedItem = position;
mAdapter.notifyDataSetChanged();
}
};
And override the getView method of your adapter:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view = View.inflate(context, R.layout.item_list, null);
if (position == mSelectedItem) {
// set your color
}
return view;
}
For me it did the trick.
You can use a selector. Change the colors values and modify the below according to your needs.
bkg.xml in drawable folder
<?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="false"
android:drawable="#drawable/normal" />
</selector>
pressed.xml in drawable folder
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FF1A47"/> // color
<stroke android:width="3dp"
android:color="#0FECFF"/> // border
<padding android:left="5dp"
android:top="5dp"
android:right="5dp"
android:bottom="5dp"/>
<corners android:bottomRightRadius="7dp" // for rounded corners
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp"/>
</shape>
normal.xml in drawable folder
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dp"
android:color="#0FECFF" />
<padding android:left="5dp"
android:top="5dp"
android:right="5dp"
android:bottom="5dp"/>
<corners android:bottomRightRadius="7dp"
android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp"
android:topRightRadius="7dp"/>
</shape>
Set the background drawable to listview custom layout to be inflated for each row
I recommend using a custom listview with a custom adapter.
android:background="#drawable/bkg"
If you have not used a custom adapter you can set the listselector to listview as below
android:listSelector="#drawable/bkg"
Define variable
private ListView mListView;
Initialize variable
mListView = (ListView)findViewById(R.id.list_view);
OnItemClickListener of listview
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adpterView, View view, int position,
long id) {
for (int i = 0; i < mListView.getChildCount(); i++) {
if(position == i ){
mListView.getChildAt(i).setBackgroundColor(Color.BLUE);
}else{
mListView.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
}
}
}
});
Build and run the project - Done
If you want to have the item remain highlighted after you have clicked it, you need to manually set it as being selected in the onItemClick listener
Android ListView selected item stay highlighted:
myList.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.setSelected(true); // <== Will cause the highlight to remain
//... do more stuff
}});
This assumes you have a state_selected item in your selector:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:state_pressed="true" android:drawable="#color/red" />
<item android:state_enabled="true" android:state_focused="true" android:drawable="#color/red" />
<item android:state_enabled="true" android:state_selected="true" android:drawable="#color/red" />
<item android:drawable="#color/white" />
</selector>
Method 1:
Update ListView in the your xml layout activity/fragment:
<ListView
...
android:choiceMode="singleChoice"
android:listSelector="#android:color/darker_gray"
/>
That's it, you're done!
If you want a programmatic way to handle this then use method 2...
Method 2:
If you're using a ListFragment you can override onListItemClick(), using the view to set the colour. Save the current View selected to reset the colour of the last selection.
Please note, this only works on listviews that fit on one screen, as the view is recycled.
public class MyListFragment extends ListFragment {
View previousSelectedItem;
...
#Override
public void onListItemClick(ListView parent, View v, int position, long id) {
super.onListItemClick(parent, v, position, id);
if (previousSelectedItem!=null) {
previousSelectedItem.setBackgroundColor(Color.WHITE);
}
previousSelectedItem=v;
v.setBackgroundColor(Color.BLUE);
}
}
First you can create selector xml file like below in your drawable folder 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_activated="true">
<shape android:shape="rectangle">
<solid android:color="#333333" />
<padding android:left="5dp" android:right="5dp" />
</shape></item>
<item><shape android:shape="rectangle">
<solid android:color="#222222" />
</shape></item>
</selector>
And then in your listview specify background as
android:background="#drawable/list_item_selector"
For those wondering what EXACTLY needs to be done to keep rows selected even as you scroll up down. It's the state_activated The rest is taken care of by internal functionality, you don't have to worry about toggle, and can select multiple items. I didn't need to use notifyDataSetChanged() or setSelected(true) methods.
Add this line to your selector file, for me drawable\row_background.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#android:color/holo_blue_light"/>
<item android:state_enabled="true" android:state_pressed="true" android:drawable="#android:color/holo_blue_light" />
<item android:state_enabled="true" android:state_focused="true" android:drawable="#android:color/holo_blue_bright" />
<item android:state_enabled="true" android:state_selected="true" android:drawable="#android:color/holo_blue_light" />
<item android:state_activated="true" android:drawable="#android:color/holo_blue_light" />
<item android:drawable="#android:color/transparent"/>
</selector>
Then in layout\custom_row.xml
<?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="wrap_content"
android:padding="10dip"
android:background="#drawable/row_background"
android:orientation="vertical">
<TextView
android:id="#+id/line1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
For more information, I'm using this with ListView Adapter, using
myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
and
myList.setMultiChoiceModeListener(new MultiChoiceModeListener()...
from this example: http://www.androidbegin.com/tutorial/android-delete-multiple-selected-items-listview-tutorial/
Also, you (should) use this structure for your list-adapter coupling: List myList = new ArrayList();
instead of: ArrayList myList = new ArrayList();
Explanation: Type List vs type ArrayList in Java
Simplest way I've found:
in your activity XML add these lines:
<ListView
...
android:choiceMode="singleChoice"
android:listSelector="#666666"
/>
or programatically set these properties:
listView.setSelector(Drawable selector)
listView.setSelector(int resourceId)
My particular example:
<ListView
android:choiceMode="singleChoice"
android:listSelector="#666666"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listView"/>
thanks to AJG:
https://stackoverflow.com/a/25131125/1687010
View updateview;// above oncreate method
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (updateview != null)
updateview.setBackgroundColor(Color.TRANSPARENT);
updateview = view;
view.setBackgroundColor(Color.CYAN);
}
});
I'm also doing the similar thing: highlight the selected list item's background (change it to red) and set text color within the item to white.
I can think out a "simple but not efficient" way:
maintain a selected item's position in the custom adapter, and change it in the ListView's OnItemClickListener implement:
// The OnItemClickListener implementation
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mListViewAdapter.setSelectedItem(position);
}
// The custom Adapter
private int mSelectedPosition = -1;
public void setSelectedItem (int itemPosition) {
mSelectedPosition = itemPosition;
notifyDataSetChanged();
}
Then update the selected item's background and text color in getView() method.
// The custom Adapter
#Override
public View getView(int position, View convertView, ViewGroup parent) {
...
if (position == mSelectedPosition) {
// customize the selected item's background and sub views
convertView.setBackgroundColor(YOUR_HIGHLIGHT_COLOR);
textView.setTextColor(TEXT_COLOR);
} else {
...
}
}
After searching for a while, I found that many people mentioned about to set android:listSelector="YOUR_SELECTOR". After tried for a while, I found the simplest way to highlight selected ListView item's background can be done with only two lines set to the ListView's layout resource:
android:choiceMode="singleChoice"
android:listSelector="YOUR_COLOR"
There's also other way to make it work, like customize activatedBackgroundIndicator theme. But I think that would be a much more generic solution since it will affect the whole theme.
use the below xml as listitem background it will solve all the issues.
The selected will be highlighted though you scrolled down.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#android:color/holo_orange_dark" android:state_pressed="true"/>
<item android:drawable="#android:color/holo_green_light" android:state_selected="true"/>
<item android:drawable="#android:color/holo_green_light" android:state_activated="true"/>
Thanks,
Nagendra
I know this is a old question, but i give a simple solution for this need (without loops!):
//On your adapter create a variable:
private View lastSelectedItem;
//Define the folowing method:
private void toggleBackgroundItem(View view) {
if (lastSelectedItem != null) {
lastSelectedItem.setBackgroundColor(Color.TRANSPARENT);
}
view.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
lastSelectedItem = view;
}
//finally invoque the method onItemClick
lvSac.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick (AdapterView < ? > adapterView, View view,int i, long l){
toggleBackgroundItem(view);
}
}
In a ListView set:
android:choiceMode="singleChoice"
Create a selector for a background (drawable/selector_gray.xml):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/gray" android:state_checked="true" />
<item android:drawable="#color/white" />
</selector>
Add an item for a list:
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="5dp"
android:background="#drawable/selector_gray"
android:textColor="#color/colorPrimary"
tools:text="Your text" />
In a ViewHolder you can inflate this item.
nameofList.getChildAt(position).setBackgroundColor(RED);
worked for me
assume you want one item to be clicked each time. Then this code works well. Let's take the listview name as stlist
stList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
// here i overide the onitemclick method in onitemclick listener
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
//color change
//selected item colored
for(int i=0; i<stList.getAdapter().getCount();i++)
{
stList.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
}
parent.getChildAt(position).setBackgroundColor(Color.GRAY);
});
This is a simple method that can handle selection even if the list is long as well:
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder=new Holder();
View rowView;
rowView = inflater.inflate(R.layout.list_item, null);
//Handle your items.
//StringHolder.mSelectedItem is a public static variable.
if(getItemId(position)==StringHolder.mSelectedItem){
rowView.setBackgroundColor(Color.LTGRAY);
}else{
rowView.setBackgroundColor(Color.TRANSPARENT);
}
return rowView;
}
And then in your onclicklistener:
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
StringHolder.mSelectedItem = catagoryAdapter.getItemId(i-1);
catagoryAdapter.notifyDataSetChanged();
.....
It's very simple. In the constructor of the "OnItemClick" use the parameter "view" which is the second one that represents the listView or GridView's items's view and it becomes the new item's view made by the adapterView it self. So to set new color ONLY to the SELECTED ITEM itself do as the following:
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l){
//view is instead of the view like textView , ImageView, or whatever
view.setBackgroundColor(Color.green);
}
If you do any different codes to set new color, you will face awkward behaviours like the green color will be applied to the unclicked item.

How do I ensure change the background of a selected GridView cell?

In Android, I have a GridView - each cell in the GridView is an ImageView. When a user clicks on a cell, I would like that cell to be "selected" (have its background turn blue), and all other cells to "unselect" (have their backgrounds turn white).
I have implemented the following background drawable, but it only changes the background while the cell is pressed:
<?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/iconborder_selected" /> <!-- pressed -->
<item android:drawable="#drawable/iconborder_unselected" /> <!-- default -->
</selector>
EDIT: Here is my adapter code for the GridView.
class IconAdapter extends BaseAdapter {
private Context context = null;
private List<Drawable> icons = new ArrayList<Drawable>();
public IconAdapter(Context context) {
this.context = context;
for (Field f : R.drawable.class.getFields()) {
String path = f.getName();
if (path.contains("icon_")) {
int id = context.getResources().getIdentifier(path, "drawable",
context.getPackageName());
Drawable drawable = context.getResources().getDrawable(id);
icons.add(drawable);
}
}
}
#Override
public int getCount() {
return icons.size();
}
#Override
public Object getItem(int position) {
return icons.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView iv = new ImageView(context);
iv.setImageDrawable(icons.get(position));
iv.setBackgroundResource(R.drawable.iconborder);
return iv;
}
}
You should add state_selected too:
<?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/iconborder_selected" /> <!-- selected -->
<item android:state_pressed="true"
android:drawable="#drawable/iconborder_pressed" /> <!-- pressed -->
<item android:state_pressed="false"
android:drawable="#drawable/iconborder_unselected" /> <!-- default -->
</selector>
Try in the XML declaration of the GridView to put these lines:
<GridView
<!-- Some stuff here, like id, width, e.t.c. -->
android:drawSelectorOnTop="true"
android:listSelector="path_to_your_selector"
/>
And your selector should contain something like this:
<item android:state_pressed="true">
<shape>
<!-- Or a drawable here -->
</shape>
</item>
<item android:state_focused="true">
<shape>
<!-- Or a drawable here -->
</shape>
</item>
<item android:drawable="#android:color/transparent" />

Categories

Resources