Android 多级菜单联动操作

今天是分享一个android实现三级菜单联动效果,到了第三级菜单有点复杂,下面带着大家看下代码。

项目结构:
这里写图片描述

为了让大家更有的耐心的阅读, 我先从简单的开始说起,我们先看下demo实现的效果吧!这样可以让大家更好的理解后面的思路。

这里写图片描述

我们来看下整体的布局,主页面无非就只有两个TextView控件,可点击。我把代码贴出来,xml如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview1"
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:text="Activity Demo"
        android:textColor="@color/black"
        android:layout_margin="20dp"/>

    <TextView
        android:id="@+id/textview2"
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:textColor="@color/black"
        android:text="Dialog Demo"
        android:layout_margin="20dp"/>

</LinearLayout>

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

然后从Activity Demo进去,我们可以看到先是出来半边的menu列表,效果如下:

这里写图片描述

这个布局大家都知道,就是一个简单的ListView,以下是code:

<?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:background="@color/menudialog_divider_color"
    android:orientation="vertical">

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/white"
        android:cacheColorHint="@android:color/transparent"
        android:divider="@null"
        android:scrollbars="none" />
</LinearLayout>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

那么第二个menu列表是什么出来的呢?布局是一样的,这里三个列表菜单的ListView,我都用同一个xml实现,这并不矛盾,都是ListView列表。这里两个ListView都在同一个屏幕,其实道理很简单,一个ListView占整个屏幕的1/2。第二listView自然可以在同一个屏幕上显示,是不是顿时明白了?哈哈。。。

好,接下来我我们看一下ListView的item布局,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu_item_ly"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="43dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/menu_item_textview"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="title"
        android:textColor="#000000"
        android:textSize="17sp"/>

    <TextView
        android:id="@+id/menu_item_divider"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textColor="@color/black"
        android:background="@color/menudialog_divider_color"/>


</LinearLayout>
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

也很简单,两个TextView控件,第一个是我们要显示的title文本,第二个是title下方的线,以上效果图不太清楚,我这边把颜色加深点,方便大家理解查看。
这里写图片描述

左右滑动是ViewPager,讲到这里,大致就知道这个结构了,没错,就是在ViewPager里面放入三个ListView,实现三个列表可以左右滑动,我也把这份布局贴出来吧!请看以下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <com.lai.threemenudemo.view.MyViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"/>

</LinearLayout>

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这个ViewPager是自定义的,里面很简单,如下:

package com.lai.threemenudemo.view;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;

/**
 * Created by LaiYingtang on 2016/5/22.
 * 主页面左右滑动
 */
public class MyViewPager extends ViewPager{
    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewPager(Context context) {
        super(context);
    }
    //判断menu在x,y的位置
    public void scrollTo(int x,int y){
        if(getAdapter()==null||x>getWidth()*(getAdapter().getCount()-2)){
            return;
        }
        super.scrollTo(x,y);
    }

}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

以下说重点,我们在第一个ListView中点击某一个item,出来第二个ListView列表,我们是怎么做到的呢?思路跟我们的数据库一样,每个菜单的联动必须要关联另个菜单,这样触动一个item的时候,跟它所关联的item便随之出现,我把这些数据写在一个txt文本里面,我们要读取的时候,直接将这些数据封装到SparseArray集合里面遍历出来即可。这里用到的SparseArray是为了节省内存,提高性能。

我们看下数据是怎么关联起来的,我就不全部贴出来了,贴两个item的数据,后面以此类推。

310000,IT/互联网/软件/通信,0;
310100,产品,310000;
310101,产品专员/产品助理,310100;
310102,产品经理/高级产品经理,310100;
310103,产品总监/副总监,310100;
310104,产品VP/首席产品官,310100;
310105,其他产品类职位,310100;
310200,设计,310000;
310201,网页设计/网站美工,310200;
310202,APP设计,310200;
310203,UI/UE/交互设计,310200;
310204,Flash/多媒体设计,310200;
310205,游戏设计,310200;
310206,设计经理/主美,310200;
310207,设计总监/副总监,310200;
310208,其他设计类职位,310200;
    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

