当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS的客户端菜单功能仿百度糯米/美团二级菜单

iOS的客户端菜单功能仿百度糯米/美团二级菜单

2019年07月24日  | 移动技术网IT编程  | 我要评论

躲避探照灯,12306网上订票提前几天,dnf范弗拉丁的自白书怎么得

我刚好最近在开发一个商城项目,实现了一个简单的控件,就和大家一起分享一下。

控件的效果就是类似百度糯米或者美团的二级菜单,我开发ios的客户端菜单功能,直接参考了git一个项目,对应的ui效果:

其实效果看起来还不错。ios开发完成以后,又要准备开发android,发现对应网上的案例还是很少的,或者不是想要的效果。我想参考了别人的项目代码,也为开源项目做点贡献,准备自己开发一个android的menu项目;

折腾了大概三个小时,终于搞定了,效果如下:

从图片不难看出,这是一个多级菜单,控制者填充数据源,所以实现的时候,尽量封装的使用,使用者最好是能两三行代码搞定。

具体实现思路:

1、menuview,实现了第一级菜单的封装

①、view初始化和数据源定义;

②、绘制一级菜单;

③、控制子菜单的popupwindow弹出框

代码具体如下:

package com.spring.sky.menuproject.view; 
import android.content.context; 
import android.util.attributeset; 
import android.view.gravity; 
import android.view.view; 
import android.view.viewgroup; 
import android.widget.linearlayout; 
import android.widget.textview; 
import com.spring.sky.menuproject.appinfoutils; 
import com.spring.sky.menuproject.r; 
import java.util.list; 
/** 
* created by springsky on 16/10/24. 
*/ 
public class menuview extends linearlayout implements view.onclicklistener, menupopupwindow.onmenulistener { 
private string[] hinttexts; 
public list[] datasource; 
public textview[] textviews; 
private int textcolor = r.color.gray_80; 
private int textcolorselected = r.color.orange; 
private int textsize; 
private int lineheight ; 
private menupopupwindow menupopupwindow; 
private onmenulistener onmenulistener; 
view lineview; 
textview lasttv; 
private indexpath[] indexpaths; 
public menuview(context context) { 
super(context); 
init(context); 
} 
public menuview(context context, attributeset attrs) { 
super(context, attrs); 
init(context); 
} 
public menuview(context context, attributeset attrs, int defstyleattr) { 
super(context, attrs, defstyleattr); 
init(context); 
} 
public void sethinttexts(string[] hinttexts) { 
this.hinttexts = hinttexts; 
} 
public void setdatasource(list[] datasource) { 
this.datasource = datasource; 
reloaddata(); 
} 
/*** 
* 设置当前选中的数据 
* @param indexpath 
*/ 
public void setindexpath(indexpath indexpath) { 
setindexpath(indexpath, false); 
} 
/*** 
* 设置当前选中的内容 
* @param indexpath 
* @param actionmenu 是否通知监听器 
*/ 
public void setindexpath(indexpath indexpath, boolean actionmenu) { 
indexpaths[indexpath.column] = indexpath; 
if (actionmenu) { 
textview lasttv = textviews[indexpath.column]; 
list<menumodel> list = datasource[indexpath.column]; 
if(list == null || indexpath.row >= list.size()){ 
return; 
} 
menumodel left = list.get(indexpath.row); 
menumodel menumodel = null; 
if (indexpath.item < 0) { 
menumodel = left; 
} else { 
menumodel right = left.chindmenu.get(indexpath.item); 
menumodel = right; 
} 
lasttv.settext(menumodel.value); 
if (onmenulistener != null) { 
onmenulistener.onmenu(indexpath, menumodel); 
} 
} 
} 
public list[] getdatasource() { 
return datasource; 
} 
/*** 
* 初始化 
* @param context 
*/ 
private void init(context context) { 
menupopupwindow = new menupopupwindow(context); 
menupopupwindow.setonmenulistener(this); 
appinfoutils.getviewheight(this); 
textsize = appinfoutils.sptopx(6); 
lineheight = appinfoutils.diptopx(1); 
} 
/*** 
* 绘制一级菜单分类 
*/ 
private void reloaddata() { 
removeallviews(); 
if (datasource == null || datasource.length < 1) { 
return; 
} 
int count = datasource.length; 
int height = getmeasuredheight() - lineheight; 
setorientation(linearlayout.vertical); 
linearlayout menubaseview = new linearlayout(getcontext()); 
menubaseview.setlayoutparams(new layoutparams(layoutparams.match_parent, height)); 
menubaseview.setweightsum(count); 
menubaseview.setgravity(gravity.center); 
menubaseview.setorientation(linearlayout.horizontal); 
indexpaths = new indexpath[count]; 
textviews = new textview[count]; 
for (int i = 0; i < count; i++) { 
indexpaths[i] = new indexpath(i, 0, -1); 
linearlayout tempbaseview = new linearlayout(getcontext()); 
tempbaseview.setlayoutparams(new layoutparams(layoutparams.match_parent, height, 1)); 
tempbaseview.setgravity(gravity.center); 
textview tv = new textview(getcontext()); 
tv.settextcolor(getresources().getcolor(textcolor)); 
tv.settextsize(textsize); 
linearlayout.layoutparams params = new layoutparams(layoutparams.wrap_content, layoutparams.match_parent); 
tv.setgravity(gravity.center); 
tv.setlayoutparams(params); 
tv.setmaxlines(1); 
tv.setcompounddrawableswithintrinsicbounds(0, 0, r.mipmap.triangle_down, 0); 
tv.setcompounddrawablepadding(appinfoutils.diptopx(2)); 
tv.setid(i); 
tv.setonclicklistener(this); 
textviews[i] = tv; 
tempbaseview.addview(tv); 
menubaseview.addview(tempbaseview); 
if (hinttexts != null && i < hinttexts.length) { 
tv.settext(hinttexts[i]); 
} 
view lineview = new view(getcontext()); 
lineview.setbackgroundcolor(getresources().getcolor(r.color.main_bg_in)); 
menubaseview.addview(lineview, new layoutparams(appinfoutils.diptopx(1), height - appinfoutils.diptopx(8))); 
} 
addview(menubaseview); 
lineview = new view(getcontext()); 
lineview.setbackgroundcolor(getresources().getcolor(r.color.main_bg_in)); 
addview(lineview, new layoutparams(viewgroup.layoutparams.match_parent, lineheight)); 
} 
/*** 
* 一级菜单点击事件触发 
* @param v 
*/ 
@override 
public void onclick(view v) { 
lasttv = (textview) v; 
int column = v.getid(); 
list<menumodel> list = datasource[column]; 
lasttv.setcompounddrawableswithintrinsicbounds(0, 0, r.mipmap.triangle_up, 0); 
lasttv.settextcolor(getresources().getcolor(textcolorselected)); 
menupopupwindow.setleftlist(column, list); 
indexpath indexpath = indexpaths[column]; 
menupopupwindow.setselect(indexpath.row, indexpath.item); 
// int[] location = new int[2]; 
// lineview.getlocationonscreen(location); 
menupopupwindow.showasdropdown(lineview); 
// menupopupwindow.showatlocation(this,gravity.bottom,0,0); 
} 
/*** 
* 弹出框点击事件处理 
* @param column 
* @param row 
* @param item 
* @param menumodel 
*/ 
@override 
public void onmenu(int column, int row, int item, menumodel menumodel) { 
textview lasttv = textviews[column]; 
lasttv.settext(menumodel.value); 
indexpath indexpath = indexpaths[column]; 
indexpath.row = row; 
indexpath.item = item; 
onmenudismiss(); 
if (onmenulistener != null) { 
onmenulistener.onmenu(indexpath, menumodel); 
} 
} 
/*** 
* 弹出框关闭 
*/ 
@override 
public void onmenudismiss() { 
lasttv.settextcolor(getresources().getcolor(r.color.gray_80)); 
lasttv.setcompounddrawableswithintrinsicbounds(0, 0, r.mipmap.triangle_down, 0); 
} 
/*** 
* 设置监听器 
* @param onmenulistener 
*/ 
public void setonmenulistener(onmenulistener onmenulistener) { 
this.onmenulistener = onmenulistener; 
} 
public static interface onmenulistener { 
void onmenu(indexpath indexpath, menumodel menumodel); 
} 
/**** 
* 菜单列、行、二级子行 
*/ 
public static class indexpath { 
public int column; //一级菜单 
public int row; //left row 
public int item; //right row 
public indexpath(int column, int row, int item) { 
this.column = column; 
this.row = row; 
this.item = item; 
} 
} 
}

