Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 如何在Android的ListView中構建CheckBox和RadioButton列表(Android版支持單選和多選的投票項目),androidlistview多選

如何在Android的ListView中構建CheckBox和RadioButton列表(Android版支持單選和多選的投票項目),androidlistview多選

編輯:關於android開發

如何在Android的ListView中構建CheckBox和RadioButton列表(Android版支持單選和多選的投票項目),androidlistview多選


引言

我們在android的APP開發中有時候會碰到提供一個選項列表供用戶選擇的需求,如在投票類型的項目中,我們提供一些主題給用戶選擇,每個主題有若干選項,用戶對這些主題的選項進行選擇,然後提交。

本文以一個支持單選和多選投票項目為例,演示了在一個ListView中如何構建CheckBox列表和RadioButton列表,並分析了實現的原理和思路,提供有需要的朋友參考。

項目的演示效果如下。

 

數據源

通常我們的數據源來自於數據庫。首先,我們構建投票項目類SubjectItem。

/**
 * 主題項目類
 * @author zoupeiyang
 *
 */
public class SubjectItem {
    /**
     * 主題id
     */
    private String subjectId;
    /**
     * 主題名稱
     */
    private String subjectName;
    /**
     * 主題id
     */
    private String itemId;
    /**
     * 主題名稱
     */
    private String itemName;
    /**
     * 是否多選
     */
    private Boolean  isMultiChoice;
    public String getSubjectId() {
        return subjectId;
    }
    public void setSubjectId(String subjectId) {
        this.subjectId = subjectId;
    }
    public String getSubjectName() {
        return subjectName;
    }
    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }
    public String getItemId() {
        return itemId;
    }
    public void setItemId(String itemId) {
        this.itemId = itemId;
    }
    public String getItemName() {
        return itemName;
    }
    public void setItemName(String itemName) {
        this.itemName = itemName;
    }
    public Boolean getIsMultiChoice() {
        return isMultiChoice;
    }
    public void setIsMultiChoice(Boolean isMultiChoice) {
        this.isMultiChoice = isMultiChoice;
    }
}

然後我們構造一個SubjectItem對象的List集合作為我們這個投票項目的數據源,實際項目中這個數據源可以來自數據庫投票項目表。

/**
     * 模擬從數據庫表獲取投票主題項目的數據源
     * 
     * @return
     */
    public static List<SubjectItem> getSubjectItems() {
        List<SubjectItem> list = new ArrayList<SubjectItem>();
        HashMap<String, Boolean> subjectMap = new HashMap<String, Boolean>();
        for (int i = 0; i < 3; i++) {

            for (int j = 0; j < 3; j++) {

                SubjectItem item = new SubjectItem();
                item.setSubjectId(i + "");
                //為了方便主題標題和主題項目的布局,集合中同一個主題的項目,只有主題第一個項目的對象的主題名稱不為空,其它為空
                //這樣顯示ListView的每列時如果主題名稱為空就隱藏主題名稱
                if (subjectMap.containsKey(item.getSubjectId())) {
                    item.setSubjectName("");
                } else {
                    item.setSubjectName("投票主題" + i);
                    subjectMap.put(item.getSubjectId(), true);
                }

                item.setItemId(i + "" + j);
                item.setItemName("項目名稱" + i + "" + j);
                item.setIsMultiChoice(i % 2 == 1 ? true : false);
                list.add(item);

            }
        }
        return list;
    }

 

如何在ListView控件上展示以列表的方式展示投票項目

首先我們先來了解下在ListView控件展示列表數據的流程。
1、定義一個展示列表每一行的布局layout,我們這裡定義這個layout的文件名為listview_subject_item.xml。
2、定義展示listview的布局layout,我們這裡定義這個layout的文件名為listview_subject_activity.xml。
3、定義listview的數據適配器SubjectAdapter。

定義ListView控件每列的布局

