用过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"></textview> </linearlayout>
tabmenu的封装类tabmenu.java的源码如下:
package com.iaiai.activity;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;/** * * <p> * title: tabmenu.java * </p> * <p> * e-mail: [email protected] * </p> * <p> * qq: 176291935 * </p> * <p> * http: iaiai.iteye.com * </p> * <p> * create time: 2011-8-17 * </p> * * @author 丸子 * @version 0.0.1 */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.iaiai.activity;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;/** * * <p> * title: mainmenuview.java * </p> * <p> * e-mail: [email protected] * </p> * <p> * qq: 176291935 * </p> * <p> * http: iaiai.iteye.com * </p> * <p> * create time: 2011-8-17 * </p> * * @author 丸子 * @version 0.0.1 */public class mainmenuview 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(mainmenuview.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 }}