2、popupwindow主要是实现了弹出框显示子列的一级和二级菜单的数据。

我使用了两个listview来动态实现数据的加载。

具体代码如下:

package com.spring.sky.menuproject.view; 
import android.content.context; 
import android.graphics.drawable.paintdrawable; 
import android.view.layoutinflater; 
import android.view.view; 
import android.view.viewgroup; 
import android.view.animation.animation; 
import android.view.animation.animationutils; 
import android.widget.adapterview; 
import android.widget.linearlayout; 
import android.widget.listview; 
import android.widget.popupwindow; 
import com.spring.sky.menuproject.r; 
import java.util.list; 
/** 
* created by springsky on 16/10/20. 
*/ 
public class menupopupwindow extends popupwindow implements adapterview.onitemclicklistener { 
context mcontext; 
private listview leftlv,rightlv; 
private onmenulistener onmenulistener; 
private list<menumodel> leftlist,rightlist; 
private menuadapter menuleftadapter,menurightadapter; 
private int column; 
boolean hassecond; 
/*** 
* 初始化 
* @param context 
*/ 
public menupopupwindow(context context){ 
this.mcontext = context; 
view view = layoutinflater.from(mcontext).inflate(r.layout.menu_popup_window, null); 
leftlv = (listview) view.findviewbyid(r.id.leftlv); 
leftlv.setchoicemode(listview.choice_mode_single); 
rightlv = (listview) view.findviewbyid(r.id.rightlv); 
rightlv.setchoicemode(listview.choice_mode_single); 
setcontentview(view); 
setbackgrounddrawable(new paintdrawable()); 
setfocusable(true); 
setwidth(viewgroup.layoutparams.match_parent); 
setheight(linearlayout.layoutparams.wrap_content); 
setondismisslistener(new popupwindow.ondismisslistener() { 
@override 
public void ondismiss() { 
leftlv.setselection(0); 
rightlv.setselection(0); 
if( onmenulistener != null ){ 
onmenulistener.onmenudismiss(); 
} 
} 
}); 
menuleftadapter = new menuadapter(mcontext); 
menuleftadapter.setcolumn(0); 
menuleftadapter.setlist(leftlist); 
leftlv.setadapter(menuleftadapter); 
leftlv.setonitemclicklistener(this); 
menurightadapter = new menuadapter(mcontext); 
menurightadapter.setcolumn(1); 
menurightadapter.setlist(rightlist); 
rightlv.setadapter(menurightadapter); 
rightlv.setonitemclicklistener(this); 
} 
@override 
public void showasdropdown(view anchor) { 
super.showasdropdown(anchor); 
} 
/*** 
* 加载数据 
* @param column 
* @param leftlist 
*/ 
public void setleftlist(int column,list<menumodel> leftlist) { 
this.column = column; 
this.leftlist = leftlist; 
hassecond = false; 
for (menumodel childmodel : leftlist){ 
if(childmodel.haschind()){ 
hassecond = true; 
break; 
} 
} 
menuleftadapter.setlist(leftlist); 
if(!hassecond){ 
rightlv.setvisibility(view.gone); 
setrightlist(null); 
}else { 
rightlv.setvisibility(view.visible); 
} 
} 
/*** 
* 默认选中的一级和二级行 
* @param row 
* @param item 
*/ 
public void setselect(int row,int item){ 
if(row < 0 || leftlist == null || row >= leftlist.size()){ 
return; 
} 
menumodel leftmodel = leftlist.get(row); 
leftlv.setselection(row); 
menuleftadapter.setselectposition(row); 
setrightlist(leftmodel.chindmenu); 
if(item < 0 || rightlist ==null || item >= rightlist.size()){ 
return; 
} 
rightlv.setselection(item); 
menurightadapter.setselectposition(item); 
} 
private void setrightlist(list<menumodel> rightlist) { 
this.rightlist = rightlist; 
menurightadapter.setlist(rightlist); 
} 
@override 
public void onitemclick(adapterview<?> parent, view view, int position, long id) { 
if(parent.getid() == leftlv.getid()){ 
menumodel model = leftlist.get(position); 
if(leftlv.getselecteditemposition() == position){ 
return; 
} 
if(model.haschind()){ 
menuleftadapter.setselectposition(position); 
setrightlist(model.chindmenu); 
}else { 
dismiss(); 
} 
onmenuclick(position,0,model); 
}else { 
menurightadapter.setselectposition(position); 
menumodel model = rightlist.get(position); 
onmenuclick(menuleftadapter.getselectposition(),position,model); 
dismiss(); 
} 
} 
void onmenuclick(int row,int item,menumodel model){ 
if(onmenulistener != null){ 
onmenulistener.onmenu(column,row,item,model); 
} 
} 
public void setonmenulistener(onmenulistener onmenulistener) { 
this.onmenulistener = onmenulistener; 
} 
public static interface onmenulistener{ 
void onmenu(int column, int row, int item, menumodel menumodel); 
void onmenudismiss(); 
} 
}