我们来看下这些数据到底如何理解,学过mysql的很容易理解,使用id关联数据表的每一个对应的字段,这个也一样,我贴张图讲述就明白了。
这里写图片描述

看红色框部门,点击左栏产品子菜单,包含了右栏多个item的效果,我们来看下这组数据:

这里写图片描述

我们可以理解为,在多条数据中,一条数据有三个字段,第一条的titleName为“产品”,用它的id关联了以下多个titleName,得出了产品包含多个item的结果。下面的设计选项也是一样,不妨去试着理解,看如下:

这里写图片描述这里写图片描述

是不是?。。。。。
前面一级菜单到二级菜单也是如此,我们看看效果图:
数据图
效果图

后面以此类推。结构就这么简单,但是代码有点小复杂。我们一起看看:

这里我贴出dialog这部分的代码,这部分写了注解:
package com.lai.threemenudemo.dialog;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.lai.threemenudemo.R;
import com.lai.threemenudemo.adapter.MenuDialogAdapter;
import com.lai.threemenudemo.adapter.MyPagerAdapter;
import com.lai.threemenudemo.bean.MenuData;
import com.lai.threemenudemo.utils.MenuDataManager;
import com.lai.threemenudemo.view.MyViewPager;

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

/**
 * 三级菜单列表
 * Created by LaiYingtang on 2016/5/25.
 */
public class ThreeMenuDialog extends SecondMenuDialog{

    private  int mWidth;    //宽度
    private MyViewPager mViewPager; //滑动viewPager
    private LinearLayout mRootView;    //需要显示的layout
    private View view1,view2,view3;    //三个菜单级view
    private ListView mListView1,mListView2,mListView3;  //每个菜单列表都是一个listView
    private MenuDialogAdapter mListView1Adapter, mListView2Adapter, mListView3Adapter; //列表显示数据必须要的adapter
    private List<View> views = new ArrayList<View>(); //数据集合
    public MenuDataManager mDictDataManager = MenuDataManager.getInstance(); //全部数据
    private MenuItemClickListener menuItemClickListener;   //接口,点击监听

    public ThreeMenuDialog(Context context) {
        super(context);
        mWidth = mContext.getResources().getDisplayMetrics().widthPixels;//获取屏幕参数
        mContentView = LayoutInflater.from(context).inflate(R.layout.three_menu_dialog,null);
        //初始化控件及对控件操作
        initViews();
        setTitle("三级列表");//设置title
    }

