ExpandableListView+Dialog实现弹出二级下拉列表选项。可自由用于Activity和Fragment中

3/1/2017来源:Android开发人气:1539

话说今天刚是本人失业第二天。已经感觉有点无聊了。对于这次失业挺突然的。不过想通之后也没啥可惋惜的。毕竟身怀技术走到哪都不怕找不到饭碗。作为技术人员要做的首要就是不断提高自身技术水平,以适应这个瞬息万变的社会。 本人是15年下半年入行,喜欢这行也是兴趣所向。喜欢那种解决问题后的成就感,完成一个功能后的喜悦感。但是觉得自己又比较矛盾,自己家确实很喜欢编程,但是却对上班编程感觉不是那么特别喜欢,原因是:虽然也是同样的写程序,上班是要根据公司领导的安排而去写一些有时候自己不是很喜欢的代码或者是没有技术含量的代码。而自己写的话肯定是写一些自己喜欢或者自己感兴趣的方向去深究和钻研。希望自己有一天实现经济自由,可以随意学习自己喜欢的技术吧。

好了上面叨叨了很多,下来看今天的正题:一个ExpandableListView+Dialog实现的弹出二级下拉菜单选项的功能。直接老规矩先看效果图:

这里写图片描述

ExpandableListView相信大家从单词上都能看出来,里面有listview。没错,这里给大家大概说一下有兴趣的可以继续查阅资料了解,ExpandableListView是继承自ListView。这样一说估计心里都有个大概了。

下来看看具体实现: 这里我们是在Activity里面实现的 1.首先在 activity_main中添加基本的一些布局,用于后面触发事件和显示结果数据

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:layout_height="match_parent" android:orientation="vertical" tools:context="diaog.com.expandablelistviewdialog.MainActivity"> <EditText android:id="@+id/editText_group" android:layout_width="match_parent" android:layout_height="wrap_content" android:editable="false" android:textSize="22sp" /> <EditText android:id="@+id/editText_child" android:layout_width="match_parent" android:layout_height="wrap_content" android:editable="false" android:textSize="22sp" /> <Button android:id="@+id/btnShowDialog" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Show" android:textSize="22sp" /> </LinearLayout>

这个布局没什么可说的。 2. expandablelistview_item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ExpandableListView android:id="@+id/ew_dialog" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="@android:color/white" /> </LinearLayout>

这里说下它跟listview不同的是要自己独立写一个layout。下来是两个xml布局文件,一个显示一级目录一个显示对应的二级目录

group_item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/group_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:padding="5dp" android:textSize="24sp" /> </LinearLayout>

child_item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_margin="5dp" android:layout_height="wrap_content" android:textSize="18sp" /> </LinearLayout>

3.下来是adapter,这里是继承自BaseExpandableListAdapter

