1、PopupDownMenu介绍
想必大家在各种诸如美团,淘宝等app上都有看到过这样的下拉菜单筛选栏,而据我所知,别人还原的做法大多是用单纯的ListView或者ExpandableListView更或者自定义View之类的来实现,但我是第一想法使用利用PopupWindow+ListView的方法实现的,所以就有了这个项目。
同样,为了提高这个的利用性,我为PopupWindow设置了一个包装类,判断不同级别的目录有不同的做法,因为一般的app也只会做到三级目录,我在操作上就只做到三级的效果了。但是有了这个包装类,实现起来将会十分简单~只需要按规则放入数据就可以了。(因为是实现效果了就放出来了,就求不要吐槽界面丑了)
2、直接看预览图
3、使用方法
3.1Gradle
在project 中build.gradle下增加:
1
2
3
4
5
6
7
8allprojects { repositories { google() jcenter() maven { url 'https://jitpack.io' } } }
在app中build.gradle下添加:
1
2
3dependencies { implementation 'com.github.ChitoseYono:PopupDownMenu:v1.0.2' }
3.2布局文件
以单单一个三级菜单为例,需要一个有三个ListView的布局文件:
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<?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:orientation="horizontal" android:baselineAligned="false" > <ListView android:id="@+id/pop_listview_left" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:dividerHeight="0.5dp" android:divider="#e2e2e2" android:scrollbars="none" android:scrollingCache="false" /> <ListView android:id="@+id/pop_listview_center" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" android:layout_weight="1" android:background="#efefef" android:dividerHeight="0.5dp" android:divider="#c6c6c6" android:scrollingCache="false"/> <ListView android:id="@+id/pop_listview_right" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="none" android:layout_weight="1" android:background="#e2e2e2" android:dividerHeight="0.5dp" android:divider="#c6c6c6" android:scrollingCache="false"/> </LinearLayout>
(在这里你可以自定义如divider,scrollbars,background,dividerHeight等属性[备注:这里setListSelector可能会显示有问题,不建议加])
3.3数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24itemList.add(new PopItem(1, 0, "语言")); itemList.add(new PopItem(2, 1, "说话的")); itemList.add(new PopItem(3, 1, "编程的")); itemList.add(new PopItem(4, 1, "凑数的")); itemList.add(new PopItem(5, 1, "还是凑数的")); itemList.add(new PopItem(6, 2, "中文")); itemList.add(new PopItem(7, 2, "英文")); itemList.add(new PopItem(8, 2, "法语")); itemList.add(new PopItem(9, 2, "日语")); itemList.add(new PopItem(10, 3, "C语言")); itemList.add(new PopItem(11, 3, "Java")); itemList.add(new PopItem(12, 3, "Python")); itemList.add(new PopItem(13, 0, "性别")); itemList.add(new PopItem(14, 13, "男性")); itemList.add(new PopItem(15, 13, "女性")); itemList.add(new PopItem(16, 0, "课程")); itemList.add(new PopItem(17, 16, "公选课")); itemList.add(new PopItem(18, 16, "专业课")); itemList.add(new PopItem(19, 17, "大英")); itemList.add(new PopItem(20, 17, "数学")); itemList.add(new PopItem(21, 18, "数据库")); itemList.add(new PopItem(22, 18, "数据结构")); itemList.add(new PopItem(23, 18, "操作系统")); itemList.add(new PopItem(24, 0, "凑数"));
数据的形式十分简单:id就是这个item的id,pid就是他的父类id,名称就不多说了。(切记要按照id顺序放入,不然会报错)
3.4PopupDownMenu的初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19//初始化PopupWindow中的三个ListView view = LayoutInflater.from(this).inflate(R.layout.popup_triple_layout, null); firstListView = view.findViewById(R.id.pop_listview_left); secondListView = view.findViewById(R.id.pop_listview_center); thirdListView = view.findViewById(R.id.pop_listview_right); p = new PopupDownMenu(this, itemList, width, height, view, drawable, firstListView, secondListView, thirdListView); p.popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { //处理数据方式要防止取得的数据是不正常的数据 if (.results[3] != null) { Toast.makeText(MainActivity.this, p.results[0] + "+" + p.results[1] + "+" + p.results[2], Toast.LENGTH_SHORT).show(); } } });
三级菜单就需要三个ListView,然后定义你需要的PopupDownMenu的宽和高,还要自定义一个drawable作为PopupDownMenu的背景。
而数据的获得就需要通过PopupDownMenu中包装的popupWindow的OnDismiss中回调获得(备注:p.result[3]是数据正常输出标记,没有这个判定可能会导致数据缓存导致的异常而得到不理想的数据)
3.5给事件源增添加监听事件
1
2
3
4
5
6
7
8
9
10
11
12tv_demo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //判断是否popupWindow是否已经在显示,没显示就显示,显示就dismiss if (!p.popupWindow.isShowing()) { p.popupWindow.showAsDropDown(v,0,0); } else { p.popupWindow.dismiss(); } } });
这就能实现显示了点击按钮时:没显示就显示,显示了就收回了,就此基本上完成了正常的功能的实现了!
不过要实现图中的效果还需要加上一些东西的...例如点击外部popWindow的消失,popWindow显示时的变暗效果,多个PopupDownMenu时的兼容效果等等来完善用户体验,这些也需要你们自己写在Activity里的,我在下面写吧
4、用户体验的完善
4.1实现点击外部布局的popupWindow消失
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15@Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { //点击按钮以外的布局时要把可能有的PopupWindow清除 case MotionEvent.ACTION_UP: if (p.popupWindow.isShowing()) { p.popupWindow.dismiss(); } break; default: break; } return true; }
如果只是点击事件源的话不会触发这个,因为会被事件源的监听拦下,所以放心加上这个就可以了!
4.2变暗效果
这个效果的话...我就有点投机取巧了。这里需要你们的Activity里的布局有一个DarkView布局,像这样
1
2
3
4
5
6<View android:id="@+id/main_darkview" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#9b9b9b" android:visibility="gone"/>
只要在事件源的onClick里面加上
1darkView.setVisibility(View.VISIBLE);
再在PopupDownMenu的onDismiss中加上:
1darkView.setVisibility(View.GONE);
很简单易懂吧~不过人性化设计一点就要加上渐变动画了,这个可以参照我的示例代码中的anim文件就行,其实就是startAnimation的事。
4.3多个Menu时的兼容
在实际使用时应该不会只有一个出现,所以需要解决一些多个PopupDownMenu可能会产生的问题:
实际上也很好解决的,假设还有两个,那么只要在事件源的onClick里面加上:
1
2
3
4
5
6
7//避免另外两个pop窗口还存在的情况 if (p1.popupWindow.isShowing()) { p1.popupWindow.dismiss(); } if (p2.popupWindow.isShowing()) { p2.popupWindow.dismiss(); }
4.4小箭头效果
首先你得准备两个小箭头图片...然后做一个像这样的selector:
1
2
3
4
5
6
7<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:drawable="@drawable/ic_up"/> <item android:state_selected="false" android:drawable="@drawable/ic_down"/> </selector>
再在你的代码中对事件源的onClick和PopupDownWindow的onDismiss中分别加上
1tv.setSelected(true);
和
1tv.setSelected(false);
就ojbk了(这个我本来不太想的,因为应该都知道怎么做的吧)
总之!到此就能实现预览图的效果了!
5、其他事项
1.对于ListView里的各项的布局的自定义设置
这个需要直接改依赖包library中的东西了。
直接改res/popup_item.xml就可以了。
2.对于ListView各项点击效果的自定义设置
这个...也需要改Library中的文件了,直接改res/item_selector就可以了,放一张截图吧:
3.其他一些话
这也只是大概也就做了几天的一个小想法,像上面两点需要到依赖包里改文件这问题我会再想想怎么处理的,也可能存在没发现的Bug,或者设计很丑之类的问题,又或者设计理念上的更新,我都会注意处理的。
总之,欢迎大家评论提出问题和使用上的其他问题,我会尽快回复!过一段时间我也会试着再写一篇blog说明是怎么做的。
另外各位客官github求一波star、fork、issue三连啦。
4. 做法大致概括
初始化一个List<List<Integer>> mList
遍历一次itemList,
每遍历一个popItem元素,都给mList.add(null)
然后分情况
①Pid为0的元素,不做任何操作
②Pid不为0的元素,给mList.get(Pid).add(id)
这样得到的mList上的第i个元素,
如果mList.get(i)!=null,说明他是有子节点的结点
若为null则是没有子节点的结点
6、项目下载
项目在GitHub上的地址:
GitHub上的PopupDownMenu
在CSDN上的下载地址:
CSDN下载地址
(CSDN上下载要C币,去GitHub下载就行)
最后
以上就是优秀胡萝卜最近收集整理的关于仿美团、淘宝等三层以下的任意层级下拉筛选菜单PopupDownMenu1、PopupDownMenu介绍2、直接看预览图 3、使用方法 4、用户体验的完善 5、其他事项6、项目下载 的全部内容,更多相关仿美团、淘宝等三层以下内容请搜索靠谱客的其他文章。
发表评论 取消回复