【Android学习】使用popupWindow模拟menu

刚开始学习android,下了个apk,发现它的menu很帅气,而android自带的menu非常丑,特别是4.0之后,menu变成了垂直的list,更丑,于是花了点时间模仿了一个

效果图如下:

源码下载地址:http://download.csdn.net/detail/cbxjj/7513471

点击更多按钮来进行换页操作

代码如下:

1.Activity

public class SlideActivity extends Activity {

	private MyMenu_1 myMenu;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	protected void onResume() {
		super.onResume();
		myMenu = new MyMenu_1(SlideActivity.this);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_MENU:
			if (myMenu.isShowing()) {
				myMenu.dismiss();
			} else {
				//将弹出menu显示到底部
				myMenu.showAtLocation(findViewById(R.id.main_layout),
						Gravity.BOTTOM, 0, 0);
			}
			break;

		case KeyEvent.KEYCODE_BACK:
			myMenu.dismiss();
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
}

2.MyMenu_1

public class MyMenu_1 extends PopupWindow {

	private static int menuSize = 1;
	private Context mContext;
	private RelativeLayout mLinearLayout;
	private GridView mGridView;
	private String[] titles = { "添加收藏夹", "查找短信", "新增短信", "定时任务", "发送报告", "更多", "设置", "关于", "帮助", "反馈", "返回" };
	private int[] images = { R.drawable.icon_menu_favorite,
			R.drawable.icon_menu_search, R.drawable.icon_menu_add,R.drawable.icon_menu_schedule_task,
			R.drawable.icon_menu_view_sent_status,R.drawable.icon_menu_more,R.drawable.icon_menu_setting,
			R.drawable.icon_menu_info,R.drawable.icon_menu_help,R.drawable.icon_menu_feedback,R.drawable.icon_menu_back};
	private List<HashMap<String,Object>> itemList = new ArrayList<HashMap<String,Object>>();
	private SimpleAdapter adapter;
	private LayoutInflater inflater;
	
	public MyMenu_1(Context context){
		super(context);
		
		mContext = context;
		
		initDatas();
		initViewInWin();

		this.setWidth(LayoutParams.FILL_PARENT);
		this.setHeight(LayoutParams.WRAP_CONTENT);
		//这里用上了我们在popupWindow中定义的animation了
		this.setAnimationStyle(android.R.style.Animation_Dialog);  
		this.setContentView(mLinearLayout); 
		ColorDrawable dw = new ColorDrawable(-00000);
   	    this.setBackgroundDrawable(dw);
		/*设置触摸外面时消失*/  
		this.setOutsideTouchable(true);
		
		//这里要设置为true,否则将无法响应popupWindow中控件的点击事件。
		this.setFocusable(true);
//		this.update();  
		this.setOnDismissListener(new OnDismissListener() {
			
			@Override
			public void onDismiss() {
				menuSize = 1;
				itemList.clear();
				initDatas();
			}
		});
	}
	
	/**
	 * 初始化popupWindow中的内容
	 */
	public void initViewInWin(){
		inflater = (LayoutInflater)mContext.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
		mLinearLayout = (RelativeLayout)inflater.inflate(R.layout.slide_menu, null);
		
		//这里需要设置成可以获取焦点,否则无法响应OnKey事件
		mLinearLayout.setFocusable(true);
		mLinearLayout.setFocusableInTouchMode(true);
		
		//在这里设置,即可实现关闭的效果。
		mLinearLayout.setOnKeyListener(new LayouOnKeyEvent());
		mGridView = (GridView)mLinearLayout.findViewById(R.id.menu_gridView);
		//设置item点击响应的时间
		mGridView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				if(menuSize == 1 && position == 5){
					MyMenu_1.this.dismiss();
					menuSize = 2;
					itemList.clear();
					initDatas();
					MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
				}				
				if(menuSize == 2 && position == 4){
					MyMenu_1.this.dismiss();
					MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
				}				
			}
		});
		mGridView.setAdapter(adapter);
		
	}
	
	/**
	 * 初始化数据内容
	 */
	public void initDatas(){
		int forStart = 0;
		int forEnd = 5;
		if(menuSize==1){
			forStart = 0;
			forEnd = 5;
		}
		if(menuSize==2){
			forStart = 6;
			forEnd = 6*2-1>titles.length-1?titles.length-1:6*2-1;
		}
		for(int i = forStart; i<=forEnd; i++){
			HashMap<String,Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList.add(map);
		}
		
		adapter = new SimpleAdapter(mContext, itemList, R.layout.my_menu_item,
				new String[]{"image","title"}, new int[]{R.id.item_image,R.id.item_title});
	}
	
	class LayouOnKeyEvent implements OnKeyListener{

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			menuSize = 1;
			itemList.clear();
			initDatas();
			MyMenu_1.this.showAtLocation(mGridView.findViewById(R.id.menu_item_layout), Gravity.BOTTOM, 0, 0);
			//判断事件为menu按钮按下时,将popupWindow关闭
			if(event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_MENU){
				if(MyMenu_1.this.isShowing()){
					MyMenu_1.this.dismiss();
				}
			}
			return true;
		}
		
	}
	
	
}