    private void initViews() {
        mRootView = (LinearLayout) findViewById(R.id.rootview);
        mViewPager = (MyViewPager) findViewById(R.id.viewpager);
        mViewPager.setOffscreenPageLimit(2);//显示2页

        //为view加载layout,由于三个级的菜单都是只有一个listView,这里就只xie一个了
        LayoutInflater inflater = LayoutInflater.from(mContext);
        view1 = inflater.inflate(R.layout.pager_number, null);
        view2 = inflater.inflate(R.layout.pager_number, null);
        view3 = inflater.inflate(R.layout.pager_number, null);

        //获取id
        mListView1 = (ListView) view1.findViewById(R.id.listview);
        mListView2 = (ListView) view2.findViewById(R.id.listview);
        mListView3 = (ListView) view3.findViewById(R.id.listview);

        //获取列表数据了
        List<MenuData> list=mDictDataManager.getTripleColumnData(mContext, 0);
        //关联adapter
        mListView1Adapter = new MenuDialogAdapter(mContext, list);
        mListView1Adapter.setSelectedBackgroundResource(R.drawable.select_white);//选中时的背景
        mListView1Adapter.setHasDivider(false);
        mListView1Adapter.setNormalBackgroundResource(R.color.menudialog_bg_gray);//未选中
        mListView1.setAdapter(mListView1Adapter);


        views.add(view1);
        views.add(view2);//当前是第三级菜单,所以前面已经存在第一,第二菜单了

        //关联
        mViewPager.setAdapter(new MyPagerAdapter(views));
        //触屏监听
        mRootView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mViewPager.dispatchTouchEvent(event);
            }
        });

        //view1的listView的点击事件
        //点击事件
        mListView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mListView1Adapter != null)
                    mListView1Adapter.setSelectedPos(position);
                if (mListView2Adapter != null)
                    mListView2Adapter.setSelectedPos(-1);

                if (views.contains(view3)) {
                    views.remove(view3);
                    mViewPager.getAdapter().notifyDataSetChanged();//立即更新adapter数据
                }
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);//得到第position个menu子菜单
                if (menuData.id == 0) {//不限
                    if (mListView2Adapter != null) {
                        mListView2Adapter.setData(new ArrayList<MenuData>());
                        mListView2Adapter.notifyDataSetChanged();//刷新
                    }
                    setDictItemClickListener(menuData);
                } else {
                    List<MenuData> list2 = mDictDataManager.getTripleColumnData(mContext, menuData.id);
                    if (mListView2Adapter == null) {
                        mListView2Adapter = new MenuDialogAdapter(mContext, list2);
                        mListView2Adapter.setNormalBackgroundResource(R.color.white);
                        mListView2.setAdapter(mListView2Adapter);
                    } else {
                        mListView2Adapter.setData(list2);
                        mListView2Adapter.notifyDataSetChanged();
                    }

                }
            }
        });


        //view2的listView点击
        mListView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mListView2Adapter != null) {
                    mListView2Adapter.setSelectedPos(position);
                    mListView2Adapter.setSelectedBackgroundResource(R.drawable.select_gray);
                }

                if (views.contains(view3)) {
                    views.remove(view3);
                }

                //从第二级菜单的基础上加载第三级菜单
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);
                List<MenuData> list3 = mDictDataManager.getTripleColumnData(mContext, menuData.id);
                if (mListView3Adapter == null) {
                    mListView3Adapter = new MenuDialogAdapter(mContext, list3);
                    mListView3Adapter.setHasDivider(false);
                    mListView3Adapter.setNormalBackgroundResource(R.color.menudialog_bg_gray);
                    mListView3.setAdapter(mListView3Adapter);
                } else {
                    mListView3Adapter.setData(list3);
                    mListView3Adapter.notifyDataSetChanged();
                }

                //放入第三级菜单列表
                views.add(view3);
                mViewPager.getAdapter().notifyDataSetChanged();

                if (mViewPager.getCurrentItem() != 1) {
                    mViewPager.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mViewPager.setCurrentItem(1);//选一个
                        }
                    }, 300);
                }
            }
        });

        //最后就是第三级菜单的点击了
        mListView3.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);
                setDictItemClickListener(menuData);//选中点击的子菜单,去设置titleName
            }
        });

    }

    private void setDictItemClickListener(MenuData menuData) {
        if (menuItemClickListener != null) {
            menuItemClickListener.onMenuItemClick(menuData);
        }
        dismiss();
    }

    public final void setonItemClickListener(MenuItemClickListener listener) {
        menuItemClickListener = listener;
    }

    public interface MenuItemClickListener {
        public void onMenuItemClick(MenuData menuData);
    }
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190

然后dialog的动画效果,我也贴出来:

package com.lai.threemenudemo.dialog;

import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.lai.threemenudemo.R;

/**
 * 菜单动画
 * Created by LaiYingtang on 2016/5/25.
 */
public class SecondMenuDialog extends Dialog{
    public Context mContext;
    public LinearLayout containerViewGroup;
    public View mContentView;
    public TextView titleView;
    Window window = null;

    //构造器
    public SecondMenuDialog(Context context) {
        super(context, R.style.dialog_change_card);//样式
        mContext = context;
        containerViewGroup = (LinearLayout) getLayoutInflater().inflate(R.layout.second_menu_dialog, null);
        titleView = (TextView) containerViewGroup.findViewById(R.id.dictdialog_title_tv);
    }
    public View findViewById(int id) {
        return mContentView.findViewById(id);
    }

    /**
     * 设置窗口显示
     */
    public void windowDeploy() {
        window = getWindow(); // 得到对话框
        window.setWindowAnimations(R.style.RegDialogAnimation); // 设置窗口弹出动画效果
        WindowManager.LayoutParams windowAttributes = window.getAttributes();
        windowAttributes.x = 0; // x小于0左移,大于0右移
        windowAttributes.y = 0; // y小于0上移,大于0下移
        windowAttributes.height = 2 * mContext.getResources().getDisplayMetrics().heightPixels / 3;
        windowAttributes.width = LinearLayout.LayoutParams.FILL_PARENT;
        windowAttributes.alpha = 0.6f; //设置透明度
        windowAttributes.gravity = Gravity.BOTTOM; // 设置重力,对齐方式
        window.setAttributes(windowAttributes);
    }
    //显示到layout里面
    @Override
    public void show() {
        if (mContentView != null) {
            containerViewGroup.addView(mContentView);
        }
        setContentView(containerViewGroup);
        setCanceledOnTouchOutside(true);
        windowDeploy();
        super.show();
    }
    //选中的title设置为title
    @Override
    public void setTitle(CharSequence title) {
        if (titleView != null)
            titleView.setText(title);
    }
}

    
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

有一些注释提示大家去理解,我在这里也不能全部讲的那么详细,重要的是,还是要靠大家自己去理解,去参悟,这样才能真正学到东西。好了,大家自己慢慢去消化吧!最后我还是会把源码链接给共享出来,希望大家看了后对你们有所帮助,谢谢!

最后我附上demo的链接:
源码下载

今天是分享一个android实现三级菜单联动效果,到了第三级菜单有点复杂,下面带着大家看下代码。

项目结构:
这里写图片描述

为了让大家更有的耐心的阅读, 我先从简单的开始说起,我们先看下demo实现的效果吧!这样可以让大家更好的理解后面的思路。

这里写图片描述

我们来看下整体的布局,主页面无非就只有两个TextView控件,可点击。我把代码贴出来,xml如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview1"
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:text="Activity Demo"
        android:textColor="@color/black"
        android:layout_margin="20dp"/>

    <TextView
        android:id="@+id/textview2"
        android:layout_width="fill_parent"
        android:layout_height="30dp"
        android:textColor="@color/black"
        android:text="Dialog Demo"
        android:layout_margin="20dp"/>

</LinearLayout>

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

然后从Activity Demo进去,我们可以看到先是出来半边的menu列表,效果如下:

这里写图片描述

这个布局大家都知道,就是一个简单的ListView,以下是code:

<?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:background="@color/menudialog_divider_color"
    android:orientation="vertical">

    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/white"
        android:cacheColorHint="@android:color/transparent"
        android:divider="@null"
        android:scrollbars="none" />
</LinearLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

那么第二个menu列表是什么出来的呢?布局是一样的,这里三个列表菜单的ListView,我都用同一个xml实现,这并不矛盾,都是ListView列表。这里两个ListView都在同一个屏幕,其实道理很简单,一个ListView占整个屏幕的1/2。第二listView自然可以在同一个屏幕上显示,是不是顿时明白了?哈哈。。。

好,接下来我我们看一下ListView的item布局,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu_item_ly"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="43dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/menu_item_textview"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="title"
        android:textColor="#000000"
        android:textSize="17sp"/>

    <TextView
        android:id="@+id/menu_item_divider"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:textColor="@color/black"
        android:background="@color/menudialog_divider_color"/>


</LinearLayout>
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

也很简单,两个TextView控件,第一个是我们要显示的title文本,第二个是title下方的线,以上效果图不太清楚,我这边把颜色加深点,方便大家理解查看。
这里写图片描述

左右滑动是ViewPager,讲到这里,大致就知道这个结构了,没错,就是在ViewPager里面放入三个ListView,实现三个列表可以左右滑动,我也把这份布局贴出来吧!请看以下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <com.lai.threemenudemo.view.MyViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"/>

</LinearLayout>

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

这个ViewPager是自定义的,里面很简单,如下:

package com.lai.threemenudemo.view;

import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;

/**
 * Created by LaiYingtang on 2016/5/22.
 * 主页面左右滑动
 */
public class MyViewPager extends ViewPager{
    public MyViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewPager(Context context) {
        super(context);
    }
    //判断menu在x,y的位置
    public void scrollTo(int x,int y){
        if(getAdapter()==null||x>getWidth()*(getAdapter().getCount()-2)){
            return;
        }
        super.scrollTo(x,y);
    }

}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

以下说重点,我们在第一个ListView中点击某一个item,出来第二个ListView列表,我们是怎么做到的呢?思路跟我们的数据库一样,每个菜单的联动必须要关联另个菜单,这样触动一个item的时候,跟它所关联的item便随之出现,我把这些数据写在一个txt文本里面,我们要读取的时候,直接将这些数据封装到SparseArray集合里面遍历出来即可。这里用到的SparseArray是为了节省内存,提高性能。

我们看下数据是怎么关联起来的,我就不全部贴出来了,贴两个item的数据,后面以此类推。

310000,IT/互联网/软件/通信,0;
310100,产品,310000;
310101,产品专员/产品助理,310100;
310102,产品经理/高级产品经理,310100;
310103,产品总监/副总监,310100;
310104,产品VP/首席产品官,310100;
310105,其他产品类职位,310100;
310200,设计,310000;
310201,网页设计/网站美工,310200;
310202,APP设计,310200;
310203,UI/UE/交互设计,310200;
310204,Flash/多媒体设计,310200;
310205,游戏设计,310200;
310206,设计经理/主美,310200;
310207,设计总监/副总监,310200;
310208,其他设计类职位,310200;
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

我们来看下这些数据到底如何理解,学过mysql的很容易理解,使用id关联数据表的每一个对应的字段,这个也一样,我贴张图讲述就明白了。
这里写图片描述

看红色框部门,点击左栏产品子菜单,包含了右栏多个item的效果,我们来看下这组数据:

这里写图片描述

我们可以理解为,在多条数据中,一条数据有三个字段,第一条的titleName为“产品”,用它的id关联了以下多个titleName,得出了产品包含多个item的结果。下面的设计选项也是一样,不妨去试着理解,看如下:

这里写图片描述这里写图片描述

是不是?。。。。。
前面一级菜单到二级菜单也是如此,我们看看效果图:
数据图
效果图

后面以此类推。结构就这么简单,但是代码有点小复杂。我们一起看看:

这里我贴出dialog这部分的代码,这部分写了注解:
package com.lai.threemenudemo.dialog;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.ListView;

import com.lai.threemenudemo.R;
import com.lai.threemenudemo.adapter.MenuDialogAdapter;
import com.lai.threemenudemo.adapter.MyPagerAdapter;
import com.lai.threemenudemo.bean.MenuData;
import com.lai.threemenudemo.utils.MenuDataManager;
import com.lai.threemenudemo.view.MyViewPager;

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

/**
 * 三级菜单列表
 * Created by LaiYingtang on 2016/5/25.
 */
public class ThreeMenuDialog extends SecondMenuDialog{

    private  int mWidth;    //宽度
    private MyViewPager mViewPager; //滑动viewPager
    private LinearLayout mRootView;    //需要显示的layout
    private View view1,view2,view3;    //三个菜单级view
    private ListView mListView1,mListView2,mListView3;  //每个菜单列表都是一个listView
    private MenuDialogAdapter mListView1Adapter, mListView2Adapter, mListView3Adapter; //列表显示数据必须要的adapter
    private List<View> views = new ArrayList<View>(); //数据集合
    public MenuDataManager mDictDataManager = MenuDataManager.getInstance(); //全部数据
    private MenuItemClickListener menuItemClickListener;   //接口,点击监听