PRivate Context context; private List<String> listGroup = new ArrayList<String>(); private List<List<String>> listChild = new ArrayList<List<String>>(); public MyExpandableListAdapter(Context context, List<String> listGroup, List<List<String>> listChild) { super(); this.context = context; this.listGroup = listGroup; this.listChild = listChild; } @Override public int getGroupCount() { // TODO Auto-generated method stub return listGroup.size(); } @Override public int getChildrenCount(int groupPosition) { // TODO Auto-generated method stub return listChild.get(groupPosition).size(); } @Override public Object getGroup(int groupPosition) { // TODO Auto-generated method stub return listGroup.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { // TODO Auto-generated method stub return childPosition; } @Override public long getGroupId(int groupPosition) { // TODO Auto-generated method stub return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub return childPosition; } @Override public boolean hasStableIds() { // TODO Auto-generated method stub return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { // TODO Auto-generated method stub convertView = LinearLayout.inflate(context, R.layout.group_item, null); TextView text_group = (TextView) convertView.findViewById(R.id.group_text); text_group.setText(listGroup.get(groupPosition)); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // TODO Auto-generated method stub convertView = LinearLayout.inflate(context, R.layout.child_item, null); TextView text_child = (TextView) convertView.findViewById(R.id.text); text_child.setText(listChild.get(groupPosition).get(childPosition)); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { // TODO Auto-generated method stub return true; }

基本跟listview的baseadapter很相似。这里要注意的就是getGroupView和getChildView方法。从方法名称可以看到,一个是获取一级目录layout的一个是获取其下的二级目录的layout。这里我都是饮用了xml的layout的,之前在网上也看到很多人在这里是直接写一个getGenericView(String s)方法

public TextView getGenericView(String s) { // Layout parameters for the ExpandableListView AbsListView.LayoutParams lp = new AbsListView.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT,50); lp.height=36; TextView text = new TextView(activity); text.setLayoutParams(lp); text.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT); text.setPadding(36, 0, 0, 0); text.setTextColor(Color.BLACK); text.setTextSize(22); text.setText(s); return text; }

不过我本人还是习惯尽量讲布局和代码分开,那样感觉可拓展性比较好,例如将来的二级或者一级目录不是一行文字而是一个复杂的布局呢。

4.下来是为了方便,对此功能做了一个封装,创建一个utils类将弹出dialog和添加数据等方法进行封装。

public class SecondaryMemuUtils { private Context context; private ExpandableListView expandableListView; // Layout expandablelist.xml private List<String> listGroup = new ArrayList<String>(); private List<List<String>> listChild = new ArrayList<List<String>>(); private String[] groupDate;//一级目录数据 private String[][] childDate;//对应的二级目录数据 public SecondaryMemuUtils(Context context, ExpandableListView expandableListView, List<String> listGroup, List<List<String>> listChild, String[] groupDate, String[][] childDate) { super(); this.context = context; this.expandableListView = expandableListView; this.listGroup = listGroup; this.listChild = listChild; this.groupDate = groupDate; this.childDate = childDate; } /** * 添加二级菜单数据 * * @param groupDate */ public void addDate(String[] groupDate) { // TODO Auto-generated method stub for (int i = 0; i < groupDate.length; i++) { String group_text = groupDate[i];// 获取每一个一级菜单text listGroup.add(group_text); List<String> children = new ArrayList<String>(); if (listGroup.get(i).equals(group_text)) { mforTwoArrays(children,childDate,i); // children.add("公路建设"); // children.add("铁路建设"); // children.add("矿产开发"); // children.add("旅游开发"); } else if (listGroup.get(i).equals(group_text)) { mforTwoArrays(children,childDate,i); // children.add("河湖养殖"); // children.add("毁林草开垦"); } else if (listGroup.get(i).equals(group_text)) { mforTwoArrays(children,childDate,i); // children.add("水污染"); // children.add("大气污染"); // children.add("土壤污染"); // children.add("固体废弃物污染"); // children.add("噪声污染"); } else { mforTwoArrays(children,childDate,i); // children.add("放牧"); // children.add("砍伐"); // children.add("捕捞"); // children.add("狩猎"); // children.add("道路交通等"); } listChild.add(children); } } /** * 循环添加数据 * @param children * @param arrs * @param j */ private void mforTwoArrays(List<String> children,String[][] arrs, int j){ String[] arr2 = arrs[j]; for (int c = 0; c < arr2.length; c++) { children.add(arr2[c]); } } /** * 类型 * @param editText_group * @param editText_child */ public void createExpandableListViewDialog(final EditText editText_group,final EditText editText_child) { // 设给弹出窗口的view final Dialog dialog; // 弹出类似Spinner选择项的窗口 View viewList = ((Activity) context).getLayoutInflater().inflate( R.layout.expandablelistview_item, null); dialog = new Dialog(context); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);//取消dialog的标题栏 dialog.show(); dialog.setContentView(viewList); expandableListView = (ExpandableListView) viewList.findViewById(R.id.ew_dialog); // 绑定ExpandableListView的数据 MyExpandableListAdapter mAdapter = new MyExpandableListAdapter(context,listGroup,listChild); expandableListView.setAdapter(mAdapter); /** * 1 单击事件 返回 false表示不触发单击事件 */ expandableListView.setOnGroupClickListener(new OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { return false; } }); /** * Child 单击事件 */ expandableListView.setOnChildClickListener(new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View view, int groupPosition, int childPosition, long id) throws RuntimeException { Toast.makeText(context, listGroup.get(groupPosition) + "--->>>" + listChild.get(groupPosition) .get(childPosition).toString(), Toast.LENGTH_SHORT) .show(); // editText1.setText(listGroup.get(groupPosition) // + "下的" // + listChild.get(groupPosition).get(childPosition) // .toString()); editText_group.setText(listGroup.get(groupPosition)); editText_child.setText(listChild.get(groupPosition) .get(childPosition).toString()); dialog.dismiss(); return true; } }); } }

这里为了更好的封装,写了一个mforTwoArrays方法。将传进来的数据自动循环添加进去。这样我们就可以传任意的string类型的二级目录数组数据了。

private void mforTwoArrays(List<String> children,String[][] arrs, int j){ String[] arr2 = arrs[j]; for (int c = 0; c < arr2.length; c++) { children.add(arr2[c]); } }

对于一级目录的数据添加则比较简单

public void addDate(String[] groupDate) { // TODO Auto-generated method stub for (int i = 0; i < groupDate.length; i++) { String group_text = groupDate[i];// 获取每一个一级菜单text listGroup.add(group_text);

就可以循环添加每一个一级目录列表了。 至此算是大功告成,下来我们在测试一下吧。 在MainActivity中调用,首先我们得创建菜单二二级菜单的数据。和装它们的集合list。然后调用我们写好的工具类里面的createExpandableListViewDialog和addDate方法。就是如此简单:

public class MainActivity extends AppCompatActivity { private Button btnShowDialog; private ExpandableListView expandableListView; // private List<String> listGroup = new ArrayList<String>(); private List<List<String>> listChild = new ArrayList<List<String>>(); private String[] groupDate = { "开放建设", "农牧渔业活动", "环境污染", "其他" }; private String[][] childDate = { { "房地产", "公路建设", "铁路建设", "矿产开发", "旅游开发", "管理建设及河道治理" }, { "河湖养殖", "毁林草开垦" }, { "水污染", "大气污染", "土壤污染", "固体废弃物污染", "噪声污染" }, { "放牧", "砍伐", "采挖", "捕捞", "狩猎", "道路交通等" } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final EditText editText_child = (EditText) findViewById(R.id.editText_child); final EditText editText_group = (EditText) findViewById(R.id.editText_group); btnShowDialog = (Button) findViewById(R.id.btnShowDialog); btnShowDialog.setOnClickListener(new View.OnClickListener() { SecondaryMemuUtils secondaryMemuUtils = new SecondaryMemuUtils( MainActivity.this, expandableListView, listGroup, listChild, groupDate, childDate); @Override public void onClick(View view) { listChild.clear(); listGroup.clear(); secondaryMemuUtils.addDate(groupDate);// 添加二级菜单数据 secondaryMemuUtils.createExpandableListViewDialog(editText_group,editText_child); } }); } }

是不是感觉调用的代码不多呢。最后在奉上

源码