如何使用复选框和自定义适配器从 Listview 中获取选定的列表项?

Posted

技术标签:

【中文标题】如何使用复选框和自定义适配器从 Listview 中获取选定的列表项?【英文标题】:How to get selected list items from a Listview with checkBox and Custom Adapter? 【发布时间】:2012-06-10 07:12:29 【问题描述】:

我有一个ListView,上面有CheckBox。我正在使用Custom Adapter 填充ListView

在我的xml 文件中,底部有一个Button。我想要的是让用户在ListView 中选择行数,当他/她点击Button 时,获取所选项目的位置,以便我可以获取特定行的对象以进行进一步计算。

【问题讨论】:

***.com/questions/10895763/… 【参考方案1】:

Below Snippet 完全符合您的要求。

package com.windrealm.android;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class PlanetsActivity extends Activity


    private ListView mainListView;
    private Planet[] planets;
    private ArrayAdapter<Planet> listAdapter;
    private Button check;
    private Context context;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        context = PlanetsActivity.this;
        check = (Button) findViewById(R.id.check);
        // Find the ListView resource.
        mainListView = (ListView) findViewById(R.id.mainListView);

        // When item is tapped, toggle checked properties of CheckBox and
        // Planet.
        mainListView
                .setOnItemClickListener(new AdapterView.OnItemClickListener()
                
                    @Override
                    public void onItemClick(AdapterView<?> parent, View item,
                            int position, long id)
                    
                        Planet planet = listAdapter.getItem(position);
                        planet.toggleChecked();
                        PlanetViewHolder viewHolder = (PlanetViewHolder) item
                                .getTag();
                        viewHolder.getCheckBox().setChecked(planet.isChecked());
                    
                );

        // Create and populate planets.
        planets = (Planet[]) getLastNonConfigurationInstance();
        if (planets == null)
        
            planets = new Planet[]
             new Planet("Mercury"), new Planet("Venus"), new Planet("Earth"),
                    new Planet("Mars"), new Planet("Jupiter"),
                    new Planet("Saturn"), new Planet("Uranus"),
                    new Planet("Neptune"), new Planet("Ceres"),
                    new Planet("Pluto"), new Planet("Haumea"),
                    new Planet("Makemake"), new Planet("Eris") ;
        
        ArrayList<Planet> planetList = new ArrayList<Planet>();
        planetList.addAll(Arrays.asList(planets));

        // Set our custom array adapter as the ListView's adapter.
        listAdapter = new PlanetArrayAdapter(this, planetList);
        mainListView.setAdapter(listAdapter);

        check.setOnClickListener(new OnClickListener()
        

            @Override
            public void onClick(View view)
            
                for (int i = 0; i < listAdapter.getCount(); i++)
                
                    Planet planet = listAdapter.getItem(i);
                    if (planet.isChecked())
                    
                        Toast.makeText(context,
                                planet.getName() + " is Checked!!",
                                Toast.LENGTH_SHORT).show();
                    
                

            
        );
    

    /** Holds planet data. */
    private static class Planet
    
        private String name = "";
        private boolean checked = false;

        public Planet()
        
        

        public Planet(String name)
        
            this.name = name;
        

        public Planet(String name, boolean checked)
        
            this.name = name;
            this.checked = checked;
        

        public String getName()
        
            return name;
        

        public void setName(String name)
        
            this.name = name;
        

        public boolean isChecked()
        
            return checked;
        

        public void setChecked(boolean checked)
        
            this.checked = checked;
        

        public String toString()
        
            return name;
        

        public void toggleChecked()
        
            checked = !checked;
        
    

    /** Holds child views for one row. */
    private static class PlanetViewHolder
    
        private CheckBox checkBox;
        private TextView textView;

        public PlanetViewHolder()
        
        

        public PlanetViewHolder(TextView textView, CheckBox checkBox)
        
            this.checkBox = checkBox;
            this.textView = textView;
        

        public CheckBox getCheckBox()
        
            return checkBox;
        

        public void setCheckBox(CheckBox checkBox)
        
            this.checkBox = checkBox;
        

        public TextView getTextView()
        
            return textView;
        

        public void setTextView(TextView textView)
        
            this.textView = textView;
        
    

    /** Custom adapter for displaying an array of Planet objects. */
    private static class PlanetArrayAdapter extends ArrayAdapter<Planet>
    

        private LayoutInflater inflater;

        public PlanetArrayAdapter(Context context, List<Planet> planetList)
        
            super(context, R.layout.simplerow, R.id.rowTextView, planetList);
            // Cache the LayoutInflate to avoid asking for a new one each time.
            inflater = LayoutInflater.from(context);
        

        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        
            // Planet to display
            Planet planet = (Planet) this.getItem(position);

            // The child views in each row.
            CheckBox checkBox;
            TextView textView;

            // Create a new row view
            if (convertView == null)
            
                convertView = inflater.inflate(R.layout.simplerow, null);

                // Find the child views.
                textView = (TextView) convertView
                        .findViewById(R.id.rowTextView);
                checkBox = (CheckBox) convertView.findViewById(R.id.CheckBox01);

                // 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 PlanetViewHolder(textView, checkBox));

                // If CheckBox is toggled, update the planet it is tagged with.
                checkBox.setOnClickListener(new View.OnClickListener()
                
                    public void onClick(View v)
                    
                        CheckBox cb = (CheckBox) v;
                        Planet planet = (Planet) cb.getTag();
                        planet.setChecked(cb.isChecked());
                    
                );
            
            // Reuse existing row view
            else
            
                // Because we use a ViewHolder, we avoid having to call
                // findViewById().
                PlanetViewHolder viewHolder = (PlanetViewHolder) convertView
                        .getTag();
                checkBox = viewHolder.getCheckBox();
                textView = viewHolder.getTextView();
            

            // Tag the CheckBox with the Planet it is displaying, so that we can
            // access the planet in onClick() when the CheckBox is toggled.
            checkBox.setTag(planet);

            // Display planet data
            checkBox.setChecked(planet.isChecked());
            textView.setText(planet.getName());

            return convertView;
        

    

    public Object onRetainNonConfigurationInstance()
    
        return planets;
    

