Android仿美团淘宝实现多级下拉列表菜单功能
我们在常用的电商或者旅游app中,例如美团,手机淘宝等等,都能够看的到有那种下拉式的二级列表菜单。具体如图所示:
上面两张图就是美团的一个二级列表菜单的一个展示。我相信很多人都想开发一个跟它一样的功能放到自己的app中。好,接下来我们就开始动手,解决它。
1.结构分析
首先,我们给出这个下拉菜单需要的组建。我们用线框图来分析。
1)如上图所示,最外围的是一个activity,顶部包含了一个view的容器,这个容器主要是装载togglebutton来实现诸如美团里面的“美食,全城,理我最近,刷选”这一行。这一行一点就会弹出对应的下来菜单。
2)下拉菜单是如何实现的呢?,这里我们利用了popupwindow来实现这一弹出式窗口。然后我们在弹出式窗口里面再定义我们的下来列表项,是单列还是二级菜单,都是由里面来定。
3)不同的菜单,需要一级或者需要二级,在这里根据我的需求而变动。我们在popupwindow上面加一个自定义的leftview,或者是middleview,rightview。主要是一个togglebutton,你弹出一个窗口,你就定制一个窗口。
4)视图里面嵌入listview,就形成了列表项。
好分析就到上面为止,接下来我们一步步的说明实现。
2.项目结构
本项目的项目结构如图所示:
1) adapter。适配器,主要是为listview提供数据适配的。
2)mainactivity。主活动页面。
3)expandtabview。本项目的核心类,它包含togglebutton容器和popupwindow,是控制弹出窗口的核心类。
4)viewleft,viewmiddle,viewright。是弹出里面嵌套的类,实现不同的列表菜单。
3.mainactivity
承载所有元素。看代码比看文字实在。
package com.example.expandtabview; import java.util.arraylist; import android.app.activity; import android.os.bundle; import android.util.log; import android.view.view; import android.widget.toast; import com.example.view.expandtabview; import com.example.view.viewleft; import com.example.view.viewmiddle; import com.example.view.viewright; public class mainactivity extends activity { private static final string tag = "mainactivity"; private expandtabview expandtabview; private arraylist mviewarray = new arraylist(); private viewleft viewleft; private viewmiddle viewmiddle; private viewright viewright; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); initview(); initvaule(); initlistener(); } private void initview() { log.d(tag,"initview"); expandtabview = (expandtabview) findviewbyid(r.id.expandtab_view); viewleft = new viewleft(this); viewmiddle = new viewmiddle(this); viewright = new viewright(this); } private void initvaule() { log.d(tag,"initvalue"); mviewarray.add(viewleft); mviewarray.add(viewmiddle); mviewarray.add(viewright); arraylist mtextarray = new arraylist(); mtextarray.add("距离"); mtextarray.add("区域"); mtextarray.add("距离"); expandtabview.setvalue(mtextarray, mviewarray);//将三个下拉列表设置进去 expandtabview.settitle(viewleft.getshowtext(), 0); expandtabview.settitle(viewmiddle.getshowtext(), 1); expandtabview.settitle(viewright.getshowtext(), 2); } private void initlistener() { log.d(tag,"initlistener"); viewleft.setonselectlistener(new viewleft.onselectlistener() { @override public void getvalue(string distance, string showtext) { log.d("viewleft", "onselectlistener, getvalue"); onrefresh(viewleft, showtext); } }); viewmiddle.setonselectlistener(new viewmiddle.onselectlistener() { @override public void getvalue(string showtext) { log.d("viewmiddle","onselectlistener, getvalue"); onrefresh(viewmiddle,showtext); } }); viewright.setonselectlistener(new viewright.onselectlistener() { @override public void getvalue(string distance, string showtext) { log.d("viewright","onselectlistener, getvalue"); onrefresh(viewright, showtext); } }); } private void onrefresh(view view, string showtext) { log.d(tag,"onrefresh,view:"+view+",showtext:"+showtext); expandtabview.onpressback(); int position = getpositon(view); if (position >= 0 && !expandtabview.gettitle(position).equals(showtext)) { expandtabview.settitle(showtext, position); } toast.maketext(mainactivity.this, showtext, toast.length_short).show(); } private int getpositon(view tview) { log.d(tag,"getposition"); for (int i = 0; i < mviewarray.size(); i++) { if (mviewarray.get(i) == tview) { return i; } } return -1; } @override public void onbackpressed() { if (!expandtabview.onpressback()) { finish(); } } }
4 .expandtabview
最主要就是如何处理当我们点击这些togglebutton的时候要弹出或者收起这些popupwindow。
package com.example.view; import java.util.arraylist; import com.example.expandtabview.r; import android.app.activity; import android.content.context; import android.util.attributeset; import android.util.log; import android.view.layoutinflater; import android.view.view; import android.widget.linearlayout; import android.widget.popupwindow; import android.widget.popupwindow.ondismisslistener; import android.widget.relativelayout; import android.widget.textview; import android.widget.togglebutton; /** * 菜单控件头部,封装了下拉动画,动态生成头部按钮个数 * * @author zengjinlong */ public class expandtabview extends linearlayout implements ondismisslistener { private static final string tag = "expandtabview"; private togglebutton selectedbutton; private arraylist mtextarray = new arraylist(); private arraylist mviewarray = new arraylist(); private arraylist mtogglebutton = new arraylist(); private context mcontext; private final int small = 0; private int displaywidth; private int displayheight; private popupwindow popupwindow; private int selectposition; public expandtabview(context context) { super(context); init(context); } public expandtabview(context context, attributeset attrs) { super(context, attrs); init(context); } /** * 根据选择的位置设置tabitem显示的值 */ public void settitle(string valuetext, int position) { if (position < mtogglebutton.size()) { mtogglebutton.get(position).settext(valuetext); } } public void settitle(string title){ } /** * 根据选择的位置获取tabitem显示的值 */ public string gettitle(int position) { if (position < mtogglebutton.size() && mtogglebutton.get(position).gettext() != null) { return mtogglebutton.get(position).gettext().tostring(); } return ""; } /** * 设置tabitem的个数和初始值 * @param textarray 标题数组 * @param viewarray 控件数组 */ public void setvalue(arraylist textarray, arraylist viewarray) { if (mcontext == null) { return; } layoutinflater inflater = (layoutinflater) mcontext.getsystemservice(context.layout_inflater_service); log.d(tag,"setvalue"); mtextarray = textarray; for (int i = 0; i < viewarray.size(); i++) { final relativelayout r = new relativelayout(mcontext); int maxheight = (int) (displayheight * 0.7); relativelayout.layoutparams rl = new relativelayout.layoutparams(relativelayout.layoutparams.match_parent, maxheight); rl.leftmargin = 10; rl.rightmargin = 10; r.addview(viewarray.get(i), rl); mviewarray.add(r); r.settag(small); togglebutton tbutton = (togglebutton) inflater.inflate(r.layout.toggle_button, this, false); addview(tbutton); view line = new textview(mcontext); line.setbackgroundresource(r.drawable.choosebar_line); if (i < viewarray.size() - 1) { linearlayout.layoutparams lp = new linearlayout.layoutparams(2, linearlayout.layoutparams.match_parent); addview(line, lp); } mtogglebutton.add(tbutton); tbutton.settag(i); tbutton.settext(mtextarray.get(i)); r.setonclicklistener(new onclicklistener() { @override public void onclick(view v) { log.d("relativelayout","view:"+v); onpressback(); } }); r.setbackgroundcolor(mcontext.getresources().getcolor(r.color.popup_main_background)); tbutton.setonclicklistener(new onclicklistener() { @override public void onclick(view view) { log.d("tbutton","setonclicklistener(l)"); // initpopupwindow(); togglebutton tbutton = (togglebutton) view; if (selectedbutton != null && selectedbutton != tbutton) { selectedbutton.setchecked(false); } selectedbutton = tbutton; selectposition = (integer) selectedbutton.gettag(); startanimation(); if (monbuttonclicklistener != null && tbutton.ischecked()) { monbuttonclicklistener.onclick(selectposition); } } }); }// for.. } private void startanimation() { log.d(tag,"startanimation"); if (popupwindow == null) { log.d(tag,"startanimation(),new popupwindow now"); popupwindow = new popupwindow(mviewarray.get(selectposition), displaywidth, displayheight); popupwindow.setanimationstyle(r.style.popupwindowanimation); popupwindow.setfocusable(false); popupwindow.setoutsidetouchable(true); } log.d(tag,"startanimation(),selectedbutton:"+selectedbutton+",ischecked:"+selectedbutton.ischecked()+ ",popupwindow.isshowing:"+popupwindow.isshowing()); if (selectedbutton.ischecked()) { if (!popupwindow.isshowing()) { showpopup(selectposition); } else { popupwindow.setondismisslistener(this); popupwindow.dismiss(); hideview(); } } else { if (popupwindow.isshowing()) { popupwindow.dismiss(); hideview(); } } } private void showpopup(int position) { view tview = mviewarray.get(selectposition).getchildat(0); if (tview instanceof viewbaseaction) { viewbaseaction f = (viewbaseaction) tview; f.show(); } if (popupwindow.getcontentview() != mviewarray.get(position)) { popupwindow.setcontentview(mviewarray.get(position)); } popupwindow.showasdropdown(this, 0, 0); } /** * 如果菜单成展开状态,则让菜单收回去 */ public boolean onpressback() { log.d(tag,"onpressback"); if (popupwindow != null && popupwindow.isshowing()) { popupwindow.dismiss(); hideview(); if (selectedbutton != null) { selectedbutton.setchecked(false); } return true; } else { return false; } } private void hideview() { log.d(tag, "hide()"); view tview = mviewarray.get(selectposition).getchildat(0); if (tview instanceof viewbaseaction) { viewbaseaction f = (viewbaseaction) tview; f.hide(); } } private void init(context context) { mcontext = context; displaywidth = ((activity) mcontext).getwindowmanager().getdefaultdisplay().getwidth(); displayheight = ((activity) mcontext).getwindowmanager().getdefaultdisplay().getheight(); setorientation(linearlayout.horizontal); } @override public void ondismiss() { log.d(tag,"ondismiss,selectposition:"+selectposition); showpopup(selectposition); popupwindow.setondismisslistener(null); } private onbuttonclicklistener monbuttonclicklistener; /** * 设置tabitem的点击监听事件 */ public void setonbuttonclicklistener(onbuttonclicklistener l) { monbuttonclicklistener = l; } /** * 自定义tabitem点击回调接口 */ public interface onbuttonclicklistener { public void onclick(int selectposition); } }
5.viewleft
其中的一个示例,其他两个就不列举了
package com.example.view; import com.example.adapter.textadapter; import com.example.expandtabview.r; import android.content.context; import android.util.attributeset; import android.view.layoutinflater; import android.view.view; import android.widget.listview; import android.widget.relativelayout; import android.widget.toast; public class viewleft extends relativelayout implements viewbaseaction{ private static final string tag = "viewleft"; private listview mlistview; private final string[] items = new string[] { "item1", "item2", "item3", "item4", "item5", "item6" };//显示字段 private final string[] itemsvaule = new string[] { "1", "2", "3", "4", "5", "6" };//隐藏id private onselectlistener monselectlistener; private textadapter adapter; private string mdistance; private string showtext = "item1"; private context mcontext; public string getshowtext() { return showtext; } public viewleft(context context) { super(context); init(context); } public viewleft(context context, attributeset attrs, int defstyle) { super(context, attrs, defstyle); init(context); } public viewleft(context context, attributeset attrs) { super(context, attrs); init(context); } private void init(context context) { mcontext = context; layoutinflater inflater = (layoutinflater) context.getsystemservice(context.layout_inflater_service); inflater.inflate(r.layout.view_distance, this, true); setbackgrounddrawable(getresources().getdrawable(r.drawable.choosearea_bg_mid)); mlistview = (listview) findviewbyid(r.id.listview); adapter = new textadapter(context, items, r.drawable.choose_item_right, r.drawable.choose_eara_item_selector); adapter.settextsize(17); if (mdistance != null) { for (int i = 0; i < itemsvaule.length; i++) { if (itemsvaule[i].equals(mdistance)) { adapter.setselectedpositionnonotify(i); showtext = items[i]; break; } } } mlistview.setadapter(adapter); adapter.setonitemclicklistener(new textadapter.onitemclicklistener() { @override public void onitemclick(view view, int position) { if (monselectlistener != null) { showtext = items[position]; monselectlistener.getvalue(itemsvaule[position], items[position]); } } }); } public void setonselectlistener(onselectlistener onselectlistener) { monselectlistener = onselectlistener; } public interface onselectlistener { public void getvalue(string distance, string showtext); } @override public void hide() { } @override public void show() { } }
6.效果图
以上所述是小编给大家介绍的android仿美团淘宝实现多级下拉列表菜单功能,多条目的实例代码,希望对大家有所帮助