3.slide_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/gdi_arrow_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/gdi_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/gdi_arrow_up"
        android:background="@drawable/quick_action_top_frame" />

    <GridView
        android:id="@+id/menu_gridView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:fadingEdgeLength="0.0dip"
        android:background="@drawable/quick_action_grid_bg"
        android:horizontalSpacing="10dip"
        android:listSelector="@drawable/quick_action_grid_selector"
        android:numColumns="3"
        android:padding="10dip"
        android:stretchMode="columnWidth"
        android:layout_below="@id/gdi_header"
        android:verticalSpacing="10dip" >
    </GridView>

    <FrameLayout
        android:id="@+id/gdi_footer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/menu_gridView"
        android:background="@drawable/quick_action_grid_bottom_frame" />

    <ImageView
        android:id="@+id/gdi_arrow_down"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/gdi_footer" />

</RelativeLayout>

4.my_menu_item.xml

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/menu_item_layout"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
	<ImageView
	    android:id="@+id/item_image"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:focusable="false"
	    android:layout_centerHorizontal="true"
	    />
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:focusable="false"
        android:layout_below="@id/item_image"
        android:layout_centerHorizontal="true"
        />
</RelativeLayout>

很顺利的做出来了。效果和效果图一致,基本和apk里面的差不多,但是我觉得分页操作不是很方便,觉得android的滚屏左右滑动效果不错,

用到这个上面也还不错,于是开始查资料,发现viewPager和viewgroup都可以做,先用viewgroup做了一晚上,各种bug,快崩溃了。

于是换viewPager,中间虽然出了很多次问题,但是还是做出来了,效果如下:



直接上代码:

1.PopupMenuActivity

public class PopupMenuActivity extends Activity {

	private MyMenu myMenu;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}

	@Override
	protected void onResume() {
		super.onResume();
		myMenu = new MyMenu(PopupMenuActivity.this);
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_MENU:
			if (myMenu.isShowing()) {
				myMenu.dismiss();
			} else {
				myMenu.showAtLocation(findViewById(R.id.main_layout),
						Gravity.BOTTOM, 0, 0);
			}
			break;

		case KeyEvent.KEYCODE_BACK:
			myMenu.dismiss();
			break;
		}
		return super.onKeyDown(keyCode, event);
	}
}

2.Mymenu.java

public class MyMenu extends PopupWindow {

	private Context mContext;
	private LinearLayout mLinearLayout;
	private LinearLayout pointLLayout;
	private GridView mGridView1;
	private GridView mGridView2;
	private String[] titles = { "添加收藏夹", "查找短信", "新增短信", "定时任务", "发送报告", "更多",
			"设置", "关于", "帮助", "反馈", "返回" };
	private int[] images = { R.drawable.icon_menu_favorite,
			R.drawable.icon_menu_search, R.drawable.icon_menu_add,
			R.drawable.icon_menu_schedule_task,
			R.drawable.icon_menu_view_sent_status, R.drawable.icon_menu_more,
			R.drawable.icon_menu_setting, R.drawable.icon_menu_info,
			R.drawable.icon_menu_help, R.drawable.icon_menu_feedback,
			R.drawable.icon_menu_back };
	private List<HashMap<String, Object>> itemList1 = new ArrayList<HashMap<String, Object>>();
	private List<HashMap<String, Object>> itemList2 = new ArrayList<HashMap<String, Object>>();
	private MySimpleAdapter adapter1;
	private MySimpleAdapter adapter2;
	private LayoutInflater inflater;

	private ImageView[] imgs;
	private int count;
	private int currentItem;

	private MyViewPagerAdapter adapter;
	private MyViewPager viewPager;
	private ArrayList<GridView> array = new ArrayList<GridView>();

