2014-12-06 132 views
4

我想只是为了让ListView控件的点击的项目来改变背景。但在我看来,实际上并不可能。有很多帖子都有这样的例子,但是没有一个可靠地工作。据我了解 - 这与“回收”有某种关系。的setSelected()的作品与越野车的ListView

我打电话view.setSelected()在适配器的OnItemClickListener,它很好地按照我的设置应用于另一个背景选择的项目。但是,当我选择导致ListView缺乏空间(不重要如何)和ListView内出现(或消失)的内容的项目时,android会忘记我的选择并应用默认样式。旋转屏幕时会出现同样的问题 - 取消选择该项目。所以我认为“取消选择”是在调用适配器的getView()时发生的。

有趣的是,我的onClick事件会导致发送一个JSON请求到后台服务和recieving和解码JSON响应,所以它需要一个项目的点击和活动内容的变化之间的一段时间。这是它的外观:

  1. 我点击一个ListView项目。它将背景更改为“选定的颜色”。
  2. 我等了很久。
  3. 活动内容根据服务响应而变化。滚动条出现在ListView中。项目背景更改为“默认颜色”(取消选择项目)。

点击不会导致滚动条出现的项目效果很好 - 选择的项目在处理服务的响应后不会被取消选择。

试图调用的setSelected()适配器的getView的()内的错误给出任何影响。项目仍被取消选择。我尝试在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> 

我搜索了很多关于如何使它工作但没有什么帮助。这里有一些事情,我试图:

  • view.post的内部运行view.setSelected()()
  • 运行list.setSelection() - 这是什么方法呢?它什么也没做!
  • 初始化TextView的更准确,检查是否convertView为null。给出糟糕的,非常糟糕的结果 - 导致ListView项目洗牌(对选择状态没有任何影响)。
  • 没有使用ViewHolder,因为我没有Item的复杂布局,我只是有一个简单的TextView。

回答

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_selectedandroid: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;挺有趣的。

+0

不幸的是我用API-7,它并没有state_activated。 – 2014-12-07 14:59:03

+0

那么我认为你是正确的,你的方式是唯一的方法 – tachyonflux 2014-12-07 21:22:22

0

我被混淆了一些颜色。

固定OnItemClickListener:直接来自OnItemClickListener和getView设置背景颜色固定一些愚蠢的错误,我的选择是工作可靠后

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>方式”工作?