从列表视图中选择多个项目,仅更改所选项目的颜色

时间:2012-04-11 05:29:08

标签: android android-listview

我想创建一个视图,我可以从listview中选择多个项目,也可以并排更改所选列表项目的颜色并将该项目保存到我的arraylist中。我的列表如下所示:

enter image description here

但是当我以前滚动它时......它向我展示了另外一个项目,即使我没有选择它:

enter image description here

但我希望只有那个列表项颜色应该改变我点击的位置......

我使用的代码为:

     private class ItemsAdapter extends ArrayAdapter<String> {
 List<String> items;
  Context context;
  private LayoutInflater inflater;
  public ItemsAdapter(Context context, List<String> part_array_list) {
     super( context, R.layout.part_list, R.id.label,part_array_list );

     inflater = LayoutInflater.from(context) ;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
      TextView textView ; 
    String item = (String) this.getItem( position ); 

      if ( convertView == null ) {
        convertView = inflater.inflate(R.layout.part_list, null);

        // Find the child views.
        textView = (TextView) convertView.findViewById( R.id.label );


        // Optimization: Tag the row with it's child views, so we don't have to 
        // call findViewById() later when we reuse the row.
        convertView.setTag( new ListViewHolder(textView) );


      }
      // Reuse existing row view
      else {
        // Because we use a ViewHolder, we avoid having to call findViewById().
        ListViewHolder viewHolder = (ListViewHolder) convertView.getTag();

        textView = viewHolder.getTextView() ;

      }


      textView.setText( part_array_list.get(position) );      

      return convertView;


      }
      }
        /** Holds child views for one row. */
           private class ListViewHolder {

 private TextView textView ;
 public ListViewHolder() {}
 public ListViewHolder( TextView textView ) {

   this.textView = textView ;
 }

 public TextView getTextView() {
   return textView;
 }
 public void setTextView(TextView textView) {
   this.textView = textView;
 }    

}

并且在OnCreate()方法中,

         final ArrayAdapter<String> part_list_adapter=new ItemsAdapter(AssetSearch.this, part_array_list);
        //PartNumber_List.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    PartNumber_List.setAdapter(part_list_adapter);

    PartNumber_List.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View v, int position,
            long id) {
         ListViewHolder viewHolder = (ListViewHolder) v.getTag();
         viewHolder.getTextView().setBackgroundColor(R.color.result_image_border);

        String item=(String) part_list_adapter.getItem((int) id);
        });

7 个答案:

答案 0 :(得分:10)

这里的问题是您正在为视图设置背景颜色,然后在滚动时,由于使用convertView,您最终会重复使用该视图。这正是你应该做的,在那里做得很好。

但是,当然,这意味着列表项在不应该被选中时被选中。要解决此问题,您的getView()方法需要将背景颜色重置为其默认值。我不知道最初的颜色是什么,但我认为它是透明的。所以你会把:

textView.setBackgroundColor(android.R.color.transparent);

所以现在您将背景颜色设置为默认值,但如果您从所选项目滚动,然后返回到它,它将具有透明背景而不是所选背景。要解决此问题,请在适配器类中放置ArrayList Integer个值。单击某个项目并触发onItemClick()时,将项目位置添加到ArrayList。例如,假设你有:

public ArrayList<Integer> selectedIds = new ArrayList<Integer>();
适配器类中的

。然后,您的onItemClick方法将如下所示:

@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {

     ArrayList<Integer> selectedIds = ((ItemsAdapter) parent).selectedIds;
     Integer pos = new Integer(position);
     if(selectedIds.contains(pos) {
         selectedIds.remove(pos);
     }
     else {
         selectedIds.add(pos);
     }

     parent.notifyDataChanged();
}

最后,在您的getView()方法中,添加以下行:

textView.setBackground(selectedIds.contains(position) ? R.color.result_image_border : androi.R.color.transparent);  

答案 1 :(得分:3)

我也遇到过这个问题,并发现它是因为回收视图。如果我记得正确的设置,这将删除回收并解决问题,但这不是最好的选择。

@Override
public int getItemViewType(int position) {
    return IGNORE_ITEM_VIEW_TYPE;
}

答案 2 :(得分:1)

跟踪活动中listView中选择的项目。在适配器的getView中,检查位置是否等于列表视图中的选定位置,以及视图中的setBackgroundColor。这将有效。

答案 3 :(得分:1)

无论你在itemClick监听器中尝试使用ConvertView,它都会反映在其他类中,为了避免你需要为相应的视图持有者设置背景,我会显示一些对我来说很好的样本,

public View getView(final int position, View convertView, ViewGroup parent) {
         System.gc();
         final ViewHolder holder;

         if (convertView == null) {
             convertView = mInflater.inflate(R.layout.albumlist, null);
             holder = new ViewHolder();
             holder.albumName = (TextView) convertView.findViewById(R.id.albumDetails);

             convertView.setTag(holder);
         }
         else {
             holder = (ViewHolder) convertView.getTag();
         }


         holder.albumName.setText(albumData[position][0]);

         holder.albumName.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 holder.albumName.setBackgroundColor(R.color.black);


             }});

         return convertView;
 }

     class ViewHolder {

         TextView albumName;


     }

样本o / p enter image description here

答案 4 :(得分:0)

您必须在单击列表中的任何列表项时设置标记,并选中此标志以确定在适配器的getView()方法中是否已单击该项目的天气。

答案 5 :(得分:0)

关于@JasonRobinson给出的答案的更正:

if(selectedIds.contains(pos) {
         selectedIds.remove(pos); -> **selectedIds.remove(selectedIds.indexOf(pos));**
     }
     else {
         selectedIds.add(pos);
     }

答案 6 :(得分:0)

来自 Jason Robinson 的解决方案(想法)很好,但是有错误!你不能通过它的值来删除ArrayList中的项目!!!
方法ArrayList.remove(int)将item的索引作为parametr!
如果要使用ArrayList<Integer>,则需要找到要删除的索引项。例如:

Integer

或使用方法private int getIndex(int value) { int index = -1; for(int i=0; i<selectedIds.size(); i++) { if(selectedIds.get(i)==value) { index = i; break; } } return index; } 获取索引。

现在,如何从FragmenList或ListActivity引用您的适配器。只需使用类变量:

ArrayList.indexOf(Object)