1. 程式人生 > >如何在Android的ListView中構建CheckBox和RadioButton列表(支援單選和多選的投票專案示例)

如何在Android的ListView中構建CheckBox和RadioButton列表(支援單選和多選的投票專案示例)

引言

我們在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:textStyle="bold"
        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();
            }
        });

程式碼下載

擴充套件閱讀

相關推薦

如何在Android的ListView構建CheckBoxRadioButton列表(支援投票專案示例)

引言 我們在android的APP開發中有時候會碰到提供一個選項列表供使用者選擇的需求,如在投票型別的專案中,我們提供一些主題給使用者選擇,每個主題有若干選項,使用者對這些主題的選項進行選擇,然後提交。 本文以一個支援單選和多選投票專案為例,演示了在一個ListView中如何構建CheckBox列表和Ra

在Javawebpoi實現資料匯入,支援03版07版Excel匯入

注意資料型別的轉換,另外由於在後面的sid我不需要插入資料庫,所以最後就沒有set到實體物件 哪些不明白可以直問! import java.io.File; import java.io.FileInputStream; import java.io.IOExceptio

關於python求出兩個列表的相同元素不同元素

 用列表推導式來寫 list1 = [1,3,65,2,7] list2 = [3,2,5,4] c = [x for x in list1 if x in list2] d = [y for y in (list1+list2) if y not in c] prin

移動端 ionic angularjs列表以及框混合使用問題

第一次使用ionic,需要展現一個列表,列表下面是輸入框或者多選、單選。就是一張問卷 想的是先展現題目列表,每個題目裡面巢狀多選、單選或者輸入框,結果不行。不知道是什麼原因,是列表禁用了點選功能還是什麼(如有知道的,請給小弟解惑啊)? 程式碼: <html>

9、網絡知識(路由交換ARP協議)+配置網卡ip配置默認路由

路由交換 ARP協議 網絡配置網絡知識詳解 提問:網絡到底是什麽?我們在電纜中傳輸的都是電信號(高電壓或者是低電壓),所以高電壓就是1,低電壓就是0,所以規定一定的時間傳輸固定的高低電壓來當做是接收的數據我們所謂的10Mbps:每秒中可以傳輸10M個bit所以別人說你的是4M的帶寬,指的就是4Mbps,要除

freemarker判斷一個字串是否包含另一個字串(select框資料回顯)

開發中用到了select多選框,所以資料回顯就要換一種方式解決。多選框返回的資料是一個用逗號分隔的字串,比如“a,b,c”,回顯的時候用contains判斷從而決定是否對每個option進行checked。 <#if "a,b,c,"?contains("a")>

CSS+checkbox 實現按鈕 標籤

效果圖:         CSS: input[type="checkbox"] { position: absolute; clip: rect(0, 0, 0,

Android開發—彈出列表

效果圖如下: 需要建一個menu xml佈局如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/r

Android 本地歷史記錄、及產品標籤(支援)實現(附原始碼)(使用鴻洋大神的FlowLayout開源庫)

        最近的專案需要做本地歷史記錄功能,以前寫的有些過時了,就在網上查了查較好的開源庫、實現方式等。最終選擇了鴻洋大神的FlowLayout流式佈局,再搭配SharedPreferencesUtil工具類來實現本地歷史記錄功能。同時FlowLayout開源庫還非常適

Android常用Dialog的幾種格式顯示,普通,列表,可編輯dialog等

Android中幾種常見的dialog顯示格式,話不多說,直接上程式碼 package diaog.com.diaogdemo; import android.app.Activity; import android.app.AlertDialog;

d3之元件的運用(框,下拉列表,滑動軸,

目錄 目錄 單選框 下拉列表 滑動軸 多選框 單選框 1.前端 <form name="myForm" action="" method="" style="posit

15/8/27/預設自定義Toast/簡單、選項、AlterDialog

Toast Toast分為預設的和自定義佈局的Toast 1.Toast是獨立, 不依賴於Activity,但是不能對他進行操作,因此通常用於提示資訊, 2.預設的Toast比較簡單其程式碼如下: Toast toast=Toast.mak

iOS開發

在前端開發中如果要擁有一個單選或者多選功能十分簡單,因為HTML中有現成的標籤可以很方便的實現單選或者多選效果,比如這樣寫上幾句程式碼就能擁有最原始的選擇效果。 但是在iOS開發中就沒有這麼方便的控制元件了,如果要完成單選或者多選的功能還需要一些邏輯編碼,並且

Jquery mobilecheckboxradio的設置問題

prop 不顯示 jquery 讀取 兩個 mob att attr 設置 在Jquery Mobile網頁中用JS控制Radio的狀態一直達不到目的。 用$("input[name=‘radio‘]:first").prop("checked",true)設置checke

Spring Boot擴充套件XML請求響應的支援

在Spring Boot中,我們大多時候都只提到和用到了針對HTML和JSON格式的請求與響應處理。那麼對於XML格式的請求要如何快速的在Controller中包裝成物件,以及如何以XML的格式返回一個物件呢? 實現原理:訊息轉換器(Message Converter) 在擴充套件上述問題之前,我們先要知

python 自己實現列表的sort函式,支援逆序,可以排序任意型別的資料。 實現列表的排序,要求支援逆序指定標準(key)

def paixv(lt,reverse = None): for i in range(len(lt) - 1): for j in range(i+1,len(lt)): if reverse : if

Spring Boot如何擴充套件對XML格式請求響應的支援

在Spring Boot中,對於XML格式的請求要如何快速的在Controller中包裝成物件,以及如何再以XML的格式返回一個物件呢? 實現原理:訊息轉換器(Message Converter) 在擴充套件上述問題之前,我們先要知道Spring Boot中處理HTTP請求的實現是採用的Sp

tensorflow針對迭代產生資料列表資料不使用feed_dict進行tensorboard表示

在tensorflow中存在一種情況,如果資料本身是通過迭代產生的,這時無法拿到資料集進行tensorboard顯示,這時可以先把計算的結果存到列表中,然後使用列表進行顯示操作。 程式碼如下: import tensorflow as tf import numpy as

【產業智慧官】 用新一代技術+商業作業系統(AI-CPS OS:雲端計算+大資料+物聯網+區塊鏈+人工智慧),在場景構建狀態感知-實時分析-自主決策-精準執行-學習提升的認知計算機器智慧

產業智慧官 用新一代技術+商業作業系統(AI-CPS OS:雲端計算+大資料+物聯網+區塊鏈+人工智慧),在場景中構建狀態感知-實時分析-自主決策-精準執行-學習提升的認知計算和機器智慧...

python str字符串 list列表基本操作總結

叠代 組成 結束 enter eve 字符 元素 rip move s = ‘#afsfdf222#‘print(s.capitalize()) # 首字母大寫其他字母小寫print(s.center(20, ‘%‘)) # 居中並在空白處添加指定字符print(