1. 程式人生 > >關於三級選單的實現方式

關於三級選單的實現方式

近日產品提出一個要一個三級選單列表的功能,網上也一些資源,但是並不能滿足需求。有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);
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 = new
BeanData(); 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); } } }
佈局的話就是一個expandlistview控制元件,就不貼了

一個實體類如下:

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>
這個樣完美完成三級列表的功能了