用过UCWEB-Android版的人都应该对其特殊的menu有印象,把menu做成Tab-Menu(支持分页的Menu),可以容纳比Android传统的menu更丰富的内容(Android的menu超过6项则缩略在[更多]里),本文参考网上的例子(作者:CoffeeCole,email:longkefan@foxmail.com),对例子进行简化以及封装,使其作为一个复合控件融入自己的framework。

       先来看看本文程序运行的效果:

 Android提高21篇之十八:自定义Menu(TabMenu)

       TabMenu本身就是一个PopupWindow,PopupWindow上面放了两个GridView,第一个GridView就是分页标签,位于PopupWindow的顶部,第二个GridView是菜单,位于PopupWindow的主体。为了实现PopupWindow的弹出/退出的动画效果,本文使用了以下代码:

       在工程的res文件夹里添加anim子目录,再新建文件popup_enter.xml:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">  
  3.         <translate android:fromYDelta="100%p" android:toYDelta="0" android:duration="1000" />  
  4.         <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="1000" />  
  5. </set>   

       新建文件popup_exit.xml:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android">  
  3.         <translate android:fromYDelta="0" android:toYDelta="100%p" android:duration="1000" />  
  4.         <alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:duration="1000" />  
  5. </set>   

       在工程的values文件夹里新建文件popup_animation.xml:

XML/HTML代码
  1. <?xml version="1.0" encoding="utf-8"?>    
  2. <resources>       
  3.     <style name="PopupAnimation" parent="android:Animation">  
  4.         <item name="android:windowEnterAnimation">@anim/popup_enter</item>    
  5.         <item name="android:windowExitAnimation">@anim/popup_exit</item>     
  6.     </style>    
  7. </resources>   

       main.xml的源码如下:

XML/HTML代码
  1. <linearlayout android:id="@+id/LinearLayout01"   
  2.         android:layout_width="fill_parent" android:layout_height="fill_parent"  
  3.         xmlns:android="http://schemas.android.com/apk/res/android">  
  4.         <textview android:id="@+id/TextView01" android:layout_height="wrap_content"   
  5.                 android:layout_width="fill_parent" android:text="扩展Menu----hellogv">  

        TabMenu的封装类TabMenu.java的源码如下:

