我试图让ListView的点击项目改变背景。但在我看来,实际上并不可能。有很多帖子都有这样做的例子,但没有一个可靠地运作。据我了解 - 它以某种方式与回收"。
有关我在适配器的OnItemClickListener中调用view.setSelected(),它根据我的设置很好地将另一个背景应用于所选项目。但是,当我选择导致ListView缺少空间的项目(不确切的重要性)并且在ListView内部出现(或消失)scollbar时,android会忘记我的选择并应用默认样式。旋转屏幕时会发生同样的错误 - 该项目取消选择。所以我认为"取消选择"在调用适配器的getView()时发生。
有趣的是,我的onClick事件导致向后台服务发送json请求并接收和解码json响应,因此项目点击和活动内容更改之间需要一些时间。这是它的外观:
点击不会导致滚动条显示的项目效果很好 - 在处理服务的响应后,所选项目不会被取消选择。
尝试在适配器的getView()内调用setSelected()不会影响bug。物品仍然被取消选择。我尝试在getView()中手动设置项目的背景 - 它变得更有趣:导致滚动条外观的项目开始正常工作,但不会导致滚动条出现的项目(实际上它意味着他们不会导致getView()调用停止工作!
所有代码都非常复杂,所以我只会发布一些重要的片段。这是我的OnItemClickListener:
private AdapterView.OnItemClickListener onCategoryClickListener =
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, final View view, final int position,
long id) {
categoriesAdapter.setSelectedPosition(position);
view.setSelected(true);
// More code here
}
};
这是我的适配器代码的一部分:
private int selectedPosition;
private boolean selectable = true;
public void setSelectedPosition(int position) {
this.selectedPosition = position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) View.inflate(context, textViewResourceId, null);
label.setText(getName(values.get(position)));
if(selectable) {
label.setBackgroundResource(R.drawable.list_selector);
if(position == selectedPosition) {
label.setSelected(true); // This does not work. Why?
label.setBackgroundColor( // This gives strange results
context.getResources().getColor(R.color.list_item_selected_color));
} else {
// Similar code here, but for deselecting items.
}
}
return label;
}
这是我的选择器:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/list_item_default_color"
android:state_selected="false" />
<item
android:drawable="@color/list_item_selected_color"
android:state_selected="true"/>
</selector>
我搜索了很多如何使它工作,但没有任何帮助。以下是我尝试过的一些事情:
答案 0 :(得分:10)
对于API 11 +:
1)将列表视图设置为单选:
<ListView
android:choiceMode="singleChoice" />
2)将项目布局的根元素的背景设置为选择器:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/selector">
3)将android:state_selected
更改为 android:state_activated
:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/list_item_selected_color"
android:state_activated="true"/>
<item android:drawable="@color/list_item_default_color"/>
</selector>
4)使用listView.setItemChecked(index, true);
注意: 为了明确视图的状态,特别是 state_activated
,您可以查看this post;这很有趣。
答案 1 :(得分:0)
我对颜色感到困惑。在修复了一些愚蠢的错误之后,通过直接从OnItemClickListener和getView设置背景颜色,我的选择可靠地工作:
修复了OnItemClickListener:
public void onItemClick(AdapterView<?> parent, final View view, final int position,
long id) {
categoriesAdapter.setSelectedPosition(position);
for (int j = 0; j < parent.getChildCount(); j++) {
parent.getChildAt(j).setSelected(false);
parent.getChildAt(j).setBackgroundColor(getContext().getResources().getColor(
R.color.list_item_default_color));
}
view.setBackgroundColor(getContext().getResources().getColor(
R.color.list_item_selected_color));
// More code here
}
固定适配器:
private Integer selectedPosition;
public void setSelectedPosition(int position) {
this.selectedPosition = position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) View.inflate(context, textViewResourceId, null);
label.setText(getName(values.get(position)));
if(selectedPosition != null) {
if(position == selectedPosition) {
label.setBackgroundColor(context.getResources()
.getColor(R.color.list_item_selected_color));
} else {
label.setBackgroundColor(context.getResources()
.getColor(R.color.list_item_default_color));
}
}
return label;
}
因此,使用<selector>
执行此操作的方法不起作用,因为android无法可靠地切换窗口小部件状态。是正确还是有人“<selector>
方式”工作?