【问题标题】:Select multiple items from listview and change color of selected item only从列表视图中选择多个项目并仅更改所选项目的颜色
【发布时间】:2019-05-18 17:41:16
【问题描述】:

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

但是当我过去滚动它时.. 它显示我又选择了 1 个项目,即使我没有像这样选择它:

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

我将代码用作:

     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);
        });

【问题讨论】:

  • 这是因为在 Android 中,当您滚动列表时,列表会被回收。

标签: android android-listview


【解决方案1】:

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

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

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

所以现在您将背景颜色设置为其默认值,但是如果您从选定的项目上滚动,然后再回到它,它将具有透明背景而不是选定的背景。要解决此问题,请将 ArrayListInteger 值放入您的适配器类中。单击某个项目并触发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);  

【讨论】:

  • 嘿,非常感谢您的回答,但是当我添加 public ArrayList selectedIds = new ArrayList();在我的适配器类中,然后在 onlistItemClick 中,它没有采用 ((ItemsAdapter) parent).selectedIds;它在这里给了我一个错误,并且没有从适配器类中提取 selectedIds 变量:(请帮助做什么
  • 您需要适配器中的ArrayList,然后从活动中的onItemClick 方法访问它。你可以选择任何你想做的方式,它不必是我逐字写的。我建议使用 getter 方法。
  • 嘿,请解决这个问题..我无法..我不明白 arraylist 应该如何在 OnItemClick 方法和 arrayasper 之间进行通信?如果我确实在适配器类中创建了一个数组列表,那么我无法在 OnItemClick 方法中获取它??请帮助:(
  • 嘿,非常感谢您的支持。我终于找到了解决方案:)
  • @Kanika 请问你最后是怎么解决的?我遇到了同样的错误,由于某种原因无法解决问题,它告诉我无法从 AdapterView 投射到我的班级
【解决方案2】:

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

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

【讨论】:

  • 您为适配器类重写此方法。
  • 还添加这个:@Override public int getViewTypeCount() { return 1; }
  • 感谢@Niko 的支持。我得到了解决方案:)
【解决方案3】:

跟踪Activity中listView中选择的项目。在适配器的 getView 中,检查位置是否等于列表视图中的选定位置和那里的视图的 setBackgroundColor。这将起作用。

【讨论】:

    【解决方案4】:

    无论您尝试在 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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 请帮助如何实现这一点。我从昨天开始就陷入了这个问题,还没有得到任何解决方案:(
      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        Jason Robinson 的解决方案(想法)很好,但是有一个错误!您不能通过它的值从 ArrayList 中删除项目!!!
        方法 ArrayList.remove(int) 将项目的索引作为参数!
        如果要使用ArrayList&lt;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;
        }
        

        或者使用方法ArrayList.indexOf(Object)获取索引。

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

        public class SimpleFragment extends ListFragment {
            private MyCustomAdapter mAdapter;
        
            @Override
            public void onActivityCreated(Bundle savedInstanceState) {
                super.onActivityCreated(savedInstanceState);
        
                mAdapter = new MyCustomAdapter(getActivity(), R.layout.row_layout);
                setListAdapter(mAdapter);
            }
        
            @Override
            public void onListItemClick(ListView l, View v, int position, long id) {
                // now you have an access to your adapter through class variable mAdapter
            }
        }
        

        【讨论】:

        猜你喜欢
        • 2017-06-19
        • 2020-11-27
        • 2021-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-05
        • 1970-01-01
        相关资源
        最近更新 更多