Java代码
  1. package com.testTabMenu;  
  2. import android.content.Context;  
  3. import android.graphics.Color;  
  4. import android.graphics.drawable.ColorDrawable;  
  5. import android.view.Gravity;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8. import android.widget.BaseAdapter;  
  9. import android.widget.GridView;  
  10. import android.widget.ImageView;  
  11. import android.widget.LinearLayout;  
  12. import android.widget.PopupWindow;  
  13. import android.widget.TextView;  
  14. import android.widget.AdapterView.OnItemClickListener;  
  15. import android.widget.LinearLayout.LayoutParams;  
  16. public class TabMenu extends PopupWindow{  
  17.         private GridView gvBody, gvTitle;  
  18.         private LinearLayout mLayout;  
  19.         private MenuTitleAdapter titleAdapter;  
  20.         public TabMenu(Context context,OnItemClickListener titleClick,OnItemClickListener bodyClick,  
  21.                         MenuTitleAdapter titleAdapter,int colorBgTabMenu,int aniTabMenu){  
  22.                 super(context);  
  23.                   
  24.                 mLayout = new LinearLayout(context);  
  25.                 mLayout.setOrientation(LinearLayout.VERTICAL);  
  26.                 //标题选项栏  
  27.                 gvTitle = new GridView(context);  
  28.                 gvTitle.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));  
  29.                 gvTitle.setNumColumns(titleAdapter.getCount());  
  30.                 gvTitle.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);  
  31.                 gvTitle.setVerticalSpacing(1);  
  32.                 gvTitle.setHorizontalSpacing(1);  
  33.                 gvTitle.setGravity(Gravity.CENTER);  
  34.                 gvTitle.setOnItemClickListener(titleClick);  
  35.                 gvTitle.setAdapter(titleAdapter);  
  36.                 gvTitle.setSelector(new ColorDrawable(Color.TRANSPARENT));//选中的时候为透明色  
  37.                 this.titleAdapter=titleAdapter;  
  38.                 //子选项栏  
  39.                 gvBody = new GridView(context);  
  40.                 gvBody.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));  
  41.                 gvBody.setSelector(new ColorDrawable(Color.TRANSPARENT));//选中的时候为透明色  
  42.                 gvBody.setNumColumns(4);  
  43.                 gvBody.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);  
  44.                 gvBody.setVerticalSpacing(10);  
  45.                 gvBody.setHorizontalSpacing(10);  
  46.                 gvBody.setPadding(10101010);  
  47.                 gvBody.setGravity(Gravity.CENTER);  
  48.                 gvBody.setOnItemClickListener(bodyClick);  
  49.                 mLayout.addView(gvTitle);  
  50.                 mLayout.addView(gvBody);  
  51.                   
  52.                 //设置默认项  
  53.                 this.setContentView(mLayout);  
  54.                 this.setWidth(LayoutParams.FILL_PARENT);  
  55.                 this.setHeight(LayoutParams.WRAP_CONTENT);  
  56.                 this.setBackgroundDrawable(new ColorDrawable(colorBgTabMenu));// 设置TabMenu菜单背景  
  57.                 this.setAnimationStyle(aniTabMenu);  
  58.                 this.setFocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应  
  59.         }  
  60.           
  61.           
  62.         public void SetTitleSelect(int index)  
  63.         {  
  64.                 gvTitle.setSelection(index);  
  65.                 this.titleAdapter.SetFocus(index);  
  66.         }  
  67.           
  68.         public void SetBodySelect(int index,int colorSelBody)  
  69.         {  
  70.                 int count=gvBody.getChildCount();  
  71.                 for(int i=0;i<count;i++)  
  72.                 {  
  73.                         if(i!=index)  
  74.                                 ((LinearLayout)gvBody.getChildAt(i)).setBackgroundColor(Color.TRANSPARENT);  
  75.                 }  
  76.                 ((LinearLayout)gvBody.getChildAt(index)).setBackgroundColor(colorSelBody);  
  77.         }  
  78.           
  79.         public void SetBodyAdapter(MenuBodyAdapter bodyAdapter)  
  80.         {  
  81.                 gvBody.setAdapter(bodyAdapter);  
  82.         }  
  83.           
  84.         /** 
  85.          * 自定义Adapter,TabMenu的每个分页的主体 
  86.          *  
  87.          */  
  88.         static public class MenuBodyAdapter extends BaseAdapter {  
  89.                 private Context mContext;  
  90.                 private int fontColor,fontSize;  
  91.                 private String[] texts;  
  92.                 private int[] resID;  
  93.                 /** 
  94.                  * 设置TabMenu的分页主体 
  95.                  * @param context 调用方的上下文 
  96.                  * @param texts 按钮集合的字符串数组 
  97.                  * @param resID 按钮集合的图标资源数组 
  98.                  * @param fontSize 按钮字体大小 
  99.                  * @param color 按钮字体颜色 
  100.                  */  
  101.                 public MenuBodyAdapter(Context context, String[] texts,int[] resID, int fontSize,int fontColor)   
  102.                 {  
  103.                         this.mContext = context;  
  104.                         this.fontColor = fontColor;  
  105.                         this.texts = texts;  
  106.                         this.fontSize=fontSize;  
  107.                         this.resID=resID;  
  108.                 }  
  109.                 public int getCount() {  
  110.                         return texts.length;  
  111.                 }  
  112.                 public Object getItem(int position) {  
  113.                           
  114.                         return makeMenyBody(position);  
  115.                 }  
  116.                 public long getItemId(int position) {  
  117.                         return position;  
  118.                 }  
  119.                   
  120.                 private LinearLayout makeMenyBody(int position)  
  121.                 {  
  122.                         LinearLayout result=new LinearLayout(this.mContext);  
  123.                         result.setOrientation(LinearLayout.VERTICAL);  
  124.                         result.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);          
  125.                         result.setPadding(10101010);  
  126.                           
  127.                         TextView text = new TextView(this.mContext);  
  128.                         text.setText(texts[position]);  
  129.                         text.setTextSize(fontSize);  
  130.                         text.setTextColor(fontColor);  
  131.                         text.setGravity(Gravity.CENTER);  
  132.                         text.setPadding(5555);  
  133.                         ImageView img=new ImageView(this.mContext);  
  134.                         img.setBackgroundResource(resID[position]);  
  135.                         result.addView(img,new LinearLayout.LayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT)));  
  136.                         result.addView(text);  
  137.                         return result;  
  138.                 }  
  139.                   
  140.                 public View getView(int position, View convertView, ViewGroup parent) {  
  141.                         return makeMenyBody(position);  
  142.                 }  
  143.         }  
  144.           
  145.           
  146.         /** 
  147.          * 自定义Adapter,TabMenu的分页标签部分 
  148.          *  
  149.          */  
  150.         static public class MenuTitleAdapter extends BaseAdapter {  
  151.                 private Context mContext;  
  152.         private int fontColor,unselcolor,selcolor;  
  153.         private TextView[] title;  
  154.         /** 
  155.          * 设置TabMenu的title 
  156.          * @param context 调用方的上下文 
  157.          * @param titles 分页标签的字符串数组 
  158.          * @param fontSize 字体大小 
  159.          * @param fontcolor 字体颜色 
  160.          * @param unselcolor 未选中项的背景色 
  161.          * @param selcolor 选中项的背景色 
  162.          */  
  163.         public MenuTitleAdapter(Context context, String[] titles, int fontSize,  
  164.                 int fontcolor,int unselcolor,int selcolor) {  
  165.             this.mContext = context;  
  166.             this.fontColor = fontcolor;  
  167.             this.unselcolor = unselcolor;  
  168.             this.selcolor=selcolor;  
  169.             this.title = new TextView[titles.length];  
  170.             for (int i = 0; i < titles.length; i++) {  
  171.                 title[i] = new TextView(mContext);  
  172.                 title[i].setText(titles[i]);  
  173.                 title[i].setTextSize(fontSize);  
  174.                 title[i].setTextColor(fontColor);  
  175.                 title[i].setGravity(Gravity.CENTER);  
  176.                 title[i].setPadding(10101010);  
  177.             }  
  178.         }  
  179.         public int getCount() {  
  180.             return title.length;  
  181.         }  
  182.         public Object getItem(int position) {  
  183.             return title[position];  
  184.         }  
  185.         public long getItemId(int position) {  
  186.             return title[position].getId();  
  187.         }  
  188.         /** 
  189.          * 设置选中的效果 
  190.          */  
  191.         private void SetFocus(int index)  
  192.         {  
  193.                 for(int i=0;i<title.length;i++)  
  194.                 {  
  195.                         if(i!=index)  
  196.                         {  
  197.                                 title[i].setBackgroundDrawable(new ColorDrawable(unselcolor));//设置没选中的颜色  
  198.                     title[i].setTextColor(fontColor);//设置没选中项的字体颜色  
  199.                         }  
  200.                 }  
  201.                 title[index].setBackgroundColor(0x00);//设置选中项的颜色  
  202.             title[index].setTextColor(selcolor);//设置选中项的字体颜色  
  203.         }  
  204.           
  205.         public View getView(int position, View convertView, ViewGroup parent) {  
  206.             View v;  
  207.             if (convertView == null) {  
  208.                 v = title[position];  
  209.             } else {  
  210.                 v = convertView;  
  211.             }  
  212.             return v;  
  213.         }  
  214.         }  
  215. }  

       testTabMenu介绍了数据的定义以及TabMenu的使用,源码如下:

