感觉好久没有写博客了,这段时间工作很忙,只有晚上才有时间写,demo做出来后马上动手分享给大家了,其实这几天还是很累的,这身体吃不消了【大哭】。。。额!好了,今天是分享一个android实现三级菜单联动效果,这个demo我也折腾了两三个晚上,到了第三级菜单有点复杂,下面带着大家看下代码。

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

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

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

"http://schemas.android.com/apk/res/android"    android:id="@+id/rootview"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    id="@+id/textview1"        android:layout_width="fill_parent"        android:layout_height="30dp"        android:text="Activity Demo"        android:textColor="@color/black"        android:layout_margin="20dp"/>    id="@+id/textview2"        android:layout_width="fill_parent"        android:layout_height="30dp"        android:textColor="@color/black"        android:text="Dialog Demo"        android:layout_margin="20dp"/>

然后从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>

那么第二个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>

也很简单,两个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>

这个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);    }}

以下说重点,我们在第一个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;

我们来看下这些数据到底如何理解,学过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 views = new ArrayList(); //数据集合    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 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());                        mListView2Adapter.notifyDataSetChanged();//刷新                    }                    setDictItemClickListener(menuData);                } else {                    List 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 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);    }}

然后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);    }}

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

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

更多相关文章

  1. 一起Talk Android吧(第二百五十八回:Android中的Toolbar菜单一)
  2. 关于“Android SDK manager中不出现完整Android版本安装包列表”
  3. 从Android开发者的角度看一看IOS和Flutter中的列表实现
  4. Android中如何制作游戏的启动菜单
  5. Android聊天客户端Demo,开源了.基本功能都有,数据库,服务器都Ok
  6. 【Android UI设计与开发】第09期:底部菜单栏(四)Fragment+PopupWind
  7. [翻译]Android教程-保存数据-支持不同的平台版本
  8. Android——Json和Gson分别是什么,以及Json 数据的解析方法

随机推荐

  1. android 音频
  2. android 修改开关机铃声
  3. Android Handler解析和相关问题
  4. Android(安卓)横竖屏切换生命周期
  5. Android:使用JDBC链接MySQL数据库
  6. 13、Android重写系统返回键
  7. android 常用URI 值得记住
  8. 2011年沈大海讲师Android的新浪微博客户
  9. Android AIDL机制
  10. Android尺寸标注设计大全和Android切图规