	public MyMenu(Context context) {
		super(context);

		mContext = context;

		initDatas();
		initViewInWin();

		this.setWidth(LayoutParams.FILL_PARENT);
		this.setHeight(LayoutParams.WRAP_CONTENT);
		// 这里用上了我们在popupWindow中定义的animation了
		this.setAnimationStyle(android.R.style.Animation_Dialog);
		this.setContentView(mLinearLayout);
		//必须设置背景色为透明,不然弹出窗口宽度不全屏
		ColorDrawable dw = new ColorDrawable(-00000);
		this.setBackgroundDrawable(dw);
		/* 设置触摸外面时消失 */
		this.setOutsideTouchable(true);

		// 这里要设置为true,否则将无法响应popupWindow中控件的点击事件。
		this.setFocusable(true);
		this.update();
		this.setOnDismissListener(new OnDismissListener() {

			@Override
			public void onDismiss() {
				itemList1.clear();
				itemList2.clear();
				initDatas();
			}
		});

		pointLLayout = (LinearLayout) mLinearLayout.findViewById(R.id.llayout);
		viewPager = (MyViewPager) mLinearLayout.findViewById(R.id.myviewpager);
		count = viewPager.getChildCount();
		imgs = new ImageView[count];
		for (int i = 0; i < count; i++) {
			imgs[i] = (ImageView) pointLLayout.getChildAt(i);
			imgs[i].setEnabled(true);
			imgs[i].setTag(i);
		}
		currentItem = 0;
		imgs[currentItem].setEnabled(false);
		viewPager.setOnPageChangeListener(new OnPageChangeListener() {

			@Override
			public void onPageSelected(int point) {
				setcurrentPoint(point);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int point) {
			}
		});

		adapter = new MyViewPagerAdapter(mContext, array);
		viewPager.setAdapter(adapter);
	}

	protected void setcurrentPoint(int position) {
		if (position < 0 || position > count - 1 || currentItem == position) {
			return;
		}
		imgs[currentItem].setEnabled(true);
		imgs[position].setEnabled(false);
		currentItem = position;
	}

	public void initViewInWin() {
		inflater = (LayoutInflater) mContext
				.getSystemService(mContext.LAYOUT_INFLATER_SERVICE);
		mLinearLayout = (LinearLayout) inflater.inflate(R.layout.my_menu, null);
		mLinearLayout.setFocusable(true);
		mLinearLayout.setFocusableInTouchMode(true);

		mLinearLayout.setOnKeyListener(new LayouOnKeyEvent());
		mGridView1 = (GridView) mLinearLayout.findViewById(R.id.menu_gridView1);
		mGridView2 = (GridView) mLinearLayout.findViewById(R.id.menu_gridView2);

		mGridView1.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				System.out.println("点击第一个第" + position + "个按钮");
			}
		});
		mGridView1.setAdapter(adapter1);
		mGridView2.setAdapter(adapter2);

		array.add(mGridView1);
		array.add(mGridView2);
	}

	public void initDatas() {
		int forStart = 0;
		int forEnd = 5;
		for (int i = forStart; i <= forEnd; i++) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList1.add(map);
		}

		adapter1 = new MySimpleAdapter(mContext, itemList1,
				R.layout.my_menu_item, new String[] { "image", "title" },
				new int[] { R.id.item_image, R.id.item_title });

		forStart = 6;
		forEnd = 6 * 2 - 1 > titles.length - 1 ? titles.length - 1 : 6 * 2 - 1;

		for (int i = forStart; i <= forEnd; i++) {
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("image", images[i]);
			map.put("title", titles[i]);
			itemList2.add(map);
		}
		adapter2 = new MySimpleAdapter(mContext, itemList2,
				R.layout.my_menu_item, new String[] { "image", "title" },
				new int[] { R.id.item_image, R.id.item_title });
	}

	class LayouOnKeyEvent implements OnKeyListener {

		@Override
		public boolean onKey(View v, int keyCode, KeyEvent event) {
			itemList1.clear();
			itemList2.clear();
			initDatas();
			MyMenu.this.showAtLocation(
					mLinearLayout.findViewById(R.id.menu_item_layout),
					Gravity.BOTTOM, 0, 0);

			// 判断事件为menu按钮按下时,将popupWindow关闭
			if (event.getAction() == KeyEvent.ACTION_DOWN
					&& keyCode == KeyEvent.KEYCODE_MENU) {
				if (MyMenu.this.isShowing()) {
					MyMenu.this.dismiss();
				}
			}
			return true;
		}

	}

}

3.MySimpleAdapter 不用SimpleAdapter 而是自己写一个,因为报了一个The observer is null.查了下问题,应该是关闭window的时候setAdapter的时候unregisterDataSetObserver没判断mDataSetObserver是否为空,据说是因为嵌套控件导致,这里直接判断下就完了

public class MySimpleAdapter extends SimpleAdapter {