Java代码
  1. package com.testTabMenu;  
  2. import android.app.Activity;  
  3. import android.graphics.Color;  
  4. import android.os.Bundle;  
  5. import android.view.Gravity;  
  6. import android.view.Menu;  
  7. import android.view.View;  
  8. import android.widget.AdapterView;  
  9. import android.widget.AdapterView.OnItemClickListener;  
  10. import android.widget.Toast;  
  11. public class testTabMenu extends Activity {  
  12.         TabMenu.MenuBodyAdapter []bodyAdapter=new TabMenu.MenuBodyAdapter[3];  
  13.         TabMenu.MenuTitleAdapter titleAdapter;  
  14.         TabMenu tabMenu;  
  15.         int selTitle=0;  
  16.         @Override  
  17.         public void onCreate(Bundle savedInstanceState) {  
  18.                 super.onCreate(savedInstanceState);  
  19.                 setContentView(R.layout.main);  
  20.                 //设置分页栏的标题  
  21.                 titleAdapter = new TabMenu.MenuTitleAdapter(thisnew String[] { "常用",  
  22.                                 "设置""工具" }, 160xFF222222,Color.LTGRAY,Color.WHITE);  
  23.                 //定义每项分页栏的内容  
  24.                 bodyAdapter[0]=new TabMenu.MenuBodyAdapter(this,new String[] { "常用1""常用2", },   
  25.                                  new int[] { R.drawable.menu_test,  
  26.                                 R.drawable.menu_bookmark},130xFFFFFFFF);  
  27.                    
  28.                 bodyAdapter[1]=new TabMenu.MenuBodyAdapter(this,new String[] { "设置1""设置2",  
  29.                                         "设置3"}, new int[] { R.drawable.menu_edit,  
  30.                                         R.drawable.menu_delete, R.drawable.menu_fullscreen},130xFFFFFFFF);  
  31.                    
  32.                 bodyAdapter[2]=new TabMenu.MenuBodyAdapter(this,new String[] { "工具1""工具2",  
  33.                                         "工具3""工具4" }, new int[] { R.drawable.menu_copy,  
  34.                                         R.drawable.menu_cut, R.drawable.menu_normalmode,  
  35.                                         R.drawable.menu_quit },130xFFFFFFFF);  
  36.                    
  37.                    
  38.                 tabMenu=new TabMenu(this,  
  39.                                  new TitleClickEvent(),  
  40.                                  new BodyClickEvent(),  
  41.                                  titleAdapter,  
  42.                                  0x55123456,//TabMenu的背景颜色  
  43.                                  R.style.PopupAnimation);//出现与消失的动画  
  44.                    
  45.                  tabMenu.update();  
  46.                  tabMenu.SetTitleSelect(0);  
  47.                  tabMenu.SetBodyAdapter(bodyAdapter[0]);  
  48.         }  
  49.           
  50.         class TitleClickEvent implements OnItemClickListener{  
  51.                 @Override  
  52.                 public void onItemClick(AdapterView arg0, View arg1, int arg2,  
  53.                                 long arg3) {  
  54.                         selTitle=arg2;  
  55.                         tabMenu.SetTitleSelect(arg2);  
  56.                         tabMenu.SetBodyAdapter(bodyAdapter[arg2]);  
  57.                 }  
  58.         }  
  59.           
  60.         class BodyClickEvent implements OnItemClickListener{  
  61.                 @Override  
  62.                 public void onItemClick(AdapterView arg0, View arg1, int arg2,  
  63.                                 long arg3) {  
  64.                         tabMenu.SetBodySelect(arg2,Color.GRAY);  
  65.                         String str="第"+String.valueOf(selTitle)+"栏/n/r"  
  66.                         +"第"+String.valueOf(arg2)+"项";  
  67.                         Toast.makeText(testTabMenu.this, str, 500).show();  
  68.                           
  69.                 }  
  70.                   
  71.         }  
  72.         @Override  
  73.         /** 
  74.          * 创建MENU 
  75.          */  
  76.         public boolean onCreateOptionsMenu(Menu menu) {  
  77.                 menu.add("menu");// 必须创建一项  
  78.                 return super.onCreateOptionsMenu(menu);  
  79.         }  
  80.         @Override  
  81.         /** 
  82.          * 拦截MENU 
  83.          */  
  84.         public boolean onMenuOpened(int featureId, Menu menu) {  
  85.                 if (tabMenu != null) {  
  86.                         if (tabMenu.isShowing())  
  87.                                 tabMenu.dismiss();  
  88.                         else {  
  89.                                 tabMenu.showAtLocation(findViewById(R.id.LinearLayout01),  
  90.                                                 Gravity.BOTTOM, 00);  
  91.                         }  
  92.                 }  
  93.                 return false;// 返回为true 则显示系统menu  
  94.         }  
  95.           
  96. }  
本文发布:Android开发网
本文地址:http://www.jizhuomi.com/android/course/509.html
2015年12月7日
发布:鸡啄米 分类:Android开发教程 浏览: 评论:0