欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-19 12:20:10
我刚好最近在开发一个商城项目,实现了一个简单的控件,就和大家一起分享一下。 控件的效果就是类似百度糯米或者美团的二级菜单,我开发ios的客户端菜单功能,直接参考了git一...

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

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

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

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

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

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

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

具体实现思路:

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的客户端菜单功能仿百度糯米/美团二级菜单,希望对大家有所帮助

上一篇:

下一篇: