
GroupListDemo具体实现:
①demo中将列表页面设计为Fragment页面,方便后期调用;在主界面MainActivity中动态添加GroupListFragment页面;
MainActivity.java
package com.eric.grouplistdemo; import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.os.Bundle; import android.widget.RelativeLayout;public class MainActivity extends Activity {public static GroupListFragment fragment;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);fragment = new GroupListFragment();getFragmentManager().beginTransaction() .replace(R.id.fragContainer, fragment).commit(); } } 动态添加GroupListFragment实例到界面的fragContainer布局中;将fragment声明为static用于在Adapter中组添加子项时进行调用。<?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" ><RelativeLayout android:id="@+id/fragContainer" android:layout_width="match_parent" android:layout_height="match_parent" ></RelativeLayout> </LinearLayout>②实现自定义适配器类MyAdapter,继承自BaseExpandableListAdapter;组项布局及子项布局;
<?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="#0099ff"android:orientation="horizontal"><ImageView android:id="@+id/image_parent" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/image_parent1"/><TextView android:id="@+id/text_parent" android:layout_width="wrap_content" android:layout_height="50dp" android:textColor="#FFF" android:textSize="20sp" android:text="parent1" android:layout_toRightOf="@id/image_parent" android:gravity="center"/><ImageView android:id="@+id/image_delete" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_alignParentRight="true" android:src="@drawable/delete"/><ImageView android:id="@+id/image_add" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_toLeftOf="@id/image_delete" android:src="@drawable/add"/> </RelativeLayout>list_item_child.xml子项布局文件,名称及删除图标;
<?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="40dp"><TextView android:id="@+id/text_child" android:layout_width="wrap_content" android:layout_height="40dp" android:layout_margin="5dp" android:textColor="#0099ff" android:text="child" android:layout_centerInParent="true" android:gravity="center"/><ImageView android:id="@+id/image_delete" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:src="@drawable/delete"/> </RelativeLayout>MyAdapter.java自定义适配器
package com.eric.grouplistdemo;import java.util.List; import java.util.Map;import android.content.Context; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView;public class MyAdapter extends BaseExpandableListAdapter{private List<String> parentList;private Map<String,List<String>> map;private Context context;private EditText edit_modify;private ModifyDialog dialog;//构造函数public MyAdapter(Context context, List<String> parentList, Map<String,List<String>> map) { this.context = context; this.parentList = parentList; this.map = map;}//获取分组数@Overridepublic int getGroupCount() { return parentList.size();}//获取当前组的子项数@Overridepublic int getChildrenCount(int groupPosition) { String groupName = parentList.get(groupPosition); int childCount = map.get(groupName).size(); return childCount;}//获取当前组对象@Overridepublic Object getGroup(int groupPosition) { String groupName = parentList.get(groupPosition); return groupName;}//获取当前子项对象@Overridepublic Object getChild(int groupPosition, int childPosition) { String groupName = parentList.get(groupPosition); String chidlName = map.get(groupName).get(childPosition); return chidlName;}//获取组ID@Overridepublic long getGroupId(int groupPosition) { return groupPosition;}//获取子项ID@Overridepublic long getChildId(int groupPosition, int childPosition) { return childPosition;} @Overridepublic boolean hasStableIds() { return true;}//组视图初始化@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) { final int groupPos = groupPosition;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.list_item_parent, null); }ImageView image = (ImageView) convertView.findViewById(R.id.image_parent); ImageView image_add = (ImageView) convertView.findViewById(R.id.image_add); ImageView image_delete = (ImageView) convertView.findViewById(R.id.image_delete);if(isExpanded){image.setImageResource(R.drawable.image_parent2); }else{image.setImageResource(R.drawable.image_parent1); }image_add.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) { alertAddDialog(MainActivity.fragment.getActivity(), "新增子项", groupPos);} }); image_delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) { GroupListFragment.deleteGroup(groupPos);} }); TextView parentText = (TextView) convertView.findViewById(R.id.text_parent); parentText.setText(parentList.get(groupPosition)); return convertView;}//子项视图初始化@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) { final int groupPos = groupPosition; final int childPos = childPosition;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.list_item_child, null); } TextView childText = (TextView) convertView.findViewById(R.id.text_child); ImageView image_delete = (ImageView) convertView.findViewById(R.id.image_delete); String parentName = parentList.get(groupPosition); String childName = map.get(parentName).get(childPosition); childText.setText(childName);image_delete.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) { GroupListFragment.deleteChild(groupPos, childPos);} }); return convertView;} @Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) { return true;}//弹新增子项对话框public void alertAddDialog(Context context, String title, int currentGroup){ final int group = currentGroup;dialog = new ModifyDialog(context, title, null); edit_modify = dialog.getEditText(); dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) { GroupListFragment.addChild(group, edit_modify.getText().toString()); dialog.dismiss();} }); dialog.show();} } 构造函数:将传入的parentList和map进行数据同步,parentList保存组数据,map保存对应组及其子项list数据;<?xml version="1.0" encoding="utf-8"?> <resources xmlns:android="http://schemas.android.com/apk/res/android"><style name="noTitleDialog" parent="android:style/Theme.Dialog"> <item name="android:width">300dp</item> <item name="android:height">40dp</item> <item name="android:windowNoTitle">true</item></style> </resources>dialog_modify.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/text_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="center" android:background="#0099ff" android:text="修改名称" android:textColor="#FFF" android:textSize="20sp"/><EditText android:id="@+id/edit_modify" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="组名称"/><Button android:id="@+id/btn_commit" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="确定" android:textColor="#FFF" android:background="#0099ff" /> </LinearLayout>ModifyDialog.java
package com.eric.grouplistdemo;import android.app.Dialog; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class ModifyDialog extends Dialog{private TextView text_title;private EditText edit_modify;private Button btn_commit;public ModifyDialog(Context context, String title, String name) { super(context, R.style.noTitleDialog);View view = LayoutInflater.from(getContext()) .inflate(R.layout.dialog_modify, null); text_title = (TextView) view.findViewById(R.id.text_title); edit_modify = (EditText)view.findViewById(R.id.edit_modify); btn_commit = (Button) view.findViewById(R.id.btn_commit); text_title.setText(title); edit_modify.setText(name);super.setContentView(view);}public EditText getEditText(){ return edit_modify;}public void setOnClickCommitListener(View.OnClickListener listener){ btn_commit.setOnClickListener(listener);} } ModifyDialog自定义构造函数中,通过super()加载刚刚自定义的no_title_dialog.xml,声明View加载layout布局dialog_modify.xml;并且获取布局中的相应控件,将构造函数中传来的字符串title和name,分别赋值到标题文本和输入框控件中;最后调用setContentView()初始化对话框视图;<?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"><ExpandableListView android:id="@+id/expandablelistview" android:layout_width="match_parent" android:layout_height="match_parent" android:groupIndicator="@null" ></ExpandableListView><ImageView android:id="@+id/image_add" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true" android:src="@drawable/add"/> </RelativeLayout>这里需要将ExpandableListView的groupIndicator属性设置为@null,不使用其自带的展开图标;
package com.eric.grouplistdemo;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;import android.R.integer; import android.app.Fragment; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ExpandableListView; import android.widget.ImageView; import android.widget.Toast; public class GroupListFragment extends Fragment{private View view;private ExpandableListView expandableListView;public static MyAdapter adapter;public static List<String> parentList;public static Map<String,List<String>> map;private ModifyDialog dialog;private EditText edit_modify;private ImageView image_add;private int currentGroup,currentChild;public static SharedPreferences sp;public static Editor editor;public static String dataMap,dataParentList;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {view = inflater.inflate(R.layout.fragment_group_list, container, false); expandableListView = (ExpandableListView) view.findViewById(R.id.expandablelistview); image_add = (ImageView) view.findViewById(R.id.image_add); image_add.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) { alertAddDialog(getActivity(), "新增组");} });initData();adapter = new MyAdapter(getActivity().getApplicationContext(), parentList, map); expandableListView.setAdapter(adapter);//设置子项点击事件 MyOnClickListener myListener = new MyOnClickListener(); expandableListView.setOnChildClickListener(myListener);//设置长按点击事件 MyOnLongClickListener myLongListener = new MyOnLongClickListener(); expandableListView.setOnItemLongClickListener(myLongListener);return view;}public void initData(){ map = new HashMap<String, List<String>>(); parentList = new ArrayList<String>();sp = getActivity().getApplicationContext().getSharedPreferences("spfile", getActivity().MODE_PRIVATE); dataMap = sp.getString("dataMap", null); dataParentList = sp.getString("dataParentList", null);if(dataMap == null || dataParentList == null){parentList = new ArrayList<String>();parentList.add("客厅");parentList.add("厨房");parentList.add("卧室"); List<String> list1 = new ArrayList<String>();list1.add("客厅空调");list1.add("客厅电视");list1.add("客厅电灯");map.put("客厅", list1);List<String> list2 = new ArrayList<String>();list2.add("厨房油烟机");list2.add("厨房电灯");list2.add("厨房电器");map.put("厨房", list2);List<String> list3 = new ArrayList<String>();list3.add("卧室空调");list3.add("卧室灯光");list3.add("卧室电视");map.put("卧室", list3); }else{try { //初始化parentList JSONArray jsonArray = new JSONArray(dataParentList); for (int i = 0; i < jsonArray.length(); i++) {parentList.add(jsonArray.get(i).toString()); }//初始化map JSONObject jsonObject = new JSONObject(dataMap); for (int i = 0; i < jsonObject.length(); i++) {String key = jsonObject.getString(parentList.get(i));JSONArray array = new JSONArray(key);List<String> list = new ArrayList<String>();for (int j = 0; j < array.length(); j++) { list.add(array.get(j).toString());}map.put(parentList.get(i), list); }Log.d("eric", "①:"+map+"②:"+parentList);} catch (JSONException e) { e.printStackTrace(); Log.e("eric","String转Map或List出错"+e);} } Log.e("eric", dataMap+"!&&!"+dataParentList); saveData();}//自定义点击监听事件public class MyOnClickListener implements ExpandableListView.OnChildClickListener{ @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {String str = "choose"+groupPosition+"-"+childPosition;Toast.makeText(getActivity(), str, Toast.LENGTH_SHORT).show();return false; }}//自定义长按监听事件public class MyOnLongClickListener implements AdapterView.OnItemLongClickListener{ @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {//长按子项if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD){ long packedPos = ((ExpandableListView) parent).getExpandableListPosition(position); int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos); int childPosition = ExpandableListView.getPackedPositionChild(packedPos);currentGroup = groupPosition; currentChild = childPosition;String str = (String)adapter.getChild(groupPosition, childPosition); alertModifyDialog("修改此项名称",str); Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show(); return true;//长按组}else if(ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_GROUP){ long packedPos = ((ExpandableListView) parent).getExpandableListPosition(position); int groupPosition = ExpandableListView.getPackedPositionGroup(packedPos); int childPosition = ExpandableListView.getPackedPositionChild(packedPos);currentGroup = groupPosition; currentChild = childPosition;String group = parentList.get(groupPosition); alertModifyDialog("修改组名称", group);String str = (String)adapter.getGroup(groupPosition); Toast.makeText(getActivity(),str,Toast.LENGTH_SHORT).show();} return false;}}//新增组public static void addGroup(String newGroupName){ parentList.add(newGroupName); List<String> list = new ArrayList<String>(); map.put(newGroupName, list); adapter.notifyDataSetChanged(); saveData();}//新增子项到指定组public static void addChild(int groupPosition, String newChildName){ String groupName = parentList.get(groupPosition); List<String> list = map.get(groupName); list.add(newChildName); adapter.notifyDataSetChanged(); saveData();}//删除指定组public static void deleteGroup(int groupPos){ String groupName = parentList.get(groupPos); map.remove(groupName); parentList.remove(groupPos); adapter.notifyDataSetChanged(); saveData();}//删除指定子项public static void deleteChild(int groupPos, int childPos){ String groupName = parentList.get(groupPos); List<String> list = map.get(groupName); list.remove(childPos); adapter.notifyDataSetChanged(); saveData();}//修改该项名称public void modifyName(int groupPosition, int childPosition, String modifyName){ Toast.makeText(getActivity(), String.valueOf(groupPosition)+"-"+String.valueOf(childPosition), Toast.LENGTH_SHORT).show(); if(childPosition<0){//修改组名称String groupName = parentList.get(groupPosition);if(!groupName.equals(modifyName)){ map.put(modifyName, map.get(groupName)); map.remove(groupName); parentList.set(groupPosition, modifyName);} }else{//修改子项名称String group = parentList.get(groupPosition);List<String> list =map.get(group);list.set(childPosition, modifyName);map.put(group, list); } adapter.notifyDataSetChanged(); saveData();}//弹修改对话框public void alertModifyDialog(String title, String name){ dialog = new ModifyDialog(getActivity(), title, name); edit_modify = dialog.getEditText(); dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) { modifyName(currentGroup, currentChild, edit_modify.getText().toString()); dialog.dismiss();} }); dialog.show();}//弹新增组对话框public void alertAddDialog(Context context, String title){ dialog = new ModifyDialog(context, title, null); edit_modify = dialog.getEditText(); dialog.setOnClickCommitListener(new OnClickListener() {@Overridepublic void onClick(View v) { addGroup(edit_modify.getText().toString()); dialog.dismiss();} }); dialog.show();}//保存数据public static void saveData(){ JSONObject jsonObject = new JSONObject(map); dataMap = jsonObject.toString(); dataParentList = parentList.toString();editor = sp.edit(); editor.putString("dataMap", dataMap); editor.putString("dataParentList", dataParentList); editor.commit();} } 内容有点多,一个个来: