项目结构:
为了让大家更有的耐心的阅读, 我先从简单的开始说起,我们先看下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>
然后从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<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);
}
}
然后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);
}
}
有一些注释提示大家去理解,我在这里也不能全部讲的那么详细,重要的是,还是要靠大家自己去理解,去参悟,这样才能真正学到东西。好了,大家自己慢慢去消化吧!最后我还是会把源码链接给共享出来,希望大家看了后对你们有所帮助,谢谢!