    public ThreeMenuDialog(Context context) {
        super(context);
        mWidth = mContext.getResources().getDisplayMetrics().widthPixels;//获取屏幕参数
        mContentView = LayoutInflater.from(context).inflate(R.layout.three_menu_dialog,null);
        //初始化控件及对控件操作
        initViews();
        setTitle("三级列表");//设置title
    }

    private void initViews() {
        mRootView = (LinearLayout) findViewById(R.id.rootview);
        mViewPager = (MyViewPager) findViewById(R.id.viewpager);
        mViewPager.setOffscreenPageLimit(2);//显示2页

        //为view加载layout,由于三个级的菜单都是只有一个listView,这里就只xie一个了
        LayoutInflater inflater = LayoutInflater.from(mContext);
        view1 = inflater.inflate(R.layout.pager_number, null);
        view2 = inflater.inflate(R.layout.pager_number, null);
        view3 = inflater.inflate(R.layout.pager_number, null);

        //获取id
        mListView1 = (ListView) view1.findViewById(R.id.listview);
        mListView2 = (ListView) view2.findViewById(R.id.listview);
        mListView3 = (ListView) view3.findViewById(R.id.listview);

        //获取列表数据了
        List<MenuData> list=mDictDataManager.getTripleColumnData(mContext, 0);
        //关联adapter
        mListView1Adapter = new MenuDialogAdapter(mContext, list);
        mListView1Adapter.setSelectedBackgroundResource(R.drawable.select_white);//选中时的背景
        mListView1Adapter.setHasDivider(false);
        mListView1Adapter.setNormalBackgroundResource(R.color.menudialog_bg_gray);//未选中
        mListView1.setAdapter(mListView1Adapter);


        views.add(view1);
        views.add(view2);//当前是第三级菜单,所以前面已经存在第一,第二菜单了

        //关联
        mViewPager.setAdapter(new MyPagerAdapter(views));
        //触屏监听
        mRootView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return mViewPager.dispatchTouchEvent(event);
            }
        });

        //view1的listView的点击事件
        //点击事件
        mListView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mListView1Adapter != null)
                    mListView1Adapter.setSelectedPos(position);
                if (mListView2Adapter != null)
                    mListView2Adapter.setSelectedPos(-1);

                if (views.contains(view3)) {
                    views.remove(view3);
                    mViewPager.getAdapter().notifyDataSetChanged();//立即更新adapter数据
                }
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);//得到第position个menu子菜单
                if (menuData.id == 0) {//不限
                    if (mListView2Adapter != null) {
                        mListView2Adapter.setData(new ArrayList<MenuData>());
                        mListView2Adapter.notifyDataSetChanged();//刷新
                    }
                    setDictItemClickListener(menuData);
                } else {
                    List<MenuData> list2 = mDictDataManager.getTripleColumnData(mContext, menuData.id);
                    if (mListView2Adapter == null) {
                        mListView2Adapter = new MenuDialogAdapter(mContext, list2);
                        mListView2Adapter.setNormalBackgroundResource(R.color.white);
                        mListView2.setAdapter(mListView2Adapter);
                    } else {
                        mListView2Adapter.setData(list2);
                        mListView2Adapter.notifyDataSetChanged();
                    }

                }
            }
        });


        //view2的listView点击
        mListView2.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                if (mListView2Adapter != null) {
                    mListView2Adapter.setSelectedPos(position);
                    mListView2Adapter.setSelectedBackgroundResource(R.drawable.select_gray);
                }

                if (views.contains(view3)) {
                    views.remove(view3);
                }

                //从第二级菜单的基础上加载第三级菜单
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);
                List<MenuData> list3 = mDictDataManager.getTripleColumnData(mContext, menuData.id);
                if (mListView3Adapter == null) {
                    mListView3Adapter = new MenuDialogAdapter(mContext, list3);
                    mListView3Adapter.setHasDivider(false);
                    mListView3Adapter.setNormalBackgroundResource(R.color.menudialog_bg_gray);
                    mListView3.setAdapter(mListView3Adapter);
                } else {
                    mListView3Adapter.setData(list3);
                    mListView3Adapter.notifyDataSetChanged();
                }

                //放入第三级菜单列表
                views.add(view3);
                mViewPager.getAdapter().notifyDataSetChanged();

                if (mViewPager.getCurrentItem() != 1) {
                    mViewPager.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mViewPager.setCurrentItem(1);//选一个
                        }
                    }, 300);
                }
            }
        });

        //最后就是第三级菜单的点击了
        mListView3.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                MenuData menuData = (MenuData) parent.getItemAtPosition(position);
                setDictItemClickListener(menuData);//选中点击的子菜单,去设置titleName
            }
        });

    }

    private void setDictItemClickListener(MenuData menuData) {
        if (menuItemClickListener != null) {
            menuItemClickListener.onMenuItemClick(menuData);
        }
        dismiss();
    }

    public final void setonItemClickListener(MenuItemClickListener listener) {
        menuItemClickListener = listener;
    }

    public interface MenuItemClickListener {
        public void onMenuItemClick(MenuData menuData);
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190

然后dialog的动画效果,我也贴出来:

package com.lai.threemenudemo.dialog;

import android.app.Dialog;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.lai.threemenudemo.R;

/**
 * 菜单动画
 * Created by LaiYingtang on 2016/5/25.
 */
public class SecondMenuDialog extends Dialog{
    public Context mContext;
    public LinearLayout containerViewGroup;
    public View mContentView;
    public TextView titleView;
    Window window = null;

    //构造器
    public SecondMenuDialog(Context context) {
        super(context, R.style.dialog_change_card);//样式
        mContext = context;
        containerViewGroup = (LinearLayout) getLayoutInflater().inflate(R.layout.second_menu_dialog, null);
        titleView = (TextView) containerViewGroup.findViewById(R.id.dictdialog_title_tv);
    }
    public View findViewById(int id) {
        return mContentView.findViewById(id);
    }

    /**
     * 设置窗口显示
     */
    public void windowDeploy() {
        window = getWindow(); // 得到对话框
        window.setWindowAnimations(R.style.RegDialogAnimation); // 设置窗口弹出动画效果
        WindowManager.LayoutParams windowAttributes = window.getAttributes();
        windowAttributes.x = 0; // x小于0左移,大于0右移
        windowAttributes.y = 0; // y小于0上移,大于0下移
        windowAttributes.height = 2 * mContext.getResources().getDisplayMetrics().heightPixels / 3;
        windowAttributes.width = LinearLayout.LayoutParams.FILL_PARENT;
        windowAttributes.alpha = 0.6f; //设置透明度
        windowAttributes.gravity = Gravity.BOTTOM; // 设置重力,对齐方式
        window.setAttributes(windowAttributes);
    }
    //显示到layout里面
    @Override
    public void show() {
        if (mContentView != null) {
            containerViewGroup.addView(mContentView);
        }
        setContentView(containerViewGroup);
        setCanceledOnTouchOutside(true);
        windowDeploy();
        super.show();
    }
    //选中的title设置为title
    @Override
    public void setTitle(CharSequence title) {
        if (titleView != null)
            titleView.setText(title);
    }
}

  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

有一些注释提示大家去理解,我在这里也不能全部讲的那么详细,重要的是,还是要靠大家自己去理解,去参悟,这样才能真正学到东西。好了,大家自己慢慢去消化吧!最后我还是会把源码链接给共享出来,希望大家看了后对你们有所帮助,谢谢!

最后我附上demo的链接:
源码下载

猜你喜欢

转载自blog.csdn.net/hzy670800844/article/details/62037033