【讨论】:

【参考方案2】:

要解决这个问题,您必须创建一个自定义 Item 类,该类将代表您在列表中的各个复选框。然后适配器类将使用这些项目的数组来显示您的复选框。

这个 Item 类将有一个布尔变量 isSelected,它将确定复选框是否被选中。您必须在自定义适配器类的 OnClick 方法中设置此变量的值

举例

    class CheckBoxItem

    boolean isSelected;


    public void setSelected(boolean val) 
            this.isSelected = val;
        

        boolean isSelected()
            return isSelected;

           

    

对于您的 CustomAdapter 类,如下所示:

    public class ItemsAdapter extends ArrayAdapter implements OnClickListener  

// you will have to initialize below in the constructor 
    CheckBoxItem items[];



    // You will have to create your check boxes here and set the position of your check box
    /// with help of setTag method of View as defined in below method, you will use this later // in your onClick method 

    @Override 
        public View getView(int position, View convertView, ViewGroup parent)  
            View v = convertView; 



            CheckBox cBox = null;

            if (v == null)  
                LayoutInflater vi = (LayoutInflater) apUI.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
                v = vi.inflate(R.layout.attachphoto, null);     

             



            CheckBoxItemItem it = items[position];      

            cBox =(CheckBox) v.findViewById(R.id.apCheckBox);
            cBox.setOnClickListener(this);
            cBox.setTag(""+position);       


            Log.d(TAG, "  CHECK BOX IS: "+cBox+ "   Check Box selected Value: "+cBox.isChecked()+"  Selection: "+it.isSelected());
            if(cBox != null)
                cBox.setText("");
                cBox.setChecked(it.isSelected());
                   


            return v; 
         


        public void onClick(View v) 
            CheckBox cBox =(CheckBox) v.findViewById(R.id.apCheckBox);
            int position = Integer.parseInt((String) v.getTag());

            Log.d(TAG, "CLicked ..."+cBox.isChecked());

            items[position].setSelected(cBox.isChecked());              
         

    

稍后您将声明 CheckBoxItem 类的数组,该类将包含在您的 Adapter 类中,在这种情况下,它将是 ItemsAdapter 类。

然后当用户按下按钮时,您可以遍历数组中的所有项,并使用 CheckBoxItem 类的 isSelected() 方法检查选择了哪一项。

在您的活动中,您将拥有:

ArrayList getSelectedItems()