listview_subject_item.xml文件定義的ListView控件中每列view的布局。我們這裡的投票項目是支持單選和多項,可以每列view的布局都包含了CheckBox和RadioButton控件,在手機界面顯示視圖的時候根據當前項目的投票類型(單選或多選)來自動顯示(隱藏)對應的控件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <!-- 投票主題ID,默認隱藏 -->
    <TextView
        android:id="@+id/tv_subject_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:visibility="gone" />
     <!-- 投票主題下項目ID,默認隱藏 -->
    <TextView
        android:id="@+id/tv_subject_item_id"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:visibility="gone" />
     <!-- 投票主題類型,true為多選,否則為單選,默認隱藏 -->
       <TextView
        android:id="@+id/tv_is_multi_choice"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text=""
        android:visibility="gone" />
       <!-- 投票主題名稱,只有主題下的第一個項目才會顯示主題名稱,其它項目不顯示 -->
    <TextView
        android:id="@+id/tv_subject_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:layout_marginBottom="10dp"
        android:textSize="14sp"
        android:textColor="#1387DD"
        android:text
        android:text="" />
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
         <!-- 投票項目名稱 -->
        <TextView
            android:id="@+id/tv_subject_item_name"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical" />
         <!-- 多選項目顯示CheckBox -->
        <CheckBox
            android:id="@+id/cb_subject_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:gravity="center_vertical" />
         <!-- 單選項目顯示RadioButton -->
        <RadioButton
            android:id="@+id/rb_subject_item"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="false"
            android:focusable="false"
            android:focusableInTouchMode="false"
            android:gravity="center_vertical" />
    </LinearLayout>
</LinearLayout>

定義展示ListView的布局

定義展示listview的布局layou,文件名為listview_subject_activity.xml
這裡使用了RelativeLayout布局,將提交按鈕固定在屏幕底部,方便用戶提交投票信息。

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffffff" >
    <RelativeLayout
        android:id="@+id/rl_head"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_alignParentTop="true"
        android:background="#0C99EF"
        android:paddingLeft="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="投票項目"
            android:textColor="#ffffffff"
            android:textSize="16sp" />
    </RelativeLayout>
    <!-- 投票項目ListView -->
    <ListView
        android:id="@+id/lv_subject"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/rl_head"
        android:layout_marginBottom="50dp"
        android:layout_marginLeft="10dp" >
    </ListView>
    <Button
        android:id="@+id/btn_add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:text="提交" />
</RelativeLayout>

定義數據適配器SubjectAdapter

listview_subject_activity.xml文件定義了名為lv_subject的ListView,這個ListView如何和listview控件中每列view的布局listview_subject_item.xml進行關聯,還有我們前面定義了投票主題項目數據源,它又如何和listview進行關聯數據綁定,要完成這些,我們必須依賴一個Apdater適配器類。
ListView控件通過方法setAdapter和Adapter關聯。
在Adapter中通過getView方法和列view的布局listview_subject_item.xml進行關聯。
數據源通過Adapter的自定義構造函數的參數傳人Adapter。

package com.example.listviewcheckbox.adapter;

import java.util.HashMap;
import java.util.List;

import com.example.listviewcheckbox.R;
import com.example.listviewcheckbox.entity.SubjectItem;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.RadioButton;
import android.widget.TextView;

public class SubjectAdapter extends BaseAdapter {
    
    private List<SubjectItem> list;
    private Context context;
    //存儲所有主題的項目的選中狀態,遍歷這個容器可以獲取選中的項目信息
    private HashMap<String,Boolean> subjectItemMap;
    private LayoutInflater inflater;
    
    public class ViewHolder{
       //投票主題id控件
       public TextView tvSubjectId;
       //投票主題名稱控件
       public TextView tvSubjectName;
       //投票項目名稱控件
       public TextView tvSubjectItemName;
       //投票項目id控件
       public TextView tvSubjectItemId;
       //投票主題類型(單選或多選)控件
       public TextView tvIsMultiChoice;
       //選中CheckBox控件(主題類型為多選時顯示)
       public CheckBox cbSubjectItem;
       //選中RadioButton控件(主題類型為單選時顯示)
       public RadioButton rbSubjectItem;
        
    }
    
