關於三級選單的實現方式
阿新 • • 發佈:2019-02-03
近日產品提出一個要一個三級選單列表的功能,網上也一些資源,但是並不能滿足需求。有4種實現思路:
(1)最常見的是兩個expandlistview相互巢狀,親身檢測,比較繁瑣,程式碼也不夠簡潔,而且會有三級慘淡測繪高度失效的情況.
(2)使用一個recycleview,自己來維護資料集合,親測,這種方式兩層的資料格式時,還是可以接受的,但是三層的時候,維護資料的複雜度就不是一個量級,比較複雜。
(3)使用3個recycleview巢狀,資料維持就相對簡單,只要處理recycleview的測繪高度衝突即可,網上有很多,這裡不多說。
(4)這是我實現的方式,自認為這種實現方式是比較簡單且清晰的,兩個控制元件巢狀,expandlistview和recycleview巢狀,童謠要處理好recycleview子類item項的高度測繪問題(這也是我的實現方式)
程式碼如下:
activity中的程式碼------------
public class MainActivity extends AppCompatActivity { private List<BeanData> mBeanDataList = new ArrayList<>(); Context mContext; ExpandableListView mExpandableListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);佈局的話就是一個expandlistview控制元件,就不貼了setContentView(R.layout.activity_main); mContext = this; initData(); mExpandableListView = findViewById(R.id.expandableListView); mExpandableListView.setAdapter(new Myadapter(mContext, mBeanDataList)); } /** * 初始化資料集合 */ private void initData() { for (int i = 0; i < 5; i++) { BeanData beanData = newBeanData(); beanData.setContent("parent" + i); List<BeanData> beanDataList = new ArrayList<>(); for (int j = 0; j < 5; j++) { BeanData beanData1 = new BeanData(); beanData1.setContent("child" + j); List<BeanData> beanDataList1 = new ArrayList<>(); for (int k = 0; k < 5; k++) { BeanData beanData2 = new BeanData(); beanData2.setContent("secondChild" + k); beanData2.setBeanData(new ArrayList<BeanData>()); beanDataList1.add(beanData2); } beanData1.setBeanData(beanDataList1); beanDataList.add(beanData1); } beanData.setBeanData(beanDataList); mBeanDataList.add(beanData); } } }
一個實體類如下:
public class BeanData { private List<BeanData> mBeanData; private String content; public List<BeanData> getBeanData() { return mBeanData; } public void setBeanData(List<BeanData> beanData) { mBeanData = beanData; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }兩個adapter 程式碼如下:
public class Myadapter extends BaseExpandableListAdapter { Context mContext; List<BeanData> list; public Myadapter(Context context, List<BeanData> list) { mContext = context; this.list = list; } @Override public int getGroupCount() { return list.size(); } @Override public int getChildrenCount(int groupPosition) { return list.get(groupPosition).getBeanData().size(); } @Override public Object getGroup(int groupPosition) { return list.get(groupPosition); } @Override public Object getChild(int groupPosition, int childPosition) { return list.get(groupPosition).getBeanData().get(childPosition); } @Override public long getGroupId(int groupPosition) { return groupPosition; } @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) { parentViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.parent_item_layout, parent, false); holder = new parentViewHolder(); holder.parent_tv = convertView.findViewById(R.id.partent); convertView.setTag(holder); } else { holder = (parentViewHolder) convertView.getTag(); } holder.parent_tv.setText(list.get(groupPosition).getContent()); return convertView; } class parentViewHolder { TextView parent_tv; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { final childViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.child_item_layout, parent, false); holder = new childViewHolder(); holder.child_tv = convertView.findViewById(R.id.partent1); holder.child_tv.setTag(false); holder.mAllHeightRecyclerView = convertView.findViewById(R.id.recyclerView); holder.mAllHeightRecyclerView.setLayoutManager(new LinearLayoutManager(parent.getContext())); convertView.setTag(holder); } else { holder = (childViewHolder) convertView.getTag(); } recyclerAdapter recyclerAdapter = new recyclerAdapter(list.get(groupPosition).getBeanData().get(childPosition).getBeanData()); holder.mAllHeightRecyclerView.setAdapter(recyclerAdapter); holder.child_tv.setText(list.get(groupPosition).getBeanData().get(childPosition).getContent()); holder.child_tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { boolean isShow = (boolean) v.getTag(); holder.mAllHeightRecyclerView.setVisibility(!isShow ? View.VISIBLE : View.GONE); v.setTag(!isShow); } }); return convertView; } class childViewHolder { TextView child_tv; AllHeightRecyclerView mAllHeightRecyclerView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return false; } }
public class recyclerAdapter extends RecyclerView.Adapter<recyclerAdapter.RecyViewHolder> { private List<BeanData> mBeanDataList; private OnItemClickListener mOnItemClickListener; /** * Created by joker on 2018/1/10. */ public interface OnItemClickListener { void onClick(int position, ShowData showData); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { mOnItemClickListener = onItemClickListener; } public recyclerAdapter(List<BeanData> beanDataList) { mBeanDataList = beanDataList; } @Override public recyclerAdapter.RecyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { TextView textView = new TextView(parent.getContext()); return new RecyViewHolder(textView); } @Override public void onBindViewHolder(recyclerAdapter.RecyViewHolder holder, int position) { holder.mTextView.setText(mBeanDataList.get(position).getContent()); } @Override public int getItemCount() { return mBeanDataList.size(); } class RecyViewHolder extends RecyclerView.ViewHolder { private TextView mTextView; RecyViewHolder(TextView itemView) { super(itemView); mTextView = itemView; } } }
這裡是一個強行測繪的recycleview:
/** * Created by jp on 2017/9/11. * 重新測量recyclerview高度,強制繪製全部高度 */ public class AllHeightRecyclerView extends RecyclerView { public AllHeightRecyclerView(Context context) { super(context); } public AllHeightRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public AllHeightRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthSpec, int heightSpec) { int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthSpec, expandSpec); } }三個列表佈局中,需要注意的就是二級列表的佈局了,程式碼如下:
<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/partent1" android:layout_width="match_parent" android:layout_height="wrap_content"/> <com.joker.threelevelslist.AllHeightRecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone"/> </LinearLayout>這個樣完美完成三級列表的功能了