3、其他的就是menumodel,考虑是多级层次关系,所以建议使用链结构。

package com.spring.sky.menuproject.view; 
import java.util.list; 
/** 
* created by springsky on 16/10/20. 
*/ 
public class menumodel { 
public object key; //key 
public string value; //显示的内容 
public list<menumodel> chindmenu; //子列表数据 
public menumodel(){ 
super(); 
} 
public menumodel(object key, string value, list<menumodel> chindmenu){ 
super(); 
this.key = key; 
this.value = value; 
this.chindmenu = chindmenu; 
} 
/*** 
* 是否有子列表数据 
* @return 
*/ 
public boolean haschind(){ 
return (chindmenu != null && chindmenu.size() > 0); 
} 
}

诶,生活压力大了,也不会写博客了,就简单描述一下,希望大家不要见怪。

项目的源码,我已经提交到git上了。

下载地址:https://github.com/skyfouk/androidmenuproject.git

以上所述是小编给大家介绍的ios的客户端菜单功能仿百度糯米/美团二级菜单,希望对大家有所帮助

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

  • ios uicollectionview实现横向滚动

    现在使用卡片效果的app很多,之前公司让实现一种卡片效果,就写了一篇关于实现卡片的文章。文章最后附有demo实现上我选择了使用uicollectionview ... [阅读全文]
  • iOS UICollectionView实现横向滑动

    本文实例为大家分享了ios uicollectionview实现横向滑动的具体代码,供大家参考,具体内容如下uicollectionview的横向滚动,目前我使... [阅读全文]
  • iOS13适配深色模式(Dark Mode)的实现

    iOS13适配深色模式(Dark Mode)的实现

    好像大概也许是一年前, mac os系统发布了深色模式外观, 看着挺刺激, 时至今日用着也还挺爽的终于, 随着iphone11等新手机的发售, ios 13系统... [阅读全文]
  • ios 使用xcode11 新建项目工程的步骤详解

    ios 使用xcode11 新建项目工程的步骤详解

    xcode11新建项目工程,新增了scenedelegate这个类,转而将原appdelegate负责的对ui生命周期的处理担子接了过来。故此可以理解为:ios... [阅读全文]
  • iOS实现转盘效果

    本文实例为大家分享了ios实现转盘效果的具体代码,供大家参考,具体内容如下demo下载地址: ios转盘效果功能:实现了常用的ios转盘效果,轮盘抽奖效果的实现... [阅读全文]
  • iOS开发实现转盘功能

    本文实例为大家分享了ios实现转盘功能的具体代码,供大家参考,具体内容如下今天给同学们讲解一下一个转盘选号的功能,直接上代码直接看viewcontroller#... [阅读全文]
  • iOS实现轮盘动态效果

    本文实例为大家分享了ios实现轮盘动态效果的具体代码,供大家参考,具体内容如下一个常用的绘图,主要用来打分之类的动画,效果如下。主要是ios的绘图和动画,本来想... [阅读全文]
  • iOS实现九宫格连线手势解锁

    本文实例为大家分享了ios实现九宫格连线手势解锁的具体代码,供大家参考,具体内容如下demo下载地址:效果图:核心代码://// clockview.m// 手... [阅读全文]
  • iOS实现卡片堆叠效果

    本文实例为大家分享了ios实现卡片堆叠效果的具体代码,供大家参考,具体内容如下如图,这就是最终效果。去年安卓5.0发布的时候,当我看到安卓全新的material... [阅读全文]
  • iOS利用余弦函数实现卡片浏览工具

    iOS利用余弦函数实现卡片浏览工具

    本文实例为大家分享了ios利用余弦函数实现卡片浏览工具的具体代码,供大家参考,具体内容如下一、实现效果通过拖拽屏幕实现卡片移动,左右两侧的卡片随着拖动变小,中间... [阅读全文]
验证码:
移动技术网