	public MySimpleAdapter(Context context,
			List<? extends Map<String, ?>> data, int resource, String[] from,
			int[] to) {
		super(context, data, resource, from, to);
	}
	
	@Override
	public void unregisterDataSetObserver(DataSetObserver observer) {
		if (observer != null) {
			super.unregisterDataSetObserver(observer);
		}
	}
	
}

4.MyViewPager 继承了android.support.v4.view.ViewPager,因为这个控件高度自动全屏了 设置wrap_content也没用,这里集成了ViewPager重新设置了以下高度

public class MyViewPager extends ViewPager {

	public MyViewPager(Context context) {
		super(context);
	}

	public MyViewPager(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

		int height = 0;
		for (int i = 0; i < getChildCount(); i++) {
			View child = getChildAt(i);
			child.measure(widthMeasureSpec,
					MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
			int h = child.getMeasuredHeight();
			if (h > height)
				height = h;
		}

		heightMeasureSpec = MeasureSpec.makeMeasureSpec(height*2,
				MeasureSpec.EXACTLY);

		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
}

5.MyViewPagerAdapter重写了PagerAdapter

public class MyViewPagerAdapter extends PagerAdapter {
	private List<GridView> array;

	/**
	 * 供外部调用(new)的方法
	 * 
	 * @param context
	 *            上下�?
	 * @param imageViews
	 *            添加的序列对�?
	 */
	public MyViewPagerAdapter(Context context, List<GridView> array) {
		this.array = array;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return array.size();
	}

	@Override
	public boolean isViewFromObject(View arg0, Object arg1) {
		// TODO Auto-generated method stub
		return arg0 == arg1;
	}

	@Override
	public Object instantiateItem(View arg0, int arg1) {
		((ViewPager) arg0).addView(array.get(arg1));
		return array.get(arg1);
	}

	@Override
	public void destroyItem(View arg0, int arg1, Object arg2) {
		((ViewPager) arg0).removeView((View) arg2);
	}

	@Override
	public void unregisterDataSetObserver(DataSetObserver observer) {
		if (observer != null) {
			super.unregisterDataSetObserver(observer);
		}
	}
}

6.my_menu.xml 注意这里最外层必须用LinearLayout,否则会报一个android.support.v4.view.ViewPager canot be cast to。。。。

转换异常,用RelativeLayout狂报错。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" 
    android:orientation="vertical">

    <ImageView
        android:id="@+id/gdi_arrow_up"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <FrameLayout
        android:id="@+id/gdi_header"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/quick_action_top_frame" />
    
   <RelativeLayout   
	  	android:layout_width="fill_parent"    
	  	android:layout_height="wrap_content"
	  	android:id="@+id/renlayout"
        android:background="@drawable/quick_action_grid_bg"
	  	>
    <com.cbxjj.myplugins.MyViewPager
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:scaleType="fitXY"
        android:layout_gravity="center"
        android:id="@+id/myviewpager">

            <GridView
                android:id="@+id/menu_gridView1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:fadingEdgeLength="0.0dip"
                android:gravity="center"
                android:horizontalSpacing="10dip"
                android:listSelector="@drawable/quick_action_grid_selector"
                android:numColumns="3"
                android:padding="10dip"
                android:stretchMode="columnWidth"
                android:verticalSpacing="10dip" >
            </GridView>
            <GridView
                android:id="@+id/menu_gridView2"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:fadingEdgeLength="0.0dip"
                android:gravity="center"
                android:horizontalSpacing="10dip"
                android:listSelector="@drawable/quick_action_grid_selector"
                android:numColumns="3"
                android:padding="10dip"
                android:stretchMode="columnWidth"
                android:verticalSpacing="10dip" >
            </GridView>
   </com.cbxjj.myplugins.MyViewPager>
	<LinearLayout 
    	android:orientation="horizontal" 
    	android:id="@+id/llayout" 
    	android:layout_width="fill_parent" 
    	android:layout_height="15dp" 
        android:layout_below="@id/myviewpager"
    	android:layout_centerHorizontal="true"
    	android:gravity="center"
    	android:visibility="visible">
      
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:clickable="true"
            android:padding="5.0dip"
            android:src="@drawable/page_indicator_bg" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:clickable="true"
            android:padding="5.0dip"
            android:src="@drawable/page_indicator_bg" />
</LinearLayout>
    </RelativeLayout>
    <FrameLayout
        android:id="@+id/gdi_footer"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/quick_action_grid_bottom_frame" >
        </FrameLayout>
</LinearLayout>
以上。

源码下载地址: http://download.csdn.net/detail/cbxjj/7513471



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值