上一篇已经将二级树形列表做了封装,如果直接使用的话,看上去是没有任何问题了,但是bug还是有的,比如一级菜单下面没有子栏目的话,点击会出现app闪退现象。这个就是个很大的缺陷,在加上实现操作中不仅仅是简单的列表展示,还会有动态添加一个父节点,或者动态添加一个子节点,动态删除一个节点,又或者动态删除一个子节点。这些都是必须的。
所以接下来我要把这些都要补充进去,这样用起来就基本满足一般的需求了。
首先是LayerAdapterInterface 接口:
package com.example.appview.Common.TwoTree; import android.view.View; import android.view.ViewGroup; public interface LayerAdapterInterface { /** * * @param groupPosition 第一层位置 * @param convertView 第一层视图 * @return */ public View getGroupView(int groupPosition, View convertView); /** * * @param groupPosition 第一层组位置 * @param childPosition 第二层view位置 * @param convertView 第二层视图 * @return */ public View getChildView(int groupPosition, int childPosition, View convertView); }
接下来是通用类的封装:
package com.example.appview.Common.TwoTree; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.ExpandableListView; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.example.appview.Demo; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Model.ThreeTreeModel; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /* _ooOoo_ o8888888o 88" . "88 (| -_- |) O = /O ____/`---'\____ .' \| |// `. / \||| : |||// / _||||| -:- |||||- | | \ - /// | | | \_| ''---/'' | | .-\__ `-` ___/-. / ___`. .' /--.-- `. . __ ."" '< `.___\_<|>_/___.' >'"". | | : `- \`.;` _ /`;.`/ - ` : | | `-. \_ __ /__ _/ .-` / / ======`-.____`-.___\_____/___.-`____.-'====== `=---=' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 佛祖保佑 永无BUG */ public class LayerAdapterHelper<T1,T2,TControl extends LayerAdapterInterface> extends BaseExpandableListAdapter { public List<T1> oneTree; //二级列表第一层 public List<List<T2>> twoTree;//二级列表第二层 private TControl tControl; //这个是我们初始化控件用的类,这个是每一个Activity页面独有的,因为每个布局里面的内容可能不一样。 private int RoneTree;//这个是二级列表第一层的页面布局 R.layout.布局页面 private int RtwoTree;//这个是二级列表第二层的页面布局 R.layout.布局页面 private Context context; LayoutInflater layoutInflater; public LayerAdapterHelper(Context context,List<T1> oneTree, List<List<T2>> twoTree,TControl tControl,int RoneTree,int RtwoTree){ this.context=context; this.oneTree=oneTree; this.twoTree=twoTree; this.tControl=tControl; this.RoneTree=RoneTree; this.RtwoTree=RtwoTree; layoutInflater = LayoutInflater.from(context); } //保证每次只展开一组 public void OnlyOne(ExpandableListView expandableListView){ expandableListView.setOnGroupExpandListener(new ExpandableListView.OnGroupExpandListener(){ @Override public void onGroupExpand(int groupPosition) { //保证每次只展开一组 int count=expandableListView.getExpandableListAdapter().getGroupCount(); for(int i=0;i<count; i++){ if(groupPosition != i){ expandableListView.collapseGroup(i); } } } }); } // 这里是控制如果列表没有孩子菜单不展开的效果 public void IsChildenCount(ExpandableListView expandableListView){ expandableListView.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() { @Override public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) { // TODO Auto-generated method stub if (twoTree.get(groupPosition)==null) {// isEmpty没有 Toast.makeText(context, "你点击了~" + groupPosition + "~项", Toast.LENGTH_SHORT).show(); return true; } else { return false; } } }); } //向第一层树形中添加一个元素 public void add(int groupPosition,T1 t) { if (oneTree == null) { oneTree= new ArrayList<>(); } oneTree.add(groupPosition,t); twoTree.add(groupPosition,null); notifyDataSetChanged(); } //向第二层树形中添加一个元素 public void addItem(int groupPosition, T2 t) { if (twoTree.get(groupPosition) == null) { Toast.makeText(context, "你点击了~" + groupPosition + "~项", Toast.LENGTH_SHORT).show(); List<T2> list=new ArrayList<>(); list.add(t); twoTree.set(groupPosition,list); }else{ twoTree.get(groupPosition).add(t); } notifyDataSetChanged(); } //向第一层树形中特定位置移除一个元素 public void remove(int position) { if (oneTree != null) { oneTree.remove(position); } notifyDataSetChanged(); } //向第二层树形中特定位置移除一个元素 public void remove(int groupPosition,int childPosition) { if (twoTree.get(groupPosition).get(childPosition)!=null) { twoTree.get(groupPosition).remove(childPosition); } notifyDataSetChanged(); } //组数量 @Override public int getGroupCount() { return oneTree.size(); } //子View数量 @Override public int getChildrenCount(int groupPosition) { return twoTree.get(groupPosition).size(); } //获取组对象 @Override public Object getGroup(int groupPosition) { return oneTree.get(groupPosition); } //获取子View对象 @Override public Object getChild(int groupPosition, int childPosition) { return twoTree.get(groupPosition).get(childPosition); } // 组View下标 @Override public long getGroupId(int groupPosition) { return groupPosition; } //子View下标 @Override public long getChildId(int groupPosition, int childPosition) { return childPosition; } @Override public boolean hasStableIds() { return false; } //取得用于显示给定分组的视图. 这个方法仅返回分组的视图对象 @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { convertView= layoutInflater.inflate(RoneTree, null); return tControl.getGroupView(groupPosition,convertView); } //取得显示给定分组给定子位置的数据用的视图 @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { convertView= layoutInflater.inflate(RtwoTree, null); return tControl.getChildView(groupPosition,childPosition,convertView); } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } }
实现类:
package com.example.appview; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.ExpandableListView; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import com.example.appview.Common.TwoTree.LayerAdapterHelper; import com.example.appview.Common.TwoTree.LayerAdapterInterface; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Activity.Preject_ItemA_AddCaiJi; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Activity.Preject_ItemA_AlterJZ; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Activity.Preject_Item_AddJL; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Model.JiLouModel; import com.example.appview.mian_page.Frament.Preject_Tance_Frament.ItemA_Model.SheiBeiModel; import java.util.ArrayList; import java.util.Date; import java.util.List; public class Demo extends AppCompatActivity { private ExpandableListView expandableListView; private List<JiLouModel> jiLou=new ArrayList<>(); private List<SheiBeiModel> sheiBei; private List<List<SheiBeiModel>> sheiBeiModels=new ArrayList<>(); private LayerAdapterHelper<JiLouModel,SheiBeiModel,myControl> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_demo); expandableListView = findViewById(R.id.expandable_listView); initdata(); adapter=new LayerAdapterHelper<>(Demo.this,jiLou,sheiBeiModels,new myControl(),R.layout.preject_item_addcaiji_onetree,R.layout.preject_item_addcaiji_twotree); expandableListView .setAdapter(adapter); //保证每次只展开一组 adapter.OnlyOne(expandableListView); // 这里是控制如果列表没有孩子菜单不展开的效果 adapter.IsChildenCount(expandableListView); } //创造数据 public void initdata(){ jiLou.add(new JiLouModel(1,"机楼1","",new Date(System.currentTimeMillis()))); jiLou.add(new JiLouModel(1,"机楼2","",new Date(System.currentTimeMillis()))); jiLou.add(new JiLouModel(1,"机楼3","",new Date(System.currentTimeMillis()))); sheiBei=new ArrayList<>(); sheiBei.add(new SheiBeiModel(1,"设备1","")); sheiBei.add(new SheiBeiModel(1,"设备2","")); sheiBei.add(new SheiBeiModel(1,"设备3","")); sheiBeiModels.add(sheiBei); sheiBeiModels.add(null);//这个是如果父节点没有子节点的情况下,自己添加一个null内容 sheiBei=new ArrayList<>(); sheiBei.add(new SheiBeiModel(1,"设备4","")); sheiBei.add(new SheiBeiModel(1,"设备5","")); sheiBei.add(new SheiBeiModel(1,"设备6","")); sheiBeiModels.add(sheiBei); } class myControl implements LayerAdapterInterface{ @Override public View getGroupView(int groupPosition, View convertView) { TextView textView = convertView.findViewById(R.id.preject_item_caijiqi_onetree); textView.setText(adapter.oneTree.get(groupPosition).getJiLouName()); LinearLayout linearLayout=convertView.findViewById(R.id.preject_item_imagecaiji_onetree); linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getOne(linearLayout,groupPosition); } }); return convertView; } @Override public View getChildView(int groupPosition, int childPosition, View convertView) { convertView.setPadding(50,5,0,5); TextView textView = convertView.findViewById(R.id.preject_item_dianbiao); textView.setText(adapter.twoTree.get(groupPosition).get(childPosition).getSheBeiName()); LinearLayout linearLayout=convertView.findViewById(R.id.preject_item_layoutcaozuo_twotree); linearLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getTwo(linearLayout,groupPosition,childPosition); } }); return convertView; } } private void getOne(LinearLayout linearLayout, int position){ View popupView = View.inflate(Demo.this, R.layout.preject_item_pop_alter, null); Button btn1=popupView.findViewById(R.id.preject_item_alter_btn1); Button btn2=popupView.findViewById(R.id.preject_item_alter_btn2); btn1.setText("添加机楼"); btn2.setText("删除"); GradientDrawable drawable1 =(GradientDrawable)btn1.getBackground(); drawable1.setColor(getResources().getColor(R.color.preject4)); GradientDrawable drawable2 =(GradientDrawable)btn2.getBackground(); drawable2.setColor(getResources().getColor(R.color.preject3)); PopupWindow popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); popupWindow.setAnimationStyle(R.anim.move_pop_left_in); popupWindow.setBackgroundDrawable(new BitmapDrawable()); int popupWidth = popupView.getMeasuredWidth(); int popupHeight = popupView.getMeasuredHeight(); int[] location = new int[2]; linearLayout.getLocationOnScreen(location); popupWindow.showAtLocation(linearLayout, Gravity.NO_GRAVITY, location[0], location[1]); btn1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupWindow.dismiss(); // adapter.add(0,new JiLouModel(1,"机楼1","",new Date(System.currentTimeMillis()))); // adapter.addItem(position,new SheiBeiModel(1,"设备4","")); } }); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupWindow.dismiss(); } }); } private void getTwo(LinearLayout linearLayout, int position,int childenPosition){ View popupView = View.inflate(Demo.this, R.layout.preject_item_pop_alter, null); Button btn1=popupView.findViewById(R.id.preject_item_alter_btn1); Button btn2=popupView.findViewById(R.id.preject_item_alter_btn2); btn1.setText("添加机楼"); btn2.setText("删除"); btn1.setVisibility(btn1.GONE); GradientDrawable drawable1 =(GradientDrawable)btn1.getBackground(); drawable1.setColor(getResources().getColor(R.color.preject4)); GradientDrawable drawable2 =(GradientDrawable)btn2.getBackground(); drawable2.setColor(getResources().getColor(R.color.preject3)); PopupWindow popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); popupWindow.setAnimationStyle(R.anim.move_pop_left_in); popupWindow.setBackgroundDrawable(new BitmapDrawable()); int popupWidth = popupView.getMeasuredWidth(); int popupHeight = popupView.getMeasuredHeight(); int[] location = new int[2]; linearLayout.getLocationOnScreen(location); popupWindow.showAtLocation(linearLayout, Gravity.NO_GRAVITY, location[0], location[1]); btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupWindow.dismiss(); } }); } }
布局页面就不再放在去了,和上一篇一样。
最后看一下效果图: