自定义多级滑动菜单控件

384 阅读8分钟

效果图

代码

  • 自定义控件类SlideMenu

这里使用属性动画的方式实现滑动效果

package cn.llj.menu.demo;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by llj on 2019/3/28.
 * 通用分级滑动菜单
 */
public class SlideMenu extends RelativeLayout
{
    private static final int MAIN_WIDTH_DPI = 150;//dp 左边栏宽度
    private static final int DURATION = 200;//ms 滑动时间
    private static final String TV_SELECTED_COLOR = "#00d26E";//tv selected color
    private static final String TV_NORMAL_COLOR = "#525866";//tv normal color
    private static final String ITEM_BG_COLOR = "#F2F6F9";//tv bg color
    private static final String TAG = "SlideMenu";
    
    private int mW;
    private int mMainWidth;//px
    private List<MenuBean> mList = new ArrayList<>();
    private int mCurrentIndex;
    private String mCurrentRootName;
    private MenuBean mCurrentMenu;
    private ISlideMenuListener mListener;
    private boolean mIsOddCount = true;//标记奇数个使用不同背景色
    private String mSelectedColor=TV_SELECTED_COLOR;
    
    public interface ISlideMenuListener
    {
        /**
         * 菜单监听器(动画结束后回调)
         *
         * @param hasPre          是否可返回
         * @param hasNext         是否可前进
         * @param currentRootName 当前所属的根菜单名称
         * @param selectedMenu    当前选中的菜单
         */
        void onAnimFinished(boolean hasPre, boolean hasNext, String currentRootName, MenuBean
                selectedMenu);
    }
    
    /**
     * 设置监听器
     *
     * @param listener
     */
    void setListener(ISlideMenuListener listener)
    {
        mListener = listener;
    }
    
    public SlideMenu(Context context)
    {
        super(context);
        initMainAndSubViews();
    }
    
    public SlideMenu(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        initMainAndSubViews();
    }
    
    public void setSelectedColor(String selectedColor)
    {
        this.mSelectedColor = selectedColor;
    }
    
    /**
     * 销毁菜单
     */
    void destroy()
    {
        mList.clear();
        mCurrentIndex = 0;
        mCurrentMenu = null;
        mCurrentRootName = null;
        mListener = null;
        removeAllViews();
    }
    
    /**
     * 初始化菜单数据,只展示第一级菜单数据
     *
     * @param list
     */
    void initCurrentMenus(List<MenuBean> list)
    {
        if (list == null || list.size() == 0)
        {
            Log.d(TAG, "没有数据");
            return;
        }
        mList.clear();
        mList.addAll(list);
        mCurrentIndex = 0;
        mCurrentRootName = mList.get(mCurrentIndex).getName();
        mCurrentMenu = mList.get(mCurrentIndex);
        MenuAdapter adapter = new MenuAdapter(mList);
      //  adapter.mSelectedPos = 0;
        getChildAt(mCurrentIndex).setAdapter(adapter);
      //  getChildAt(mCurrentIndex + 1).setAdapter(new MenuAdapter(mList.get(0).getSubItems()));
    }
    
    @Override
    public ListView getChildAt(int index)
    {
        if (index < 0 || index >= getChildCount())
        {
            return null;
        }
        else return (ListView) super.getChildAt(index);
    }
    
    private void initMainAndSubViews()
    {
        mW = getResources().getDisplayMetrics().widthPixels;
        mMainWidth = DeviceUtils.dip2px(getContext(), MAIN_WIDTH_DPI);
        //初始化两个子view
        ListView mainView = createView();
        LayoutParams p = (LayoutParams) mainView.getLayoutParams();
        p.width = mMainWidth;
        mainView.setOnItemClickListener(mMainClickItemListener);
        
        ListView subView = createView();
        subView.setOnItemClickListener(mSubClickItemListener);
        p = (LayoutParams) subView.getLayoutParams();
        p.leftMargin = mMainWidth;
        
        addView(mainView);
        addView(subView);
        
    }
    
    private ListView createView()
    {
        LayoutParams p = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup
                .LayoutParams.MATCH_PARENT);
        ListView view = (ListView) View.inflate(getContext(), R.layout.slide_menu_catogery_item,
                null);
        view.setBackgroundColor(mIsOddCount ? Color.parseColor(ITEM_BG_COLOR) : Color.WHITE);
        mIsOddCount = !mIsOddCount;
        view.setLayoutParams(p);
        return view;
    }
    
    //左边菜单项点击监听器
    AdapterView.OnItemClickListener mMainClickItemListener = new AdapterView.OnItemClickListener()
    {
        
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        {
            if (mCurrentIndex == 0)
            {
                mCurrentRootName = mList.get(position).getName();
            }
            processSelected(parent, position);
            List<MenuBean> list = mCurrentMenu.getSubItems();
            if (getChildAt(mCurrentIndex + 1) != null)
                getChildAt(mCurrentIndex + 1).setAdapter(new MenuAdapter(list));
            
            if (mListener != null)
            {
                mListener.onAnimFinished(mCurrentIndex > 0, list.size() > 0, mCurrentRootName,
                        mCurrentMenu);
            }
            
        }
    };
    
    //右边菜单项点击监听器
    AdapterView.OnItemClickListener mSubClickItemListener = new AdapterView.OnItemClickListener()
    {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id)
        {
            processSelected(parent, position);
            List<MenuBean> list = mCurrentMenu.getSubItems();
            if (list.size() > 0)
            {//还有子元素,则移动过去
                if (getChildAt(mCurrentIndex + 2) == null) //复用已有的view
                    addView(createView());
                //刷新该view的数据
                getChildAt(mCurrentIndex + 2).setAdapter(new MenuAdapter(list));
                animateForward(list.size() > 0, mCurrentMenu);
            }
            else
            {
                if (mListener != null)
                {
                    mListener.onAnimFinished(mCurrentIndex > 0, false, mCurrentRootName,
                            mCurrentMenu);
                }
            }
        }
    };
    
    //处理选中项
    private void processSelected(AdapterView<?> parent, int position)
    {
        MenuAdapter adapter = (MenuAdapter) parent.getAdapter();
        adapter.mSelectedPos = position;
        adapter.notifyDataSetChanged();
        mCurrentMenu = adapter.getItem(position);
    }
    
    //处理前进
    private void animateForward(final boolean hasNext, final MenuBean currentSelected)
    {
        setLayoutParams(getChildAt(mCurrentIndex + 1), getChildAt(mCurrentIndex + 2));
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex),
                "translationX", calculateMainViewDistance().first, calculateMainViewDistance().second);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex + 1),
                "translationX", calculateSubViewDistance().first, calculateSubViewDistance().second);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex + 2),
                "translationX", mW, mMainWidth);
        AnimatorSet set = new AnimatorSet();
        set.playTogether(animator1, animator2, animator3);
        set.setDuration(DURATION);
        set.start();
        set.addListener(new AnimatorListenerAdapter()
        {
            @Override
            public void onAnimationEnd(Animator animation)
            {
                //切换监听对象
                getChildAt(mCurrentIndex + 1).setOnItemClickListener(mMainClickItemListener);
                //if (getChildAt(mCurrentIndex + 2) != null)
                getChildAt(mCurrentIndex + 2).setOnItemClickListener(mSubClickItemListener);
                mCurrentIndex++;
                if (mListener != null)
                {
                    mListener.onAnimFinished(true, hasNext, mCurrentRootName, currentSelected);
                }
                
            }
        });
    }
    
    /**
     * 返回
     */
    public void animateBack()
    {
        if (mCurrentIndex == 0)
        {
            Log.v(TAG, "当前在第一级,不能回退了");
            return;
        }
        mCurrentIndex--;
        setLayoutParams(getChildAt(mCurrentIndex), getChildAt(mCurrentIndex + 1));
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex),
                "translationX", calculateMainViewDistance().second, calculateMainViewDistance().first);
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex + 1),
                "translationX", calculateSubViewDistance().second, calculateSubViewDistance().first);
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(getChildAt(mCurrentIndex + 2),
                "translationX", mMainWidth, mW);
        
        AnimatorSet set = new AnimatorSet();
        set.setDuration(DURATION);
        set.playTogether(animator1, animator2, animator3);
        set.start();
        set.addListener(new AnimatorListenerAdapter()
        {
            @Override
            public void onAnimationEnd(Animator animation)
            {
                //切换监听对象
                getChildAt(mCurrentIndex).setOnItemClickListener(mMainClickItemListener);
                getChildAt(mCurrentIndex + 1).setOnItemClickListener(mSubClickItemListener);
                if (mListener != null)
                {
                    mListener.onAnimFinished(mCurrentIndex > 0, true, mCurrentRootName,
                            mCurrentMenu);
                }
            }
            
        });
    }
    
    //右边菜单移到左边后宽度要变化
    private void setLayoutParams(ListView mainView, ListView subView)
    {
        LayoutParams p = (LayoutParams) mainView.getLayoutParams();
        p.width = mMainWidth;
        mainView.setLayoutParams(p);
        p = (LayoutParams) subView.getLayoutParams();
        p.width = mW - mMainWidth;
        subView.setLayoutParams(p);
    }
    
    //计算左边菜单项的动画移动距离
    private Pair<Integer, Integer> calculateMainViewDistance()
    {
        if (mCurrentIndex == 1)
        {
            return new Pair<>(-mMainWidth, -2 * mMainWidth);
        }
        else
        {
            return new Pair<>(0, -mMainWidth);
        }
    }
    
    //计算右边菜单项的动画移动距离
    private Pair<Integer, Integer> calculateSubViewDistance()
    {
        if (mCurrentIndex == 0)
        {
            return new Pair<>(0, -mMainWidth);
        }
        else
        {
            return new Pair<>(mMainWidth, 0);
        }
    }
    
    private class MenuAdapter extends BaseAdapter
    {
        
        private List<MenuBean> mList = new ArrayList<>();
        private int mSelectedPos = -1;
        
        MenuAdapter(@NonNull List<MenuBean> list)
        {
            mList.clear();
            mList.addAll(list);
        }
        
        @Override
        public int getCount()
        {
            return mList.size();
        }
        
        @Override
        public MenuBean getItem(int position)
        {
            return mList.get(position);
        }
        
        @Override
        public long getItemId(int position)
        {
            return 0;
        }
        
        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            Holder holder = new Holder();
            if (convertView == null)
            {
                convertView = View.inflate(parent.getContext(), R.layout.slide_menu_item, null);
                holder.tv = (TextView) convertView;
                convertView.setTag(holder);
            }
            else
            {
                holder = (Holder) convertView.getTag();
            }
            Drawable background = parent.getBackground();//// TODO:  待优化
            ColorDrawable colorDrawable = (ColorDrawable) background;
            int parentColor = colorDrawable.getColor();
            if (position == mSelectedPos)
            {
                holder.tv.setTextColor(Color.parseColor(mSelectedColor));
                if (parentColor == Color.WHITE)
                    holder.tv.setBackgroundColor(Color.parseColor(ITEM_BG_COLOR));
            }
            else
            {
                holder.tv.setTextColor(Color.parseColor(TV_NORMAL_COLOR));
                if (parentColor == Color.WHITE) holder.tv.setBackgroundColor(Color.WHITE);
            }
            holder.tv.setText(mList.get(position).getName());
            return convertView;
        }
    }
    
    private class Holder
    {
        TextView tv;
    }
    
    //动画监听器适配器
    private abstract class AnimatorListenerAdapter implements Animator.AnimatorListener
    {
        @Override
        public void onAnimationStart(Animator animation)
        {
            
        }
        
        @Override
        public void onAnimationEnd(Animator animation)
        {
            
        }
        
        @Override
        public void onAnimationCancel(Animator animation)
        {
            
        }
        
        @Override
        public void onAnimationRepeat(Animator animation)
        {
            
        }
    }
}

  • 菜单实体类 MenuBean.java
package cn.llj.menu.demo;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

/**
 * 滑动菜单项实体类
 * Created by llj on 2019/3/28.
 */
public class MenuBean {

    private String id;
    private String name;
    @SerializedName("sub_items")
    private List<MenuBean> subItems=new ArrayList<>();


    public static List<MenuBean> parse(JsonArray jsonArray){
        List<MenuBean> list=new ArrayList<>();
        Gson gson = new Gson();
        for (JsonElement element:jsonArray){
            MenuBean cse = gson.fromJson( element , MenuBean.class);
            list.add(cse);
        
}
        return list;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSubItems(List<MenuBean> subItems) {
        this.subItems = subItems;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public List<MenuBean> getSubItems() {
        return subItems;
    }
}

  • 菜单布局文件 slide_menu_item.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="#E3E9ED"
    android:dividerHeight="0.5dp"
    android:scrollbars="none"
    tools:showIn="@layout/activity_main" />
  • 菜单项item slide_menu_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:text="业务业务知识业务知识知识"
    android:ellipsize="end"
    android:maxLines="1"
    android:padding="20dp"
    android:textSize="16sp"
    >
</TextView>

  • 调用测试类 MainActivity.java
package cn.llj.menu.demo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.gson.JsonArray;
import com.google.gson.JsonParser;

import java.util.List;

public class MainActivity extends Activity implements View.OnClickListener
{
    private String TAG = "LLJ";
    private SlideMenu mSlideMenu;
    private View mBackView, mConfirmView;
    private String mCurrentName;
    String testData = "[  {\"id\": 1,  \"name\": \"第一级\",   \"sub_items\": [ {  \"id\": 2,  " +
            "\"name\": \"第二级的名称有点惆怅怎么办\", \"sub_items\": [ {   \"id\": 3, \"name\": \"第三极\",   " +
            "\"sub_items\": [ { \"id\": 4,  \"name\": \"第四级\",  \"sub_items\": [ { \"id\": 5, " +
            "\"name\": \"第五级\"} ] } ]} ] } ,{  \"id\": 2,  \"name\": \"第二级2\", \"sub_items\": [ {" +
            "   \"id\": 3, \"name\": \"第三极2\",   \"sub_items\": [ { \"id\": 4,  \"name\": " +
            "\"第四级2\",  \"sub_items\": [ { \"id\": 5, \"name\": \"第五级2\"} ] } ]} ] },{ \"id\": 5," +
            " \"name\": \"这级没有下一级了\"},{ \"id\": 5, \"name\": \"这级没有下一级了\"},{ \"id\": 5, \"name\":" +
            " \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"},{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"}    ] }, {\"id\": 1,  \"name\": \"第1级的地方地方斯蒂芬\",   \"sub_items\": [ {  " +
            "\"id\": 2,  \"name\": \"第二级\", \"sub_items\": [ {   \"id\": 3, \"name\": \"第三极\",   " +
            "\"sub_items\": [ { \"id\": 4,  \"name\": \"第四级\",  \"sub_items\": [ { \"id\": 5, " +
            "\"name\": \"第五级\"} ] } ]} ] } ,{  \"id\": 2,  \"name\": \"第二级2\", \"sub_items\": [ {" +
            "   \"id\": 3, \"name\": \"第三极2\",   \"sub_items\": [ { \"id\": 4,  \"name\": " +
            "\"第四级2\",  \"sub_items\": [ { \"id\": 5, \"name\": \"第五级2\"} ] } ]} ] },{ \"id\": 5," +
            " \"name\": \"这级没有下一级了\"},{ \"id\": 5, \"name\": \"这级没有下一级了\"},{ \"id\": 5, \"name\":" +
            " \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"},{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"} ,{ \"id\": 5, \"name\": \"这级没有下一级了\"} ,{ \"id\": 5, \"name\": " +
            "\"这级没有下一级了\"}    ] }]";
    
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBackView = findViewById(R.id.back);
        mConfirmView = findViewById(R.id.confirm);
        mSlideMenu = findViewById(R.id.slideMenu);
        JsonParser parser = new JsonParser();
        JsonArray Jarray = parser.parse(testData).getAsJsonArray();
        List<MenuBean> list = MenuBean.parse(Jarray);
        mSlideMenu.initCurrentMenus(list);
        mSlideMenu.setListener(new SlideMenu.ISlideMenuListener()
        {
            @Override
            public void onAnimFinished(boolean hasPre, boolean hasNext, String currentRootName,
                                       MenuBean currentMenu)
            {
                if (hasPre) mBackView.setVisibility(View.VISIBLE);
                else mBackView.setVisibility(View.INVISIBLE);
                mCurrentName = currentMenu.getName();
                Log.d(TAG, "hasNext=" + hasNext + ",rootname=" + currentRootName + "," +
                        "currentMenu=" + currentMenu.getName());
            }
        });
        mBackView.setOnClickListener(this);
        mConfirmView.setOnClickListener(this);
    }
    
    @Override
    public void onClick(View v)
    {
        if (v.getId() == R.id.back)
        {
            mSlideMenu.animateBack();
        }
        else if (v.getId() == R.id.confirm)
        {
            Toast.makeText(this.getApplicationContext(), String.format("选中了:%s", mCurrentName),
                    Toast.LENGTH_SHORT).show();
        }
    }
    
    @Override
    protected void onDestroy()
    {
        mSlideMenu.destroy();
        super.onDestroy();
    }
}