ArrayList selectedItems = new ArrayList();

int size = items.length;

        for(int i = 0; i<size; i++)
            CheckBoxItem cItem = items[i];
            if(cItem.isSelected())                 
                selectedItems.add(cItem);                   
                       
        

return selectedItems;


【讨论】:

【参考方案3】:

我遇到了完全相同的问题。我是这样解决的

public class myActivity extends Activity  
//ActionBarSherlock mSherlock = ActionBarSherlock.wrap(this);
public ListView listview;
private ArrayList<Object> itemlist=new ArrayList<Object>();
Button button;
private myAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listview=(ListView)findViewById(R.id.listview1);
    button=(Button)findViewById(R.id.button1);
    /*add some data to ur list*/ itemlist.add(something);
    adapter=new Adapter(myActivity.this, 0, itemlist);
    listview.setAdapter(adapter);
    **listview.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    listview.setItemsCanFocus(false);**
    button.setOnClickListner(new OnClickListner()
    
     @Override
     public void OnClick(View v)
     
      /* this returns the checked item positions in the listview*/
      **ArrayList<Integer> itempositions=adapter.getcheckeditemcount();**

    for(int i:itempositions)
    
             /* This is the main part...u can retrieve the object in the listview which is checked and do further calculations with it*/
        **Object info=adapter.getItem(i);**
                          Log.d(TAG,"checked object info= ",info.something);
                 
     
    );



private class myAdapter extends ArrayAdapter<Object>  

    private Context context;
    private ArrayList<Object> list;
    **private ArrayList<Integer> checkedpositions;**


    public myAdapter(Context localContext,int textViewResourceId, ArrayList<Object> objects) 
        super(localContext,textViewResourceId,objects);
        context = localContext;
        this.list=objects;
        this.checkedpositions=new  ArrayList<Integer>();
        //Log.d("adapter","list size= "+objects.size());
    

@Override       
    public View getView(int position, View convertView, ViewGroup parent) 

        ImageView picturesView;
        View v = convertView;
        TextView Mainitem;
        final CheckBox check;

       if (v == null) 
       
           LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
           v = vi.inflate(R.layout.albumview, null);


           Object item=list.get(position);
           if(item!=null)
           

               check = (CheckBox)v.findViewById(R.id.checkBox1);
                   /* set a tag for chekbox with the current view position */
               **check.setTag(position);**
                   /*set a onchecked change listner for listning to state of checkbox toggle */
               check.setOnCheckedChangeListener(new OnCheckedChangeListener() 
                
                   @Override
                   public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) 
                                
                                       /*get the tag of the checkbox...in this case this will give the (position of view)*/
                       Object tag=check.getTag();
                       if ( isChecked ) 
                        
                           // perform logic 
                           count++;
                           Log.d("Checkbox","added "+tag);
                           checkedpositions.add((Integer) tag);
                        
                       else
                       
                           count--;
                           checkedpositions.remove(tag);
                           Log.d("Checkbox","removed "+(Integer)tag);
                       

               /* if u dont have a textview in ur listview then ignore this part */        
               Mainitem = (TextView) v.findViewById(R.id.textView1);
               Mainitem.setText(item.Album_name);

                catch (IOException e) 
                     // TODO Auto-generated catch block
                     Log.d("error", "wall");
                 

           

       

    return v;

    
   /* Finally create a method which return the checkeditem postions in the listview */
**public ArrayList<Integer> getcheckeditemcount()

    return this.checkedpositions;
**




我希望这会有所帮助。

【讨论】:

【参考方案4】:

在customadapter的getview方法中,做

//use the actual id of your checkbox of course
Checkbox checkbox = (CheckBox)findViewById(R.id.checkbox); 
checkbox.setFocusable(false);
checkbox.setFocusableInTouchMode(false);

现在复选框和列表项一样可以点击。

【讨论】:

以上是关于如何使用复选框和自定义适配器从 Listview 中获取选定的列表项?的主要内容,如果未能解决你的问题,请参考以下文章

ListView 和自定义适配器在 Kotlin 中不起作用

如何在列表适配器中正确使用 ViewHolder 和自定义视图

ListView 从 EditText 更新

Listview、自定义适配器和复选框

Android - 通过复选框使用自定义适配器从列表视图中获取项目

无法从 Firebase 将数据显示为 ListView