zoukankan      html  css  js  c++  java
  • Android:ExpandableListView使用

    前言

    眼下回到了工作岗位,第一件事情就是ExpandListView的优化。这里简单的用一个Demo介绍一下ExpandableListView的使用。

    简介一下Demo实现的功能,主要是继承BaseExpandableListAdapter来自己定义adapter呈现ExpandableListView数据:
    • 每一个child item有一个TextView和一个ImageView删除标识。
    • 当点击一个child item,弹出Toast提示。
    • child item能够通过点击删除图标来删除。

    • 每次展开特定group时。其它group自己主动收缩。

    Demo效果展示:




    Android实现

    创建一个新的Android项目,我将其命名为expandtutorial。

    XML布局文件

    expandtutorial项目总共须要三个xml布局文件。各自是activity_main.xml。 child_item.xml。 group_item.xml。

    activity_main.xml

    这个是用来布局ExpandableListView的,内容例如以下:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    
        <ExpandableListView
            android:id="@+id/expandable_list_view_id"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >
        </ExpandableListView>
    
    </RelativeLayout>

    group_item.xml

    这是用来定义父列表的样式,由一个TextView和一个ImageView构成

    <?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="50dp"
        android:background="#ffffff"
        android:orientation="horizontal"
        android:gravity="center_vertical">
        
        <TextView 
            android:id="@+id/group_text"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="16dp"
            android:textColor="#808080"
            android:textSize="16sp"
            android:gravity="center_vertical"
            android:layout_alignParentLeft="true"
            android:text="@string/app_name"/>
        
        <ImageView 
            android:id="@+id/group_indicator"
            android:src="@drawable/ic_guide_listview_down"
            android:contentDescription="@null"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginRight="16sp"
            android:layout_alignParentRight="true"/>
        
    
    </RelativeLayout>
    

    child_item.xml

    这是用来定义孩子列表的样式

    <?

    xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/child_item_id" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" > <TextView android:id="@+id/child_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:paddingLeft="25dp" /> <ImageView android:id="@+id/child_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:contentDescription="@null" android:src="@drawable/delete" /> </RelativeLayout>


    自己定义Adapter

    自己定义adapter是继承自BaseExpandableListAdapter。有几个须要注意的地方:
    • 使用静态内部类标识父item和子item的weidget,由于这些控件的id是同样的,这样能够节省掉每次findViewById的时间。
    • 重写(override)isChildSelectable方法,返回true,表示子item是能够点击的。
    package com.example.expandtutorial;
    
    import java.util.ArrayList;
    
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.graphics.Typeface;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.BaseExpandableListAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    
    public class CustomerAdapter extends BaseExpandableListAdapter{
    	private ArrayList<ParentObj> datas;
    	private Context context;
    	
    	public CustomerAdapter(ArrayList<ParentObj> datas, Context context) {
    		super();
    		this.datas = datas;
    		this.context = context;
    	}
    
    	@Override
    	public int getGroupCount() {
    		return datas.size();
    	}
    
    	@Override
    	public int getChildrenCount(int groupPosition) {
    		return datas.get(groupPosition).getChilds().size();
    	}
    
    	@Override
    	public Object getGroup(int groupPosition) {
    		return datas.get(groupPosition);
    	}
    
    	@Override
    	public Object getChild(int groupPosition, int childPosition) {
    		return datas.get(groupPosition).getChilds().get(childPosition);
    	}
    
    	@Override
    	public long getGroupId(int groupPosition) {
    		return groupPosition;
    	}
    
    	@Override
    	public long getChildId(int groupPosition, int childPosition) {
    		return childPosition;
    	}
    
    	@Override
    	// 是否有稳定的id。跟刷新顺序有关
    	public boolean hasStableIds() {
    		return false;
    	}
    
    	@Override
    	public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    		ParentViewHolder pviewHolder;
    		
    		if (convertView == null) {
    			convertView = LayoutInflater.from(context).inflate(R.layout.group_item, parent, false);
    			pviewHolder = new ParentViewHolder();
    			pviewHolder.pTextView = (TextView) convertView.findViewById(R.id.group_text);
    			pviewHolder.pImageView = (ImageView) convertView.findViewById(R.id.group_indicator);
    			convertView.setTag(pviewHolder);
    		}
    		
    		pviewHolder = (ParentViewHolder)convertView.getTag();
    		pviewHolder.pTextView.setTypeface(null, Typeface.BOLD);
    		pviewHolder.pTextView.setText(datas.get(groupPosition).getpName());
    		
    		if (isExpanded) {
    			pviewHolder.pImageView.setImageResource(R.drawable.ic_guide_listview_up);
    		} else {
    			pviewHolder.pImageView.setImageResource(R.drawable.ic_guide_listview_down);
    		}
    		
    		return convertView;
    	}
    
    	@Override
    	public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
    			ViewGroup parent) {
    		ChildViewHolder cViewHolder;
    		
    		if (convertView == null) {
    			convertView = LayoutInflater.from(context).inflate(R.layout.child_item, parent, false);
    			cViewHolder = new ChildViewHolder();
    			cViewHolder.cTextView = (TextView)convertView.findViewById(R.id.child_item);
    			cViewHolder.cImageView = (ImageView) convertView.findViewById(R.id.child_delete);
    			convertView.setTag(cViewHolder);
    		}
    		
    		cViewHolder = (ChildViewHolder)convertView.getTag();
    		cViewHolder.cTextView.setText(datas.get(groupPosition).getChilds().get(childPosition).getcName());
    		
    		final int gPosition = groupPosition;
    		final int cPosition = childPosition;
    		cViewHolder.cImageView.setOnClickListener(new OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				AlertDialog.Builder builder = new AlertDialog.Builder(context);
    				builder.setMessage("Do you want to remove?");
    				builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
    					
    					@Override
    					public void onClick(DialogInterface dialog, int which) {
    						datas.get(gPosition).getChilds().remove(cPosition);
    						notifyDataSetChanged();
    					}
    				});
    				builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
    					
    					@Override
    					public void onClick(DialogInterface dialog, int which) {
    						dialog.cancel();
    					}
    				});
    				AlertDialog alertDialog = builder.create();
    				alertDialog.show();
    			}
    		});
    		
    		return convertView;
    	}
    
    	@Override
    	public boolean isChildSelectable(int groupPosition, int childPosition) {
    		return true;
    	}
    	
    	static class ParentViewHolder {
    		TextView pTextView;
    		ImageView pImageView;
    	}
    	
    	static class ChildViewHolder {
    		TextView cTextView;
    		ImageView cImageView;
    	}
    }
    

    Activity

    我们的主Activity,用来呈现UI效果,这里主要有两个地方须要注意:
    • ExpandableListView须要和自己定义adapter进行绑定,通过setAdapter方法。

    • 默认ExpandableListView带了一个指示箭头。我们自己定义布局是不须要这个指示箭头的。能够使用expandableListView.setGroupIndicator(null);方法将其去掉。
    • 设置setOnGroupExpandListener,当展开一个特定的group时,关闭其它group。
    • 设置setOnChildClickListener,监听孩子点击事件。
    package com.example.expandtutorial;
    
    import java.util.ArrayList;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ExpandableListView;
    import android.widget.ExpandableListView.OnChildClickListener;
    import android.widget.ExpandableListView.OnGroupExpandListener;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    	private ExpandableListView expandableListView;
    	private CustomerAdapter customerAdapter;
    	private ArrayList<ParentObj> listData = new ArrayList<ParentObj>();
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    
    		createGroupData();
    		
    		createChildData();
    		
    		expandableListView = (ExpandableListView) findViewById(R.id.expandable_list_view_id);
    		customerAdapter = new CustomerAdapter(listData, this);
    		expandableListView.setAdapter(customerAdapter);
    		expandableListView.setGroupIndicator(null);
    		
    		expandableListView.setOnGroupExpandListener(new OnGroupExpandListener() {
    			
    			@Override
    			public void onGroupExpand(int groupPosition) {
    				for (int i = 0; i < customerAdapter.getGroupCount(); i ++) {
    					if (i != groupPosition) {
    						expandableListView.collapseGroup(i);
    					}
    				}
    			}
    		});
    		
    		expandableListView.setOnChildClickListener(new OnChildClickListener() {
    			
    			@Override
    			public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
    				Toast.makeText(MainActivity.this, listData.get(groupPosition).getChilds().get(childPosition).getcName(), Toast.LENGTH_LONG).show();
    				return true;
    			}
    		});
    	}
    
    	private void createGroupData() {
    		ParentObj p1 = new ParentObj();
    		p1.setpName("HP");
    		listData.add(p1);
    
    		ParentObj p2 = new ParentObj();
    		p2.setpName("DELL");
    		listData.add(p2);
    
    		ParentObj p3 = new ParentObj();
    		p3.setpName("Lenovo");
    		listData.add(p3);
    
    		ParentObj p4 = new ParentObj();
    		p4.setpName("Sony");
    		listData.add(p4);
    
    		ParentObj p5 = new ParentObj();
    		p5.setpName("HCL");
    		listData.add(p5);
    
    		ParentObj p6 = new ParentObj();
    		p6.setpName("Samsung");
    		listData.add(p6);
    	}
    
    	private void createChildData() {
    		// preparing laptops collection(child)
    		String[] hpModels = { "HP Pavilion G6-2014TX", "ProBook HP 4540", "HP Envy 4-1025TX" };
    		String[] hclModels = { "HCL S2101", "HCL L2102", "HCL V2002" };
    		String[] lenovoModels = { "IdeaPad Z Series", "Essential G Series", "ThinkPad X Series", "Ideapad Z Series" };
    		String[] sonyModels = { "VAIO E Series", "VAIO Z Series", "VAIO S Series", "VAIO YB Series" };
    		String[] dellModels = { "Inspiron", "Vostro", "XPS" };
    		String[] samsungModels = { "NP Series", "Series 5", "SF Series" };
    		
    		for (ParentObj p : listData) {
    			if (p.getpName().equals("HP")) {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < hpModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(hpModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			} else if (p.getpName().equals("DELL")) {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < dellModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(dellModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			} else if (p.getpName().equals("Lenovo")) {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < lenovoModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(lenovoModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			} else if (p.getpName().equals("Sony")) {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < sonyModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(sonyModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			} else if (p.getpName().equals("HCL")) {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < hclModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(hclModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			} else {
    				ArrayList<ChildObj> clists = new ArrayList<ChildObj>();
    				for (int i = 0; i < samsungModels.length; i ++) {
    					ChildObj cObj = new ChildObj();
    					cObj.setcName(samsungModels[i]);
    					clists.add(cObj);
    				}
    				p.setChilds(clists);
    			}
    		}
    	}
    }
    
    class ParentObj {
    	private String pName;
    	private ArrayList<ChildObj> childs = new ArrayList<ChildObj>();
    
    	public String getpName() {
    		return pName;
    	}
    
    	public void setpName(String pName) {
    		this.pName = pName;
    	}
    
    	public ArrayList<ChildObj> getChilds() {
    		return childs;
    	}
    
    	public void setChilds(ArrayList<ChildObj> childs) {
    		this.childs.clear();
    		this.childs.addAll(childs);
    	}
    }
    
    class ChildObj {
    	private String cName;
    
    	public String getcName() {
    		return cName;
    	}
    
    	public void setcName(String cName) {
    		this.cName = cName;
    	}
    }

    源代码

    我将源代码上传到CSDN,大家能够免费下载,欢迎跟帖讨论。源代码地址:http://download.csdn.net/detail/zinss26914/7532205



  • 相关阅读:
    PHP---无限极分类数组处理
    PHPExcel数据导入(含图片)
    PHP数组与xml互相转换
    微信APP支付【签名失败】
    winform窗体关闭方案
    ss的优先级 和 权重
    Anaconda 与 conda 区别
    c#FileStream文件读写
    C# DataTable 某一列取算
    关于解决DevExpress用DevExpress patch工具破解后经常弹出试用框的问题
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/7095710.html
Copyright © 2011-2022 走看看