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. }
 作者:LuoXianXion

發佈留言