歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android PopupWindow模擬Windows開始菜單顯示消失效果

Android PopupWindow模擬Windows開始菜單顯示消失效果

日期:2017/3/1 11:01:00   编辑:Linux編程

Android系統給我提供的菜單不盡人意,大多數情況下我們都是根據需求,重寫系統的菜單,達到想要的效果,下面就用PopupWindow兩種方式重寫系統菜單效果。

Android PopupWindow模擬Windows開始菜單顯示消失效果DEMO下載:

免費下載地址在 http://linux.linuxidc.com/

用戶名與密碼都是www.linuxidc.com

具體下載目錄在 /pub/Android源碼集錦/2011年/11月/Android PopupWindow模擬Windows開始菜單顯示消失效果/

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

其中有三點要注意:

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就不會退出。

以上是第一種方法。

Copyright © Linux教程網 All Rights Reserved