Android提高之自定义Menu(TabMenu)实现方法
程序员文章站
2022-05-16 12:30:19
一般使用过ucweb-android版的人都应该对其特殊的menu有一定的印象,把menu做成tab-menu(支持分页的menu),可以容纳比android传统的menu...
一般使用过ucweb-android版的人都应该对其特殊的menu有一定的印象,把menu做成tab-menu(支持分页的menu),可以容纳比android传统的menu更丰富的内容(android的menu超过6项则缩略在[更多]里),本文参考网上的例子的基础上对例子进行简化以及封装,使其作为一个复合控件融入自己的framework。
先来看看本文程序运行的效果如下图所示:
tabmenu本身就是一个popupwindow,popupwindow上面放了两个gridview,第一个gridview就是分页标签,位于popupwindow的顶部,第二个gridview是菜单,位于popupwindow的主体。为了实现popupwindow的弹出/退出的动画效果,本文使用了以下代码:
在工程的res文件夹里添加anim子目录,再新建文件popup_enter.xml:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromydelta="100%p" android:toydelta="0" android:duration="1000" /> <alpha android:fromalpha="0.0" android:toalpha="1.0" android:duration="1000" /> </set>
新建文件popup_exit.xml:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromydelta="0" android:toydelta="100%p" android:duration="1000" /> <alpha android:fromalpha="1.0" android:toalpha="0.0" android:duration="1000" /> </set>
在工程的values文件夹里新建文件popup_animation.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <style name="popupanimation" parent="android:animation"> <item name="android:windowenteranimation">@anim/popup_enter</item> <item name="android:windowexitanimation">@anim/popup_exit</item> </style> </resources>
main.xml的源码如下:
<?xml version="1.0" encoding="utf-8"?> <linearlayout android:id="@+id/linearlayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <textview android:id="@+id/textview01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="扩展menu----hellogv"></textview> </linearlayout>
tabmenu的封装类tabmenu.java的源码如下:
package com.testtabmenu; import android.content.context; import android.graphics.color; import android.graphics.drawable.colordrawable; import android.view.gravity; import android.view.view; import android.view.viewgroup; import android.widget.baseadapter; import android.widget.gridview; import android.widget.imageview; import android.widget.linearlayout; import android.widget.popupwindow; import android.widget.textview; import android.widget.adapterview.onitemclicklistener; import android.widget.linearlayout.layoutparams; public class tabmenu extends popupwindow{ private gridview gvbody, gvtitle; private linearlayout mlayout; private menutitleadapter titleadapter; public tabmenu(context context,onitemclicklistener titleclick,onitemclicklistener bodyclick, menutitleadapter titleadapter,int colorbgtabmenu,int anitabmenu){ super(context); mlayout = new linearlayout(context); mlayout.setorientation(linearlayout.vertical); //标题选项栏 gvtitle = new gridview(context); gvtitle.setlayoutparams(new layoutparams(layoutparams.fill_parent, layoutparams.wrap_content)); gvtitle.setnumcolumns(titleadapter.getcount()); gvtitle.setstretchmode(gridview.stretch_column_width); gvtitle.setverticalspacing(1); gvtitle.sethorizontalspacing(1); gvtitle.setgravity(gravity.center); gvtitle.setonitemclicklistener(titleclick); gvtitle.setadapter(titleadapter); gvtitle.setselector(new colordrawable(color.transparent));//选中的时候为透明色 this.titleadapter=titleadapter; //子选项栏 gvbody = new gridview(context); gvbody.setlayoutparams(new layoutparams(layoutparams.fill_parent,layoutparams.wrap_content)); gvbody.setselector(new colordrawable(color.transparent));//选中的时候为透明色 gvbody.setnumcolumns(4); gvbody.setstretchmode(gridview.stretch_column_width); gvbody.setverticalspacing(10); gvbody.sethorizontalspacing(10); gvbody.setpadding(10, 10, 10, 10); gvbody.setgravity(gravity.center); gvbody.setonitemclicklistener(bodyclick); mlayout.addview(gvtitle); mlayout.addview(gvbody); //设置默认项 this.setcontentview(mlayout); this.setwidth(layoutparams.fill_parent); this.setheight(layoutparams.wrap_content); this.setbackgrounddrawable(new colordrawable(colorbgtabmenu));// 设置tabmenu菜单背景 this.setanimationstyle(anitabmenu); this.setfocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应 } public void settitleselect(int index) { gvtitle.setselection(index); this.titleadapter.setfocus(index); } public void setbodyselect(int index,int colorselbody) { int count=gvbody.getchildcount(); for(int i=0;i<count;i++) { if(i!=index) ((linearlayout)gvbody.getchildat(i)).setbackgroundcolor(color.transparent); } ((linearlayout)gvbody.getchildat(index)).setbackgroundcolor(colorselbody); } public void setbodyadapter(menubodyadapter bodyadapter) { gvbody.setadapter(bodyadapter); } /** * 自定义adapter,tabmenu的每个分页的主体 * */ static public class menubodyadapter extends baseadapter { private context mcontext; private int fontcolor,fontsize; private string[] texts; private int[] resid; /** * 设置tabmenu的分页主体 * @param context 调用方的上下文 * @param texts 按钮集合的字符串数组 * @param resid 按钮集合的图标资源数组 * @param fontsize 按钮字体大小 * @param color 按钮字体颜色 */ public menubodyadapter(context context, string[] texts,int[] resid, int fontsize,int fontcolor) { this.mcontext = context; this.fontcolor = fontcolor; this.texts = texts; this.fontsize=fontsize; this.resid=resid; } public int getcount() { return texts.length; } public object getitem(int position) { return makemenybody(position); } public long getitemid(int position) { return position; } private linearlayout makemenybody(int position) { linearlayout result=new linearlayout(this.mcontext); result.setorientation(linearlayout.vertical); result.setgravity(gravity.center_horizontal|gravity.center_vertical); result.setpadding(10, 10, 10, 10); textview text = new textview(this.mcontext); text.settext(texts[position]); text.settextsize(fontsize); text.settextcolor(fontcolor); text.setgravity(gravity.center); text.setpadding(5, 5, 5, 5); imageview img=new imageview(this.mcontext); img.setbackgroundresource(resid[position]); result.addview(img,new linearlayout.layoutparams(new layoutparams(layoutparams.wrap_content,layoutparams.wrap_content))); result.addview(text); return result; } public view getview(int position, view convertview, viewgroup parent) { return makemenybody(position); } } /** * 自定义adapter,tabmenu的分页标签部分 * */ static public class menutitleadapter extends baseadapter { private context mcontext; private int fontcolor,unselcolor,selcolor; private textview[] title; /** * 设置tabmenu的title * @param context 调用方的上下文 * @param titles 分页标签的字符串数组 * @param fontsize 字体大小 * @param fontcolor 字体颜色 * @param unselcolor 未选中项的背景色 * @param selcolor 选中项的背景色 */ public menutitleadapter(context context, string[] titles, int fontsize, int fontcolor,int unselcolor,int selcolor) { this.mcontext = context; this.fontcolor = fontcolor; this.unselcolor = unselcolor; this.selcolor=selcolor; this.title = new textview[titles.length]; for (int i = 0; i < titles.length; i++) { title[i] = new textview(mcontext); title[i].settext(titles[i]); title[i].settextsize(fontsize); title[i].settextcolor(fontcolor); title[i].setgravity(gravity.center); title[i].setpadding(10, 10, 10, 10); } } public int getcount() { return title.length; } public object getitem(int position) { return title[position]; } public long getitemid(int position) { return title[position].getid(); } /** * 设置选中的效果 */ private void setfocus(int index) { for(int i=0;i<title.length;i++) { if(i!=index) { title[i].setbackgrounddrawable(new colordrawable(unselcolor));//设置没选中的颜色 title[i].settextcolor(fontcolor);//设置没选中项的字体颜色 } } title[index].setbackgroundcolor(0x00);//设置选中项的颜色 title[index].settextcolor(selcolor);//设置选中项的字体颜色 } public view getview(int position, view convertview, viewgroup parent) { view v; if (convertview == null) { v = title[position]; } else { v = convertview; } return v; } } }
testtabmenu介绍了数据的定义以及tabmenu的使用,源码如下:
package com.testtabmenu; import android.app.activity; import android.graphics.color; import android.os.bundle; import android.view.gravity; import android.view.menu; import android.view.view; import android.widget.adapterview; import android.widget.adapterview.onitemclicklistener; import android.widget.toast; public class testtabmenu extends activity { tabmenu.menubodyadapter []bodyadapter=new tabmenu.menubodyadapter[3]; tabmenu.menutitleadapter titleadapter; tabmenu tabmenu; int seltitle=0; @override public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.main); //设置分页栏的标题 titleadapter = new tabmenu.menutitleadapter(this, new string[] { "常用", "设置", "工具" }, 16, 0xff222222,color.ltgray,color.white); //定义每项分页栏的内容 bodyadapter[0]=new tabmenu.menubodyadapter(this,new string[] { "常用1", "常用2", }, new int[] { r.drawable.menu_test, r.drawable.menu_bookmark},13, 0xffffffff); bodyadapter[1]=new tabmenu.menubodyadapter(this,new string[] { "设置1", "设置2", "设置3"}, new int[] { r.drawable.menu_edit, r.drawable.menu_delete, r.drawable.menu_fullscreen},13, 0xffffffff); bodyadapter[2]=new tabmenu.menubodyadapter(this,new string[] { "工具1", "工具2", "工具3", "工具4" }, new int[] { r.drawable.menu_copy, r.drawable.menu_cut, r.drawable.menu_normalmode, r.drawable.menu_quit },13, 0xffffffff); tabmenu=new tabmenu(this, new titleclickevent(), new bodyclickevent(), titleadapter, 0x55123456,//tabmenu的背景颜色 r.style.popupanimation);//出现与消失的动画 tabmenu.update(); tabmenu.settitleselect(0); tabmenu.setbodyadapter(bodyadapter[0]); } class titleclickevent implements onitemclicklistener{ @override public void onitemclick(adapterview<?> arg0, view arg1, int arg2, long arg3) { seltitle=arg2; tabmenu.settitleselect(arg2); tabmenu.setbodyadapter(bodyadapter[arg2]); } } class bodyclickevent implements onitemclicklistener{ @override public void onitemclick(adapterview<?> arg0, view arg1, int arg2, long arg3) { tabmenu.setbodyselect(arg2,color.gray); string str="第"+string.valueof(seltitle)+"栏/n/r" +"第"+string.valueof(arg2)+"项"; toast.maketext(testtabmenu.this, str, 500).show(); } } @override /** * 创建menu */ public boolean oncreateoptionsmenu(menu menu) { menu.add("menu");// 必须创建一项 return super.oncreateoptionsmenu(menu); } @override /** * 拦截menu */ public boolean onmenuopened(int featureid, menu menu) { if (tabmenu != null) { if (tabmenu.isshowing()) tabmenu.dismiss(); else { tabmenu.showatlocation(findviewbyid(r.id.linearlayout01), gravity.bottom, 0, 0); } } return false;// 返回为true 则显示系统menu } }
感兴趣的读者可以自己动手测试一下本文所述实例,相信会对大家的android程序开发有一定帮助。