图片见附件

 

项目需要展示一个通讯簿,通讯簿中的手机号码是分组的,要求勾选组时,自动勾选组下的手机号码,实现效果如下:


我们这个实例主要讲的就是当点击一个分组的时候,分组里的所有人就默认的全部选中,有了这个功能我们在群发的时候就会给我们省去不少麻烦,这样我们就可以不用一个一个的选中了。那么我们就来看看这个效果是怎么样实现吗。

下面是实现步骤。

1、新建类PhoneListItem,用于表示分组中的每一个手机号码。

Java代码:

下载附件 (36.65 KB)

 下载附件 (36.65 KB)

 

    1. package eoe.ydtf.android;
    2. 
    3. public class PhoneListItem {
    4. 
    5. public String phone,name;
    6. 
    7. public boolean checked;
    8. 
    9. public PhoneListItem(String _name,String _phone,boolean _checked){
    10. 
    11. name=_name;
    12. 
    13. phone=_phone;
    14. 
    15. checked=_checked;
    16. 
    17. }
    18. 
    19. }


    复制代码


    2、新建布局文件phone_list_item.xml,用于定义分组下面的每一条手机记录的页面布局。

    Java代码:


    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    2. 
    3. android:layout_width="fill_parent" 
    4. android:layout_height="wrap_content" 
    5. android:orientation="horizontal" 
    6. android:minHeight="40px" 
    7. android:layout_gravity="center_vertical"> 
    8. 
    9. <CheckBox 
    10. android:id="@+id/phone_check" 
    11. android:focusable="false" 
    12. android:layout_width="wrap_content" 
    13. android:layout_height="wrap_content" 
    14. android:layout_marginLeft="35px" 
    15. android:checked="false"/> 
    16. 
    17. <TextView 
    18. android:id="@+id/phone_name" 
    19. android:layout_width="80dip" 
    20. android:layout_height="wrap_content" 
    21. android:layout_gravity="center_vertical" /> 
    22. 
    23. <TextView 
    24. android:id="@+id/phone_number" 
    25. android:layout_width="wrap_content" 
    26. android:layout_height="wrap_content" 
    27. android:textColor="?android:attr/textColorPrimary" 
    28. android:paddingLeft="10px" 
    29. android:layout_gravity="center_vertical" /> 
    30. 
    31. </LinearLayout>


    复制代码


    这个主要就是我们在这里布局,你想要什么样的效果都可以,这里就是上面效果图的布局

    3、新建类PhoneGroup,用于表示一个分组。代码当中主要就是在一个分组里的内容,我们在用一个boolean值,这个就是说当你选中的时候是真,当你没有选中的时候是假,所以这个很主要,有了boolean值才能知道你是否选中。

    Java代码:


    1. import java.util.List;
    2. 
    3. public class PhoneGroup {
    4. 
    5. public String title;
    6. 
    7. private boolean checked;
    8. 
    9. public List<PhoneListItem> children; 
    10. 
    11. public PhoneGroup(String title,boolean checked,List<PhoneListItem> children){
    12. 
    13. this.title=title;
    14. 
    15. setChecked(checked);
    16. 
    17. this.children=children;
    18. 
    19. }
    20. 
    21. public boolean getChecked(){
    22. 
    23. return checked;
    24. 
    25. }
    26. 
    27. public void setChecked(boolean b){
    28. 
    29. checked=b;
    30. 
    31. if(children!=null&&children.size()>0){//若children不为空,循环设置children的checked
    32. 
    33. for(PhoneListItem each : children){
    34. 
    35. each.checked=checked;
    36. 
    37. }
    38. 
    39. }
    40. 
    41. }
    42. 
    43. }


    复制代码


    4、新建Activity布局文件phone_browser.xml,用于定义通讯簿的展现页面。

    Java代码:


    1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    2. 
    3. android:layout_width="fill_parent" 
    4. android:layout_height="fill_parent" 
    5. android:orientation="vertical"> 
    6. 
    7. <ExpandableListView 
    8. android:id="@+id/phonelist" 
    9. android:layout_width="fill_parent" 
    10. android:layout_height="0dip" 
    11. android:layout_weight="1" /> 
    12. 
    13. </LinearLayout>


    复制代码


    5、新建类QxtPhoneSelect,用于呈现通讯簿的Activity页面。

    Java代码:


    1. package eoe.ydtf;
    2. 
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. import com.ydtf.android.PhoneGroupAdapter.ExpandableListHolder;
    6. import android.app.Activity;
    7. import android.os.Bundle;
    8. import android.view.View;
    9. 
    10. import android.widget.ExpandableListView;
    11. 
    12. public class QxtSelectPhone extends Activity implements 
    13. 
    14. ExpandableListView.OnGroupClickListener,ExpandableListView.OnChildClickListener{
    15. 
    16. private List<PhoneGroup> groups; 
    17. 
    18. private PhoneGroupAdapter exlist_adapter = null; 
    19. 
    20. private ExpandableListView exlist; 
    21. 
    22. public void onCreate(Bundle savedInstanceState) { 
    23. 
    24. super.onCreate(savedInstanceState); 
    25. 
    26. //加载layout
    27. 
    28. setContentView(R.layout.phone_browser); 
    29. 
    30. //取得listview
    31. 
    32. exlist = (ExpandableListView) findViewById(R.id.phonelist); 
    33. 
    34. //调用init方法,这个方法主要是,初始化一些数据
    35. 
    36. init();
    37. 
    38. //构建expandablelistview的适配器
    39. 
    40. exlist_adapter = new PhoneGroupAdapter(this, groups); 
    41. 
    42. exlist.setOnChildClickListener(this);
    43. 
    44. exlist.setAdapter(exlist_adapter); //绑定视图-适配器
    45. 
    46. }
    47. 
    48. private void init() { 
    49. 
    50. groups = new ArrayList<PhoneGroup>();
    51. 
    52. 
    53. //构建List用作group1的子项
    54. 
    55. List<PhoneListItem> group1_children = new ArrayList<PhoneListItem>();
    56. 
    57. //往List中添加内容
    58. 
    59. PhoneListItem item = new PhoneListItem("和文明","1308763994", false); 
    60. 
    61. group1_children.add(item); 
    62. 
    63. item = new PhoneListItem("黄文明","1308763994", false); 
    64. 
    65. group1_children.add(item); 
    66. 
    67. item = new PhoneListItem("王文明","1308763994", false); 
    68. 
    69. group1_children.add(item); 
    70. 
    71. //拼装成 PhoneGroup
    72. 
    73. PhoneGroup phonegroup1=new PhoneGroup("group1",false,group1_children);
    74. 
    75. //------把前面的代码复制一遍,再添加一个组group2
    76. 
    77. //构建List用作group2的子项
    78. 
    79. List<PhoneListItem> group2_children = new ArrayList<PhoneListItem>();
    80. 
    81. //往List中添加内容
    82. 
    83. item = new PhoneListItem("张文明","1589065423", false); 
    84. 
    85. group2_children.add(item); 
    86. 
    87. item = new PhoneListItem("李文明","1589065423", false); 
    88. 
    89. group2_children.add(item); 
    90. 
    91. item = new PhoneListItem("赵文明","1589065423", false); 
    92. 
    93. group2_children.add(item); 
    94. 
    95. //拼装成 PhoneGroup
    96. 
    97. PhoneGroup phonegroup2=new PhoneGroup("group2",false,group2_children);
    98. 
    99. //添加进groups数组
    100. 
    101. groups.add(phonegroup1);
    102. 
    103. groups.add(phonegroup2);
    104. 
    105. }
    106. 
    107. //当分组行背点击时,让分组呈现“选中/取消选中”状态。
    108. 
    109. @Override
    110. public boolean onChildClick(ExpandableListView parent, View v,
    111. 
    112. int groupPosition, int childPosition, long id) {
    113. 
    114. PhoneGroupAdapter.ExpandableListHolder holder=(ExpandableListHolder) v.getTag(); 
    115. 
    116. holder.chkChecked.setChecked(!holder.chkChecked.isChecked());
    117. 
    118. groups.get(groupPosition).children.get(childPosition).checked=
    119. 
    120. !groups.get(groupPosition).children.get(childPosition).checked;
    121. 
    122. return false;
    123. 
    124. }
    125. 
    126. @Override
    127. public boolean onGroupClick(ExpandableListView parent, View v,
    128. 
    129. int groupPosition, long id) {
    130. 
    131. // groups.get(groupPosition).setChecked(!groups.get(groupPosition).getChecked());
    132. 
    133. // exlist_adapter.notifyDataSetChanged();
    134. 
    135. return false;
    136. 
    137. } 
    138. 
    139. }


    复制代码


    6、新建类PhoneGroupAdapter,实现BaseExpandableListAdapter

    Java代码:


    1. package eoe.ydtf.android;
    2. 
    3.  
    4. import java.util.List;
    5. import android.content.Context;
    6. import android.util.Log;
    7. import android.view.LayoutInflater;
    8. import android.view.View;
    9. import android.view.View.OnClickListener;
    10. import android.view.ViewGroup;
    11. import android.widget.BaseExpandableListAdapter;
    12. import android.widget.Button;
    13. import android.widget.CheckBox;
    14. import android.widget.CompoundButton;
    15. import android.widget.CompoundButton.OnCheckedChangeListener;
    16. import android.widget.TextView;
    17. 
    18.  
    19. public class PhoneGroupAdapter extends BaseExpandableListAdapter {
    20. class ExpandableListHolder { //定义一个内部类,用于保存listitem的3个子视图引用,2个textview和1个checkbox
    21. TextView tvName; 
    22. TextView tvPhone; 
    23. CheckBox chkChecked; 
    24. } 
    25. private Context context; //父activity
    26. private LayoutInflater mChildInflater; //用于加载listitem的布局xml
    27. private LayoutInflater mGroupInflater; //用于加载group的布局xml
    28. private List<PhoneGroup> groups; //所有group
    29. //构造方法:参数c - activity,参数group - 所有group
    30. public PhoneGroupAdapter(Context c,List<PhoneGroup> groups){
    31. context=c;
    32. mChildInflater = (LayoutInflater) context
    33. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    34. mGroupInflater = (LayoutInflater) context
    35. .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    36. this.groups = groups;
    37. }
    38. @Override
    39. public Object getChild(int arg0, int arg1) {//根据组索引和item索引,取得listitem // TODO Auto-generated method stub
    40. return groups.get(arg0).children.get(arg1);
    41. }
    42. @Override
    43. public long getChildId(int arg0, int arg1) {//返回item索引
    44. return arg1;
    45. }
    46. @Override
    47. public int getChildrenCount(int groupPosition) {//根据组索引返回分组的子item数
    48. return groups.get(groupPosition).children.size();
    49. }
    50. @Override
    51. public Object getGroup(int groupPosition) {//根据组索引返回组
    52. return groups.get(groupPosition);
    53. }
    54. @Override
    55. public int getGroupCount() {//返回分组数
    56. return groups.size();
    57. }
    58. @Override
    59. public long getGroupId(int groupPosition) {//返回分组索引
    60. return groupPosition;
    61. }
    62. @Override
    63. public View getGroupView(int position, boolean isExpanded,
    64. View view, ViewGroup parent) {//根据组索引渲染"组视图"
    65. ExpandableListHolder holder = null; //清空临时变量holder
    66. if (view == null) { //判断view(即view是否已构建好)是否为空
    67. 
    68. //若组视图为空,构建组视图。注意flate的使用,R.layout.browser_expandable_list_item代表了
    69. //已加载到内存的browser_expandable_list_item.xml文件
    70. view = mGroupInflater.inflate( 
    71. R.layout.phone_list_item, null); 
    72. //下面主要是取得组的各子视图,设置子视图的属性。用tag来保存各子视图的引用
    73. holder = new ExpandableListHolder(); 
    74. //从view中取得textView
    75. holder.tvName = (TextView) view.findViewById(R.id.phone_name); 
    76. //从view中取得textview
    77. holder.tvPhone = (TextView) view.findViewById(R.id.phone_number); 
    78. //从view中取得checkbox
    79. holder.chkChecked = (CheckBox) view 
    80. .findViewById(R.id.phone_check); 
    81. // holder.chkChecked.setEnabled(false);//禁用checkbox
    82. //把checkbox、textview的引用保存到组视图的tag属性中
    83. view.setTag(holder); 
    84. } else { //若view不为空,直接从view的tag属性中获得各子视图的引用
    85. holder = (ExpandableListHolder) view.getTag(); 
    86. }
    87. //对应于组索引的组数据(模型)
    88. PhoneGroup info = this.groups.get(position); 
    89. if (info != null) { 
    90. //根据模型值设置textview的文本
    91. holder.tvName.setText(info.title); 
    92. //根据模型值设置checkbox的checked属性
    93. holder.chkChecked.setChecked(info.getChecked()); 
    94. holder.chkChecked.setTag(info);
    95. holder.chkChecked.setOnClickListener(new OnClickListener(){
    96. @Override
    97. public void onClick(View v) {
    98. PhoneGroup group=(PhoneGroup)v.getTag();
    99. group.setChecked(!group.getChecked());
    100. notifyDataSetChanged();
    101. }
    102. });
    103. } 
    104. // TODO Auto-generated method stub
    105. return view;
    106. }
    107. //行渲染方法 
    108. @Override
    109. public View getChildView(int groupPosition, int childPosition, 
    110. boolean isLastChild, View convertView, ViewGroup parent) { 
    111. ExpandableListHolder holder = null; //清空临时变量
    112. if (convertView == null) { //若行未初始化
    113. //通过flater初始化行视图
    114. convertView = mChildInflater.inflate( 
    115. R.layout.phone_list_item, null); 
    116. //并将行视图的3个子视图引用放到tag中
    117. holder = new ExpandableListHolder(); 
    118. holder.tvName = (TextView) convertView 
    119. .findViewById(R.id.phone_name); 
    120. 
    121. holder.tvPhone = (TextView) convertView.findViewById(R.id.phone_number); 
    122. holder.chkChecked = (CheckBox) convertView 
    123. .findViewById(R.id.phone_check);
    124. // holder.chkChecked.setEnabled(false);
    125. convertView.setTag(holder);
    126. } else { //若行已初始化,直接从tag属性获得子视图的引用
    127. holder = (ExpandableListHolder) convertView.getTag(); 
    128. } 
    129. //获得行数据(模型)
    130. PhoneListItem info = this.groups.get(groupPosition) 
    131. .children.get(childPosition); 
    132. 
    133. if (info != null) { 
    134. //根据模型数据,设置行视图的控件值
    135. holder.tvName.setText(info.name); 
    136. holder.tvPhone.setText(info.phone); 
    137. holder.chkChecked.setChecked(info.checked); 
    138. holder.chkChecked.setTag(info);
    139. holder.chkChecked.setOnClickListener(new OnClickListener(){
    140. @Override
    141. public void onClick(View v) {
    142. CheckBox check=(CheckBox)v;
    143. PhoneListItem item=(PhoneListItem)v.getTag();
    144. item.checked=!item.checked;
    145. // check.setChecked(!check.isChecked());
    146. }
    147. 
    148. });
    149. } 
    150. return convertView; 
    151. } 
    152. @Override
    153. public boolean hasStableIds() {//行是否具有唯一id
    154. return false;
    155. }
    156. @Override
    157. public boolean isChildSelectable(int groupPosition, int childPosition) {//行是否可选
    158. return true;
    159. }
    160. }