Android PopupWindow模拟Windows开始菜单显示消失效果
Android PopupWindow模拟Windows开始菜单显示消失效果
Android系统给我提供的菜单不尽人意,大多数情况下我们都是根据需求,重写系统的菜单,达到想要的效果,下面就用PopupWindow两种方式重写系统菜单效果。
Android PopupWindow模拟Windows开始菜单显示消失效果DEMO下载:
免费下载地址在 http://linux.bkjia.com/
用户名与密码都是www.bkjia.com
具体下载目录在 /pub/Android源码集锦/2011年/11月/Android PopupWindow模拟Windows开始菜单显示消失效果/
- package com.jacp.app;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.Gravity;
- import android.view.KeyEvent;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.View.OnKeyListener;
- import android.view.View.OnTouchListener;
- import android.view.WindowManager;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.LinearLayout;
- import android.widget.ListView;
- import android.widget.PopupWindow;
- public class PopupWindowActivity extends Activity implements OnClickListener {
- private PopupWindow mLeftMenu;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- // 注册按钮事件
- findViewById(R.id.left).setOnClickListener(this);
- findViewById(R.id.right).setOnClickListener(this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.left:
- showLeftMenu();
- break;
- case R.id.right:
- startActivity(new Intent(this, PopupWindowSecondActivity.class));
- break;
- }
- }
- /**
- * 显示菜单
- * @return 如果菜单显示则返回true,否则返回false
- */
- private boolean showLeftMenu() {
- if (hideLeftMenu())
- {
- return false;
- }
- LinearLayout leftLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.menu_list, null);
- // 当菜单出现时,最外层布局接受Touch事件
- leftLayout.setOnTouchListener(new OnTouchListener()
- {
- @Override
- public boolean onTouch(View v, MotionEvent event)
- {
- hideLeftMenu();
- return false;
- }
- });
- ListView list = (ListView) leftLayout.findViewById(R.id.item_list);
- String[] data = getResources().getStringArray(R.array.menu_item);
- int[] res = new int[data.length];
- for (int i = 0, length = data.length; i < length; i++)
- {
- res[i] = R.drawable.icon;
- }
- list.setAdapter(new PopupAdapter(this, data, res, R.layout.menu_item, R.id.item_image, R.id.item_text));
- list.setOnItemClickListener(new OnItemClickListener()
- {
- @Override
- public void onItemClick(AdapterView<?> parent, View view,
- int position, long id)
- {
- hideLeftMenu();
- }
- });
- // 当菜单出现时焦点会落在ListView上
- list.setOnKeyListener(new OnKeyListener()
- {
- @Override
- public boolean onKey(View v, int keyCode, KeyEvent event)
- {
- // 此方法会调两次,一次Down和一次Up
- // 所以此处要拦截
- if (event.getAction() == KeyEvent.ACTION_DOWN)
- {
- switch (keyCode)
- {
- case KeyEvent.KEYCODE_MENU:
- return hideLeftMenu();
- case KeyEvent.KEYCODE_BACK:
- return hideLeftMenu();
- }
- }
- return false;
- }
- });
- // 设置菜单属性
- mLeftMenu = new PopupWindow(leftLayout, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
- mLeftMenu.setWidth(150);
- // 设置菜单上是否可以聚焦
- mLeftMenu.setFocusable(true);
- // 当菜单出现时菜单以外的区域是否接受点击事件
- mLeftMenu.setOutsideTouchable(true);
- // 设置菜单显示的位置
- mLeftMenu.showAtLocation(leftLayout, Gravity.BOTTOM | Gravity.LEFT, 0, 80);
- return true;
- }
- /**
- * 隐藏菜单
- * @return 如果菜单隐藏则返回true,则否返回false
- */
- private boolean hideLeftMenu()
- {
- if (null != mLeftMenu && mLeftMenu.isShowing())
- {
- mLeftMenu.dismiss();
- mLeftMenu = null;
- return true;
- }
- return false;
- }
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event)
- {
- switch (keyCode)
- {
- case KeyEvent.KEYCODE_BACK:
- hideLeftMenu();
- break;
- case KeyEvent.KEYCODE_MENU:
- showLeftMenu();
- break;
- }
- return super.onKeyDown(keyCode, event);
- }
- }
其中有三点要注意:
1.PopupWindow的参数设置
- // 设置菜单上是否可以聚焦
- mLeftMenu.setFocusable(true);
- // 当菜单出现时菜单以外的区域是否接受点击事件
- mLeftMenu.setOutsideTouchable(true);
2.当PopupWindow显示时焦点会落在其中,所以监听事件的是它里面的View,如例中的Touch事件。按键事件是占整个View的ListView监听的。很奇怪的是不是里面的LinearLayout,如果高人知道,请在下面留言,小弟不甚感激。
3.最后一点是注意按键事件。例子中重写了Activity的OnKeyDown事件,而在ListView中的OnKey方法必须拦截KeyDown事件。如果不拦截菜单出现就会消失,因为OnKey方法会因Down和Up调用两次;如果拦截的是Up事件,情况也是一样的,因为当菜单没有出现按Menu键时,先执行Activity里面的onKeyDown事件,菜单出现。注意菜单出现是Down事件,那Up呢?正好当PopupWindow出现时,ListView继续执行事件,会执行OnKey事件,如果是拦截的Action是Up则会执行,所以整个事件会两个地方执行。有人说在Activity里面的OnKeyDown事件return true进行拦截不就行了,这样事件就不会执行到PopupWindow上面,这样想没有错,如果真的是那样,那按Back键后,整个Activity就不会退出。
以上是第一种方法。
|
评论暂时关闭