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