Android UI开发第十六篇——分享一个popuwindow实例

简介:

PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。

 

 

 

   

 

实现中使用的  PopupWindow。这里做了简单封装,其中有三个类组成:PopuItem、PopuJar、PopupWindows。


 
 
  1. public class PopuItem {  
  2.     private Drawable icon;  
  3.     private Bitmap thumb;  
  4.     private String title;  
  5.     private int actionId = -1;  
  6.     private boolean selected;  
  7.     private boolean sticky;  
  8.       
  9.     /**  
  10.      * Constructor  
  11.      *   
  12.      * @param actionId  Action id for case statements  
  13.      * @param title     Title  
  14.      * @param icon      Icon to use  
  15.      */ 
  16.     public PopuItem(int actionId, String title, Drawable icon) {  
  17.         this.title = title;  
  18.         this.icon = icon;  
  19.         this.actionId = actionId;  
  20.     }  
  21.       
  22.     /**  
  23.      * Constructor  
  24.      */ 
  25.     public PopuItem() {  
  26.         this(-1nullnull);  
  27.     }  
  28.       
  29.     /**  
  30.      * Constructor  
  31.      *   
  32.      * @param actionId  Action id of the item  
  33.      * @param title     Text to show for the item  
  34.      */ 
  35.     public PopuItem(int actionId, String title) {  
  36.         this(actionId, title, null);  
  37.     }  
  38.       
  39.     /**  
  40.      * Constructor  
  41.      *   
  42.      * @param icon {@link Drawable} action icon  
  43.      */ 
  44.     public PopuItem(Drawable icon) {  
  45.         this(-1null, icon);  
  46.     }  
  47.       
  48.     /**  
  49.      * Constructor  
  50.      *   
  51.      * @param actionId  Action ID of item  
  52.      * @param icon      {@link Drawable} action icon  
  53.      */ 
  54.     public PopuItem(int actionId, Drawable icon) {  
  55.         this(actionId, null, icon);  
  56.     }  
  57.       
  58.     /**  
  59.      * Set action title  
  60.      *   
  61.      * @param title action title  
  62.      */ 
  63.     public void setTitle(String title) {  
  64.         this.title = title;  
  65.     }  
  66.       
  67.     /**  
  68.      * Get action title  
  69.      *   
  70.      * @return action title  
  71.      */ 
  72.     public String getTitle() {  
  73.         return this.title;  
  74.     }  
  75.       
  76.     /**  
  77.      * Set action icon  
  78.      *   
  79.      * @param icon {@link Drawable} action icon  
  80.      */ 
  81.     public void setIcon(Drawable icon) {  
  82.         this.icon = icon;  
  83.     }  
  84.       
  85.     /**  
  86.      * Get action icon  
  87.      * @return  {@link Drawable} action icon  
  88.      */ 
  89.     public Drawable getIcon() {  
  90.         return this.icon;  
  91.     }  
  92.       
  93.      /**  
  94.      * Set action id  
  95.      *   
  96.      * @param actionId  Action id for this action  
  97.      */ 
  98.     public void setActionId(int actionId) {  
  99.         this.actionId = actionId;  
  100.     }  
  101.       
  102.     /**  
  103.      * @return  Our action id  
  104.      */ 
  105.     public int getActionId() {  
  106.         return actionId;  
  107.     }  
  108.       
  109.     /**  
  110.      * Set sticky status of button  
  111.      *   
  112.      * @param sticky  true for sticky, pop up sends event but does not disappear  
  113.      */ 
  114.     public void setSticky(boolean sticky) {  
  115.         this.sticky = sticky;  
  116.     }  
  117.       
  118.     /**  
  119.      * @return  true if button is sticky, menu stays visible after press  
  120.      */ 
  121.     public boolean isSticky() {  
  122.         return sticky;  
  123.     }  
  124.       
  125.     /**  
  126.      * Set selected flag;  
  127.      *   
  128.      * @param selected Flag to indicate the item is selected  
  129.      */ 
  130.     public void setSelected(boolean selected) {  
  131.         this.selected = selected;  
  132.     }  
  133.       
  134.     /**  
  135.      * Check if item is selected  
  136.      *   
  137.      * @return true or false  
  138.      */ 
  139.     public boolean isSelected() {  
  140.         return this.selected;  
  141.     }  
  142.  
  143.     /**  
  144.      * Set thumb  
  145.      *   
  146.      * @param thumb Thumb image  
  147.      */ 
  148.     public void setThumb(Bitmap thumb) {  
  149.         this.thumb = thumb;  
  150.     }  
  151.       
  152.     /**  
  153.      * Get thumb image  
  154.      *   
  155.      * @return Thumb image  
  156.      */ 
  157.     public Bitmap getThumb() {  
  158.         return this.thumb;  
  159.     }  

 
 
  1. public class PopuJar extends PopupWindows implements OnDismissListener {
  2. private View mRootView;
  3. private ImageView mArrowUp;
  4. private ImageView mArrowDown;
  5. private LayoutInflater mInflater;
  6. private ViewGroup mTrack;
  7. private ScrollView mScroller;
  8. private OnPopuItemClickListener mItemClickListener;
  9. private OnDismissListener mDismissListener;
  10. private List<PopuItem> PopuItems = new ArrayList<PopuItem>();
  11. private boolean mDidAction;
  12. private int mChildPos;
  13. private int mInsertPos;
  14. private int mAnimStyle;
  15. private int mOrientation;
  16. private int rootWidth=0;
  17. public static final int HORIZONTAL = 0;
  18. public static final int VERTICAL = 1;
  19. public static final int ANIM_GROW_FROM_LEFT = 1;
  20. public static final int ANIM_GROW_FROM_RIGHT = 2;
  21. public static final int ANIM_GROW_FROM_CENTER = 3;
  22. public static final int ANIM_REFLECT = 4;
  23. public static final int ANIM_AUTO = 5;
  24. /**
  25. * Constructor for default vertical layout
  26. *
  27. * @param context Context
  28. */
  29. public PopuJar(Context context) {
  30. this(context, VERTICAL);
  31. }
  32. /**
  33. * Constructor allowing orientation override
  34. *
  35. * @param context Context
  36. * @param orientation Layout orientation, can be vartical or horizontal
  37. */
  38. public PopuJar(Context context, int orientation) {
  39. super(context);
  40. mOrientation = orientation;
  41. mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  42. if (mOrientation == HORIZONTAL) {
  43. setRootViewId(R.layout.popup_horizontal);
  44. } else {
  45. setRootViewId(R.layout.popup_vertical);
  46. }
  47. mAnimStyle = ANIM_AUTO;
  48. mChildPos = 0;
  49. }
  50. /**
  51. * Get action item at an index
  52. *
  53. * @param index Index of item (position from callback)
  54. *
  55. * @return Action Item at the position
  56. */
  57. public PopuItem getPopuItem(int index) {
  58. return PopuItems.get(index);
  59. }
  60. /**
  61. * Set root view.
  62. *
  63. * @param id Layout resource id
  64. */
  65. public void setRootViewId(int id) {
  66. mRootView = (ViewGroup) mInflater.inflate(id, null);
  67. mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks);
  68. mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down);
  69. mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up);
  70. mScroller = (ScrollView) mRootView.findViewById(R.id.scroller);
  71. //This was previously defined on show() method, moved here to prevent force close that occured
  72. //when tapping fastly on a view to show quickaction dialog.
  73. //Thanx to zammbi (github.com/zammbi)
  74. mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  75. setContentView(mRootView);
  76. }
  77. /**
  78. * Set animation style
  79. *
  80. * @param mAnimStyle animation style, default is set to ANIM_AUTO
  81. */
  82. public void setAnimStyle(int mAnimStyle) {
  83. this.mAnimStyle = mAnimStyle;
  84. }
  85. /**
  86. * Set listener for action item clicked.
  87. *
  88. * @param listener Listener
  89. */
  90. public void setOnPopuItemClickListener(OnPopuItemClickListener listener) {
  91. mItemClickListener = listener;
  92. }
  93. /**
  94. * Add action item
  95. *
  96. * @param action {@link PopuItem}
  97. */
  98. public void addPopuItem(PopuItem action) {
  99. PopuItems.add(action);
  100. String title = action.getTitle();
  101. Drawable icon = action.getIcon();
  102. View container;
  103. if (mOrientation == HORIZONTAL) {
  104. container = mInflater.inflate(R.layout.action_item_horizontal, null);
  105. } else {
  106. container = mInflater.inflate(R.layout.action_item_vertical, null);
  107. }
  108. ImageView img = (ImageView) container.findViewById(R.id.iv_icon);
  109. TextView text = (TextView) container.findViewById(R.id.tv_title);
  110. if (icon != null) {
  111. img.setImageDrawable(icon);
  112. } else {
  113. img.setVisibility(View.GONE);
  114. }
  115. if (title != null) {
  116. text.setText(title);
  117. } else {
  118. text.setVisibility(View.GONE);
  119. }
  120. final int pos = mChildPos;
  121. final int actionId = action.getActionId();
  122. container.setOnClickListener(new OnClickListener() {
  123. @Override
  124. public void onClick(View v) {
  125. if (mItemClickListener != null) {
  126. mItemClickListener.onItemClick(PopuJar.this, pos, actionId);
  127. }
  128. if (!getPopuItem(pos).isSticky()) {
  129. mDidAction = true;
  130. dismiss();
  131. }
  132. }
  133. });
  134. container.setFocusable(true);
  135. container.setClickable(true);
  136. if (mOrientation == HORIZONTAL && mChildPos != 0) {
  137. View separator = mInflater.inflate(R.layout.horiz_separator, null);
  138. RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT);
  139. separator.setLayoutParams(params);
  140. separator.setPadding(5, 0, 5, 0);
  141. mTrack.addView(separator, mInsertPos);
  142. mInsertPos++;
  143. }
  144. mTrack.addView(container, mInsertPos);
  145. mChildPos++;
  146. mInsertPos++;
  147. }
  148. /**
  149. * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view.
  150. *
  151. */
  152. public void show (View anchor) {
  153. preShow();
  154. int xPos, yPos, arrowPos;
  155. mDidAction = false;
  156. int[] location = new int[2];
  157. anchor.getLocationOnScreen(location);
  158. Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1]
  159. + anchor.getHeight());
  160. //mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  161. mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  162. int rootHeight = mRootView.getMeasuredHeight();
  163. if (rootWidth == 0) {
  164. rootWidth = mRootView.getMeasuredWidth();
  165. }
  166. int screenWidth = mWindowManager.getDefaultDisplay().getWidth();
  167. int screenHeight = mWindowManager.getDefaultDisplay().getHeight();
  168. //automatically get X coord of popup (top left)
  169. if ((anchorRect.left + rootWidth) > screenWidth) {
  170. xPos = anchorRect.left - (rootWidth-anchor.getWidth());
  171. xPos = (xPos < 0) ? 0 : xPos;
  172. arrowPos = anchorRect.centerX()-xPos;
  173. } else {
  174. if (anchor.getWidth() > rootWidth) {
  175. xPos = anchorRect.centerX() - (rootWidth/2);
  176. } else {
  177. xPos = anchorRect.left;
  178. }
  179. arrowPos = anchorRect.centerX()-xPos;
  180. }
  181. int dyTop = anchorRect.top;
  182. int dyBottom = screenHeight - anchorRect.bottom;
  183. boolean onTop = (dyTop > dyBottom) ? true : false;
  184. if (onTop) {
  185. if (rootHeight > dyTop) {
  186. yPos = 15;
  187. LayoutParams l = mScroller.getLayoutParams();
  188. l.height = dyTop - anchor.getHeight();
  189. } else {
  190. yPos = anchorRect.top - rootHeight;
  191. }
  192. } else {
  193. yPos = anchorRect.bottom;
  194. if (rootHeight > dyBottom) {
  195. LayoutParams l = mScroller.getLayoutParams();
  196. l.height = dyBottom;
  197. }
  198. }
  199. showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos);
  200. setAnimationStyle(screenWidth, anchorRect.centerX(), onTop);
  201. mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos);
  202. }
  203. /**
  204. * Set animation style
  205. *
  206. * @param screenWidth screen width
  207. * @param requestedX distance from left edge
  208. * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view
  209. * and vice versa
  210. */
  211. private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) {
  212. int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2;
  213. switch (mAnimStyle) {
  214. case ANIM_GROW_FROM_LEFT:
  215. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
  216. break;
  217. case ANIM_GROW_FROM_RIGHT:
  218. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
  219. break;
  220. case ANIM_GROW_FROM_CENTER:
  221. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
  222. break;
  223. case ANIM_REFLECT:
  224. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect);
  225. break;
  226. case ANIM_AUTO:
  227. if (arrowPos <= screenWidth/4) {
  228. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left);
  229. } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) {
  230. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center);
  231. } else {
  232. mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right);
  233. }
  234. break;
  235. }
  236. }
  237. /**
  238. * Show arrow
  239. *
  240. * @param whichArrow arrow type resource id
  241. * @param requestedX distance from left screen
  242. */
  243. private void showArrow(int whichArrow, int requestedX) {
  244. final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown;
  245. final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp;
  246. final int arrowWidth = mArrowUp.getMeasuredWidth();
  247. showArrow.setVisibility(View.VISIBLE);
  248. ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams();
  249. param.leftMargin = requestedX - arrowWidth / 2;
  250. hideArrow.setVisibility(View.INVISIBLE);
  251. }
  252. /**
  253. * Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed
  254. * by clicking outside the dialog or clicking on sticky item.
  255. */
  256. public void setOnDismissListener(PopuJar.OnDismissListener listener) {
  257. setOnDismissListener(this);
  258. mDismissListener = listener;
  259. }
  260. @Override
  261. public void onDismiss() {
  262. if (!mDidAction && mDismissListener != null) {
  263. mDismissListener.onDismiss();
  264. }
  265. }
  266. /**
  267. * Listener for item click
  268. *
  269. */
  270. public interface OnPopuItemClickListener {
  271. public abstract void onItemClick(PopuJar source, int pos, int actionId);
  272. }
  273. /**
  274. * Listener for window dismiss
  275. *
  276. */
  277. public interface OnDismissListener {
  278. public abstract void onDismiss();
  279. }
  280. }

 
 
  1. public class PopupWindows {
  2. protected Context mContext;
  3. protected PopupWindow mWindow;
  4. protected View mRootView;
  5. protected Drawable mBackground = null;
  6. protected WindowManager mWindowManager;
  7. /**
  8. * Constructor.
  9. *
  10. * @param context Context
  11. */
  12. public PopupWindows(Context context) {
  13. mContext = context;
  14. mWindow = new PopupWindow(context);
  15. mWindow.setTouchInterceptor(new OnTouchListener() {
  16. @Override
  17. public boolean onTouch(View v, MotionEvent event) {
  18. if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
  19. mWindow.dismiss();
  20. return true;
  21. }
  22. return false;
  23. }
  24. });
  25. mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
  26. }
  27. /**
  28. * On dismiss
  29. */
  30. protected void onDismiss() {
  31. }
  32. /**
  33. * On show
  34. */
  35. protected void onShow() {
  36. }
  37. /**
  38. * On pre show
  39. */
  40. protected void preShow() {
  41. if (mRootView == null)
  42. throw new IllegalStateException("setContentView was not called with a view to display.");
  43. onShow();
  44. if (mBackground == null)
  45. mWindow.setBackgroundDrawable(new BitmapDrawable());
  46. else
  47. mWindow.setBackgroundDrawable(mBackground);
  48. mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT);
  49. mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);
  50. mWindow.setTouchable(true);
  51. mWindow.setFocusable(true);
  52. mWindow.setOutsideTouchable(true);
  53. mWindow.setContentView(mRootView);
  54. }
  55. /**
  56. * Set background drawable.
  57. *
  58. * @param background Background drawable
  59. */
  60. public void setBackgroundDrawable(Drawable background) {
  61. mBackground = background;
  62. }
  63. /**
  64. * Set content view.
  65. *
  66. * @param root Root view
  67. */
  68. public void setContentView(View root) {
  69. mRootView = root;
  70. mWindow.setContentView(root);
  71. }
  72. /**
  73. * Set content view.
  74. *
  75. * @param layoutResID Resource id
  76. */
  77. public void setContentView(int layoutResID) {
  78. LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  79. setContentView(inflator.inflate(layoutResID, null));
  80. }
  81. /**
  82. * Set listener on window dismissed.
  83. *
  84. * @param listener
  85. */
  86. public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
  87. mWindow.setOnDismissListener(listener);
  88. }
  89. /**
  90. * Dismiss the popup window.
  91. */
  92. public void dismiss() {
  93. mWindow.dismiss();
  94. }
  95. }

显示popu:

参考:

http://code.google.com/p/simple-quickactions/




     本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/817276,如需转载请自行联系原作者



相关文章
|
2天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
20天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
42 19
|
21天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
46 14
|
20天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
21天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
21天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
28 0
|
Android开发
《Android UI基础教程》——导读
本节书摘来自异步社区《Android UI基础教程》一书中的目录,作者 【美】Jason Ostrander,更多章节内容可以访问云栖社区“异步社区”公众号查看
799 0