  • MainActivity.java的布局文件 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#205081"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="400dp">

        <LinearLayout
            android:id="@+id/linearLayout2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentStart="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:background="@android:color/white"
            android:orientation="vertical">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">


                <LinearLayout
                    android:id="@+id/back"
                    android:layout_width="66dp"
                    android:layout_height="40dp"
                    android:layout_alignParentStart="true"
                    android:layout_alignParentLeft="true"
                    android:layout_centerVertical="true"
                    android:layout_marginTop="15dp"
                    android:orientation="horizontal"
                    android:visibility="invisible">

                    <ImageView
                        android:id="@+id/imageView6"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_marginLeft="20dp"
                        android:src="@mipmap/ac_back_icon" />
                </LinearLayout>

                <TextView
                    android:id="@+id/textView8"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerHorizontal="true"
                    android:layout_centerVertical="true"
                    android:layout_marginTop="15dp"
                    android:layout_marginBottom="15dp"
                    android:text="知识分类"
                    android:textColor="#ff323232"
                    android:textSize="16sp" />

                <TextView
                    android:id="@+id/confirm"
                    android:layout_width="66dp"
                    android:layout_height="40dp"
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:gravity="center"
                    android:text="确定"
                    android:textColor="#00D26E"
                    android:textSize="14sp" />
            </RelativeLayout>

            <cn.llj.menu.demo.SlideMenu
                android:id="@+id/slideMenu"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </cn.llj.menu.demo.SlideMenu>
        </LinearLayout>
    </RelativeLayout>
</android.support.constraint.ConstraintLayout>
  • gradle依赖

因为我们的实体数据结构是树状结构,android自带的json库和fastjson均不支持这种数据结构的解析,所以我这边使用gson库来解析数据

...
implementation 'com.google.code.gson:gson:2.8.2'
...