I have the following requirements:
For whatever reasons it seems not to be as straight forward as I thought. The only solution that goes at least a little bit in the right direction is this one: https://stackoverflow.com/a/16978159/658718
The caveat is, that this does not change the on select color, but changes the background color permanently, plus it already changes the background color for list view items if you scroll down a bit.
How can I approach this?
The difficulty here is that pressed/checked color is dynamic. You cannot use static xml color-state-list. But you can create ColorStateList by code. Here is how to do that.
You just have to implement the ListAdapter :
private class MyListAdapter implements ListAdapter{
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView!=null){
CheckedTextView textView = (CheckedTextView)convertView;
textView.setText("the text for item "+position);
textView.setTextColor(makeColorStateListForItem(position));
return textView;
}else{
CheckedTextView textView = new CheckedTextView(parent.getContext());
textView.setText("the text for item "+position);
textView.setTextColor(makeColorStateListForItem(position));
return textView;
}
}
private ColorStateList makeColorStateListForItem(int position){
int pressedColor = pressedColorForItem(position);
int checkedColor = checkedColorForItem(position);
int defaultColor = defaultColorForItem(position);
ColorStateList colorStateList = new ColorStateList(
new int[][]{
new int[]{android.R.attr.state_pressed},
new int[]{android.R.attr.state_checked},
new int[]{0},
},
new int[]{
pressedColor, //use when state is pressed
checkedColor, //use when state is checked, but not pressed
defaultColor}); //used when state is not pressed, nor checked
}
private int pressedColorForItem(int position){
//write your business logic to determine color here
return ...;
}
private int checkedColorForItem(int position){
//write your business logic to determine color here
return ...;
}
private int defaultColorForItem(int position){
return Color.WHITE;
}
//all other adapter methods
//...
Note the use of android.R.attr.state_checked instead of the more intuitive android.R.attr.state_selected because the state_selected is not very precisely define with a touch screen (i.e. state_selected can give the expected behavior on the emulator, but on a real device it will probably fail)
On the other hand state_checked + CheckedTextView is going to work correctly on both simulator and real device.
Just call List.setChoiceMode(...); when initializing listView and ListView.setItemChecked in the clickListener.
final ListView listView = ...
listView.setAdapter(new MyListAdapter());
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
listView.setItemChecked(position,true);
}
});
EDIT : to change the item background : just create a StateListDrawable instead of a simple ColorStateList :
private Drawable makeBackgroungForItem(int position){
int pressedColor = pressedBackgroundColorForItem(position);
int checkedColor = checkedBackgroundColorForItem(position);
int defaultColor = defaultBackgroundColorForItem(position);
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_list_pressed}, new ColorDrawable(pressedColor));
stateListDrawable.addState(new int[]{android.R.attr.state_list_checked}, new ColorDrawable(checkedColor));
stateListDrawable.addState(new int[]{0, new ColorDrawable(defaultColor));
return stateListDrawable;
}
And in the getView(...)
textView.setBackground(makeBackgroungForItem(position));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With