Android PopupWindow模拟Windows开始菜单显示消失效果


Android系统给我提供的菜单不尽人意,大多数情况下我们都是根据需求,重写系统的菜单,达到想要的效果,下面就用PopupWindow两种方式重写系统菜单效果。

Android PopupWindow模拟Windows开始菜单显示消失效果DEMO下载:

免费下载地址在 http://linux.bkjia.com/

用户名与密码都是www.bkjia.com

具体下载目录在 /pub/Android源码集锦/2011年/11月/Android PopupWindow模拟Windows开始菜单显示消失效果/

  1. package com.jacp.app;  
  2.   
  3. import android.app.Activity;  
  4. import android.content.Intent;  
  5. import android.os.Bundle;  
  6. import android.view.Gravity;  
  7. import android.view.KeyEvent;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.view.View.OnKeyListener;  
  12. import android.view.View.OnTouchListener;  
  13. import android.view.WindowManager;  
  14. import android.widget.AdapterView;  
  15. import android.widget.AdapterView.OnItemClickListener;  
  16. import android.widget.LinearLayout;  
  17. import android.widget.ListView;  
  18. import android.widget.PopupWindow;  
  19.   
  20. public class PopupWindowActivity extends Activity implements OnClickListener {  
  21.       
  22.     private PopupWindow mLeftMenu;  
  23.       
  24.     @Override  
  25.     public void onCreate(Bundle savedInstanceState) {  
  26.         super.onCreate(savedInstanceState);  
  27.         setContentView(R.layout.main);  
  28.   
  29.         // 注册按钮事件   
  30.         findViewById(R.id.left).setOnClickListener(this);  
  31.         findViewById(R.id.right).setOnClickListener(this);  
  32.     }  
  33.   
  34.     @Override  
  35.     public void onClick(View v) {  
  36.         switch (v.getId()) {  
  37.         case R.id.left:  
  38.             showLeftMenu();  
  39.             break;  
  40.         case R.id.right:  
  41.             startActivity(new Intent(this, PopupWindowSecondActivity.class));  
  42.             break;  
  43.         }  
  44.     }  
  45.       
  46.     /** 
  47.      * 显示菜单 
  48.      * @return 如果菜单显示则返回true,否则返回false 
  49.      */  
  50.     private boolean showLeftMenu() {  
  51.         if (hideLeftMenu())  
  52.         {  
  53.             return false;  
  54.         }  
  55.         LinearLayout leftLayout = (LinearLayout) getLayoutInflater().inflate(R.layout.menu_list, null);  
  56.         // 当菜单出现时,最外层布局接受Touch事件   
  57.         leftLayout.setOnTouchListener(new OnTouchListener()  
  58.         {  
  59.             @Override  
  60.             public boolean onTouch(View v, MotionEvent event)  
  61.             {  
  62.                 hideLeftMenu();  
  63.                 return false;  
  64.             }  
  65.         });  
  66.           
  67.         ListView list = (ListView) leftLayout.findViewById(R.id.item_list);  
  68.         String[] data = getResources().getStringArray(R.array.menu_item);  
  69.         int[] res = new int[data.length];  
  70.         for (int i = 0, length = data.length; i < length; i++)  
  71.         {  
  72.             res[i] = R.drawable.icon;  
  73.         }  
  74.         list.setAdapter(new PopupAdapter(this, data, res, R.layout.menu_item, R.id.item_image, R.id.item_text));  
  75.         list.setOnItemClickListener(new OnItemClickListener()  
  76.         {  
  77.             @Override  
  78.             public void onItemClick(AdapterView<?> parent, View view,  
  79.                     int position, long id)  
  80.             {  
  81.                 hideLeftMenu();  
  82.             }  
  83.         });  
  84.         // 当菜单出现时焦点会落在ListView上   
  85.         list.setOnKeyListener(new OnKeyListener()  
  86.         {  
  87.             @Override  
  88.             public boolean onKey(View v, int keyCode, KeyEvent event)  
  89.             {  
  90.                 // 此方法会调两次,一次Down和一次Up   
  91.                 // 所以此处要拦截   
  92.                 if (event.getAction() == KeyEvent.ACTION_DOWN)  
  93.                 {  
  94.                     switch (keyCode)  
  95.                     {  
  96.                     case KeyEvent.KEYCODE_MENU:  
  97.                         return hideLeftMenu();  
  98.                     case KeyEvent.KEYCODE_BACK:  
  99.                         return hideLeftMenu();  
  100.                     }  
  101.                 }  
  102.                 return false;  
  103.             }  
  104.         });  
  105.           
  106.         // 设置菜单属性   
  107.         mLeftMenu = new PopupWindow(leftLayout, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);  
  108.         mLeftMenu.setWidth(150);  
  109.         // 设置菜单上是否可以聚焦   
  110.         mLeftMenu.setFocusable(true);  
  111.         // 当菜单出现时菜单以外的区域是否接受点击事件   
  112.         mLeftMenu.setOutsideTouchable(true);  
  113.         // 设置菜单显示的位置   
  114.         mLeftMenu.showAtLocation(leftLayout, Gravity.BOTTOM | Gravity.LEFT, 080);  
  115.         return true;  
  116.     }  
  117.       
  118.     /** 
  119.      * 隐藏菜单 
  120.      * @return 如果菜单隐藏则返回true,则否返回false 
  121.      */  
  122.     private boolean hideLeftMenu()  
  123.     {  
  124.         if (null != mLeftMenu && mLeftMenu.isShowing())  
  125.         {  
  126.             mLeftMenu.dismiss();  
  127.             mLeftMenu = null;  
  128.             return true;  
  129.         }  
  130.         return false;  
  131.     }  
  132.       
  133.     @Override  
  134.     public boolean onKeyDown(int keyCode, KeyEvent event)  
  135.     {  
  136.         switch (keyCode)   
  137.         {  
  138.         case KeyEvent.KEYCODE_BACK:  
  139.             hideLeftMenu();  
  140.             break;  
  141.         case KeyEvent.KEYCODE_MENU:  
  142.             showLeftMenu();  
  143.             break;  
  144.         }  
  145.         return super.onKeyDown(keyCode, event);  
  146.     }  
  147.       
  148. }  

其中有三点要注意:

1.PopupWindow的参数设置

  1. // 设置菜单上是否可以聚焦   
  2. mLeftMenu.setFocusable(true);  
  3. // 当菜单出现时菜单以外的区域是否接受点击事件   
  4. 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就不会退出。

以上是第一种方法。

  • 1
  • 2
  • 下一页

相关内容