    public SubjectAdapter(List<SubjectItem> list,Context context)
    {
        this.list=list;
        this.context=context;
         inflater = LayoutInflater.from(context);
        this.subjectItemMap=new HashMap<String, Boolean>();
        //初始化subjectItemMap,默認所有項目為未選中狀態
        for (int i = 0; i < list.size(); i++) {
            this.subjectItemMap.put(list.get(i).getItemId(), false);
        }
    }

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder viewHolder = null;
        SubjectItem item = list.get(position);
        if(convertView!=null&&convertView.getId()==R.id.lv_subject)
        {
            viewHolder=(ViewHolder)convertView.getTag();
        }
        else {
            viewHolder = new ViewHolder();
            convertView=inflater.inflate(R.layout.listview_subject_item, null);
            viewHolder.tvSubjectId=(TextView)convertView.findViewById(R.id.tv_subject_id);
            viewHolder.tvSubjectName=(TextView) convertView.findViewById(R.id.tv_subject_name);
            viewHolder.tvSubjectItemId = (TextView) convertView.findViewById(R.id.tv_subject_item_id);
            viewHolder.tvSubjectItemName = (TextView) convertView.findViewById(R.id.tv_subject_item_name);
            viewHolder.cbSubjectItem = (CheckBox) convertView.findViewById(R.id.cb_subject_item);
            viewHolder.rbSubjectItem = (RadioButton) convertView.findViewById(R.id.rb_subject_item);
            viewHolder.tvIsMultiChoice = (TextView) convertView.findViewById(R.id.tv_is_multi_choice );
            
        }
        //如果項目名稱為空就隱藏當前項的產品名稱,即所有子項目只允許第一個子項目出現產品名稱
        if(item.getSubjectName().equals(""))
        {
            viewHolder.tvSubjectName.setVisibility(View.GONE);
        }
        else {
            viewHolder.tvSubjectName.setText(item.getSubjectName());
        }
        viewHolder.tvSubjectItemId.setText(item.getItemId());
        viewHolder.tvSubjectId.setText(item.getSubjectId());
        viewHolder.tvSubjectItemName.setText(item.getItemName());
        viewHolder.tvIsMultiChoice.setText(item.getIsMultiChoice().toString());
        //當前項目為多選項目
        if(item.getIsMultiChoice().toString().equals("true"))
        {
            viewHolder.cbSubjectItem.setVisibility(View.VISIBLE);
            viewHolder.rbSubjectItem.setVisibility(View.GONE);
            viewHolder.cbSubjectItem.setChecked(this.subjectItemMap.get(item.getItemId()));
            
        }
        //當前項目為單選項目
        else {
            viewHolder.cbSubjectItem.setVisibility(View.GONE);
            viewHolder.rbSubjectItem.setVisibility(View.VISIBLE);
            viewHolder.rbSubjectItem.setChecked(this.subjectItemMap.get(item.getItemId()));
        }
        convertView.setTag(viewHolder);
        return convertView;
    }
    
    /**
     * 獲取所有主題的項目的選中狀態容器
     * @return
     */
     public  HashMap<String,Boolean> getSubjectItemMap() {
            return this.subjectItemMap;
        }
}

定義顯示投票項目的Activity組件

最後我們定義一個Activity組件,將投票項目顯示出來。
為了解決單選項目選中後同時要將同主題原來已經選中的項目取消,定義了一個Map(radioButtonSelectedMaps)來存儲單選主題的選中的項目信息,key為單選主題ID,value為選中的項目ID。
這樣在用戶選擇某個單選項目時,程序先將SubjectAdapter對象中subjectItemMap該項目主題之前選中的項目的狀態設置為false,然後將當前選中的項目設置為true,然後更新ListView,實現單選效果。

public class SubjectActivity extends Activity {

