`
iaiai
  • 浏览: 2204289 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android 自定义PopupWindow实现的Menu(TabMenu)

 
阅读更多
用过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: 176291935@qq.com
 * </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: 176291935@qq.com
 * </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
	}
}
  • 大小: 21.5 KB
分享到:
评论

相关推荐

    android自定义菜单

    本篇文章将深入探讨如何在Android中实现一个自定义菜单,包括带有图标的Tab-Menu,并支持分页功能。 首先,我们从“自定义菜单”的概念入手。在Android系统中,菜单通常用于在特定时刻显示一组操作选项,如在应用...

    android下拉列表样式筛选组件,仿美团popwindow实现

    本文将详细介绍如何在Android中实现一个仿美团PopWindow的下拉筛选组件,以及如何通过点击Tab属性来显示筛选条件。 首先,我们来理解`PopWindow`。`PopWindow`是Android中的一个非常实用的组件,它可以在屏幕上的...

    android 自定義menu加上tabhost

    点击屏幕中间可以自动弹出,按menu键可以自动弹出,相再点击自动隐藏,只要在TabMenu类中添加以下方法就行mLayout.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, ...

    android popwindow实现左侧弹出菜单层 .zip

    在Android开发中,`PopupWindow` 是一个非常实用的组件,它允许我们创建浮动窗口,可以用来实现各种自定义的交互效果,如下拉菜单、弹出对话框等。在这个"android popwindow实现左侧弹出菜单层 .zip"中,我们将重点...

    Android实现扩展Menu的方法

    本篇将介绍如何在Android中实现一个可扩展的Menu,主要通过PopupWindow结合自定义Adapter来完成。 首先,我们创建一个名为`TabMenu`的类,继承自`PopupWindow`。`PopupWindow`是一个可以浮动在屏幕任意位置的窗口,...

    android开发资料大全

    Android自定义Gallery,实现CoverFlow效果 高仿网易新闻顶部滑动条效果 Android源码之动态壁纸引擎 动态桌面实现 android控件的抖动效果 很漂亮的ListView android 图像处理滤镜 照亮边缘特效 无闪烁启动画面 ...

    Android的一些最基本的知识

    在Android开发中,掌握一些基础知识是非常重要的,这些知识包括了OptionsMenu、PopupWindow、通知系统、Fragment管理和用户交互等。下面将详细阐述这些概念。 首先,OptionsMenu是Android应用中常见的右上角三个点...

    筛选菜单库DropDownMenu­_.zip

    如果使用自定义样式只需传递customview即可以下为原始特性:支持多级菜单你可以完全自定义你的菜单样式,我这里只是封装了一些实用的方法,Tab的切换效果,菜单显示隐藏效果等并非用popupWindow实现,无卡顿软件截图...

    疯狂Android讲义源码

     5.3 使用Intent创建Tab页面 211  5.4 本章小结 212  第6章 Android应用的资源 213  6.1 资源的类型及存储方式 214  6.1.1 资源的类型以及存储方式 214  6.1.2 使用资源 216  6.2 使用字符串、颜色、  尺寸...

    Android典型技术模块开发详解

    9.6 动画组件——PopupWindow 9.7 自定义View 9.8 控件扩展(表格) 9.8.1 设计实体类 9.8.2 基于ListView的实现 9.9 本章小结 第10章 数据存储 10.1 File(文件) 10.1.1 java.io包的方法 10.1.2 openFileInput和...

Global site tag (gtag.js) - Google Analytics