    private ListView lvSubject;
    private SubjectAdapter subjectAdapter;
    private List<SubjectItem> list;
    private Button btnAdd;
    // 用來保存單選主題當前選中的項目,這樣用戶在切換選擇同一個主題下其它選項時能夠將之前選中的項目的狀態設置為未選狀態
    private HashMap<String, String> radioButtonSelectedMaps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview_subject_activity);
        lvSubject = (ListView) findViewById(R.id.lv_subject);
        btnAdd = (Button) findViewById(R.id.btn_add);
        //從數據源獲取投票主題和項目信息
        list = DataService.getSubjectItems();
        subjectAdapter = new SubjectAdapter(list, this);
        lvSubject.setAdapter(subjectAdapter);
        radioButtonSelectedMaps = new HashMap<String, String>();
        // 提交投票事件處理
        btnAdd.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String selectValues="選中信息:";
                //遍歷用戶選中項目,可以根據實際需求獲取選中項目的任何信息
                for (int i = 0; i < list.size(); i++) {
                    if(subjectAdapter.getSubjectItemMap().get(list.get(i).getItemId()))
                    {
                        selectValues+="項目ID:"+list.get(i).getItemId()+"項目名稱:"+list.get(i).getItemName();
                    }
                    
                }
                Toast.makeText(SubjectActivity.this, selectValues.equals("選中信息:")?"未選中任何信息":selectValues, Toast.LENGTH_LONG).show();
            }
        });

        // ListView控件每一行點擊事件處理
        lvSubject.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {
                // TODO Auto-generated method stub
                ViewHolder viewHolder = (ViewHolder) view.getTag();
                // 如果當前行是多選項目
                if (viewHolder.tvIsMultiChoice.getText().equals("true")) {
                    viewHolder.cbSubjectItem.toggle();
                    subjectAdapter.getSubjectItemMap().put(viewHolder.tvSubjectItemId.getText().toString(),viewHolder.cbSubjectItem.isChecked());

                } 
                
                //如果當前行為單選項目,注意單選項目選中後需要將同一主題下已經選中的項目設置為未選中狀態
                else {
                    String currentSubjectIdSelected=viewHolder.tvSubjectId.getText().toString();
                    String currentSubjectItemId=viewHolder.tvSubjectItemId.getText().toString();
                    //判斷該單選主題是否有已經選中項目,如果有需要將它的選中狀態設置為未選中
                    if (radioButtonSelectedMaps.containsKey(currentSubjectIdSelected)) {
                        subjectAdapter.getSubjectItemMap().put(radioButtonSelectedMaps.get(currentSubjectIdSelected),false);

                    }
                    //將當前選中的項目設置為該單選主題的選中項目
                    radioButtonSelectedMaps.put(currentSubjectIdSelected,currentSubjectItemId);
                    viewHolder.rbSubjectItem.toggle();
                    subjectAdapter.getSubjectItemMap().put(currentSubjectItemId,viewHolder.rbSubjectItem.isChecked());
                    //更新ListView
                    updateListView();

                }}});
    }
    
    /**
     * 更新ListView
     */
    private void updateListView()
    {
        subjectAdapter.notifyDataSetChanged();
    }

}

獲取投票結果

// 提交投票事件處理
        btnAdd.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                String selectValues="選中信息:";
                //遍歷用戶選中項目,可以根據實際需求獲取選中項目的任何信息
                for (int i = 0; i < list.size(); i++) {
                    if(subjectAdapter.getSubjectItemMap().get(list.get(i).getItemId()))
                    {
                        selectValues+="項目ID:"+list.get(i).getItemId()+"項目名稱:"+list.get(i).getItemName();
                    }
                    
                }
                Toast.makeText(SubjectActivity.this, selectValues.equals("選中信息:")?"未選中任何信息":selectValues, Toast.LENGTH_LONG).show();
            }
        });

 

代碼下載

有需要的朋友可以訪問我的GitHub下載本文示例的完整代碼。

https://github.com/zoupeiyang/ListViewCheckBox

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved