pupwindow介绍以及代码实例
PopupWindow在android.widget包下,弹出窗口的形式展示。官方文档对该控件的描述是:“一个弹出窗口控件,可以用来显示任意视图(View),而且会浮动在当前 活动(activity)的顶部”。PopupWindow可以让我们实现多种自定义控件,例如:menu、alertdialog等弹窗似的View。
一、PopupWindow的简单用法
在这个例子中,popupwindow在onCreate时初始化、通过触发事件展示出来。
java代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
public class ShowPopupWindow extends Activity implements View.OnClickListener { View view; PopupWindow pop; Button btnShowAsDrawDown; Button btnShowAsDrawDown1; Button btnShowAtLocation; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super .onCreate(savedInstanceState); setContentView(R.layout.popup_activity); btnShowAsDrawDown = (Button) findViewById(R.id.btnShowAsDrawDown); btnShowAsDrawDown.setOnClickListener( this ); btnShowAsDrawDown1 = (Button) findViewById(R.id.btnShowAsDrawDown1); btnShowAsDrawDown1.setOnClickListener( this ); btnShowAtLocation = (Button) findViewById(R.id.btnShowAt); btnShowAtLocation.setOnClickListener( this ); initPopupWindow(); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()){ case R.id.btnShowAsDrawDown: if (pop.isShowing()){ pop.dismiss(); } else { pop.showAsDropDown(v); } break ; case R.id.btnShowAsDrawDown1: if (pop.isShowing()){ pop.dismiss(); } else { pop.showAsDropDown(v, 0, -160); } break ; default : if (pop.isShowing()){ pop.dismiss(); } else { pop.showAtLocation(findViewById(R.id.main), Gravity.CENTER_HORIZONTAL, 0, 0); } break ; } } private void initPopupWindow(){ view = this .getLayoutInflater().inflate(R.layout.popup_window, null ); pop = new PopupWindow(view, ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); pop.setOutsideTouchable( true ); view.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub pop.dismiss(); } }); } } |
布局文件:popup_activity.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:id= "@+id/main" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <TextView android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "pop demo!" /> <Button android:id= "@+id/btnShowAsDrawDown" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "Show as drawndown(one parameter)" /> <Button android:id= "@+id/btnShowAsDrawDown1" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "Show as drawndown(three parameters)" /> <Button android:id= "@+id/btnShowAt" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:text= "Show At Location" /> </LinearLayout> |
布局文件:popup_window.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout android:layout_width= "fill_parent" android:layout_height= "fill_parent" android:orientation= "vertical" android:gravity= "center_horizontal" android:background= "#d3d3d3" > <Button android:id= "@+id/btn_pop" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "Close" android:layout_margin= "10dip" /> </LinearLayout> |
二、一个能在自适应位置的PopupWindow
分享一个实例。看效果:
实现中使用的 PopupWindow。这里做了简单封装,其中有三个类组成:PopuItem、PopuJar、PopupWindows。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
public class PopuItem { private Drawable icon; private Bitmap thumb; private String title; private int actionId = -1; private boolean selected; private boolean sticky; /** * Constructor * * @param actionId Action id for case statements * @param title Title * @param icon Icon to use */ public PopuItem(int actionId, String title, Drawable icon) { this .title = title; this .icon = icon; this .actionId = actionId; } /** * Constructor */ public PopuItem() { this (-1, null , null ); } /** * Constructor * * @param actionId Action id of the item * @param title Text to show for the item */ public PopuItem(int actionId, String title) { this (actionId, title, null ); } /** * Constructor * * @param icon {@link Drawable} action icon */ public PopuItem(Drawable icon) { this (-1, null , icon); } /** * Constructor * * @param actionId Action ID of item * @param icon {@link Drawable} action icon */ public PopuItem(int actionId, Drawable icon) { this (actionId, null , icon); } /** * Set action title * * @param title action title */ public void setTitle(String title) { this .title = title; } /** * Get action title * * @return action title */ public String getTitle() { return this .title; } /** * Set action icon * * @param icon {@link Drawable} action icon */ public void setIcon(Drawable icon) { this .icon = icon; } /** * Get action icon * @return {@link Drawable} action icon */ public Drawable getIcon() { return this .icon; } /** * Set action id * * @param actionId Action id for this action */ public void setActionId(int actionId) { this .actionId = actionId; } /** * @return Our action id */ public int getActionId() { return actionId; } /** * Set sticky status of button * * @param sticky true for sticky, pop up sends event but does not disappear */ public void setSticky(boolean sticky) { this .sticky = sticky; } /** * @return true if button is sticky, menu stays visible after press */ public boolean isSticky() { return sticky; } /** * Set selected flag; * * @param selected Flag to indicate the item is selected */ public void setSelected(boolean selected) { this .selected = selected; } /** * Check if item is selected * * @return true or false */ public boolean isSelected() { return this .selected; } /** * Set thumb * * @param thumb Thumb image */ public void setThumb(Bitmap thumb) { this .thumb = thumb; } /** * Get thumb image * * @return Thumb image */ public Bitmap getThumb() { return this .thumb; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
public class PopuJar extends PopupWindows implements OnDismissListener { private View mRootView; private ImageView mArrowUp; private ImageView mArrowDown; private LayoutInflater mInflater; private ViewGroup mTrack; private ScrollView mScroller; private OnPopuItemClickListener mItemClickListener; private OnDismissListener mDismissListener; private List<PopuItem> PopuItems = new ArrayList<PopuItem>(); private boolean mDidAction; private int mChildPos; private int mInsertPos; private int mAnimStyle; private int mOrientation; private int rootWidth=0; public static final int HORIZONTAL = 0; public static final int VERTICAL = 1; public static final int ANIM_GROW_FROM_LEFT = 1; public static final int ANIM_GROW_FROM_RIGHT = 2; public static final int ANIM_GROW_FROM_CENTER = 3; public static final int ANIM_REFLECT = 4; public static final int ANIM_AUTO = 5; /** * Constructor for default vertical layout * * @param context Context */ public PopuJar(Context context) { this (context, VERTICAL); } /** * Constructor allowing orientation override * * @param context Context * @param orientation Layout orientation, can be vartical or horizontal */ public PopuJar(Context context, int orientation) { super (context); mOrientation = orientation; mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); if (mOrientation == HORIZONTAL) { setRootViewId(R.layout.popup_horizontal); } else { setRootViewId(R.layout.popup_vertical); } mAnimStyle = ANIM_AUTO; mChildPos = 0; } /** * Get action item at an index * * @param index Index of item (position from callback) * * @return Action Item at the position */ public PopuItem getPopuItem(int index) { return PopuItems.get(index); } /** * Set root view. * * @param id Layout resource id */ public void setRootViewId(int id) { mRootView = (ViewGroup) mInflater.inflate(id, null ); mTrack = (ViewGroup) mRootView.findViewById(R.id.tracks); mArrowDown = (ImageView) mRootView.findViewById(R.id.arrow_down); mArrowUp = (ImageView) mRootView.findViewById(R.id.arrow_up); mScroller = (ScrollView) mRootView.findViewById(R.id.scroller); //This was previously defined on show() method, moved here to prevent force close that occured //when tapping fastly on a view to show quickaction dialog. //Thanx to zammbi (github.com/zammbi) mRootView.setLayoutParams( new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); setContentView(mRootView); } /** * Set animation style * * @param mAnimStyle animation style, default is set to ANIM_AUTO */ public void setAnimStyle(int mAnimStyle) { this .mAnimStyle = mAnimStyle; } /** * Set listener for action item clicked. * * @param listener Listener */ public void setOnPopuItemClickListener(OnPopuItemClickListener listener) { mItemClickListener = listener; } /** * Add action item * * @param action {@link PopuItem} */ public void addPopuItem(PopuItem action) { PopuItems.add(action); String title = action.getTitle(); Drawable icon = action.getIcon(); View container; if (mOrientation == HORIZONTAL) { container = mInflater.inflate(R.layout.action_item_horizontal, null ); } else { container = mInflater.inflate(R.layout.action_item_vertical, null ); } ImageView img = (ImageView) container.findViewById(R.id.iv_icon); TextView text = (TextView) container.findViewById(R.id.tv_title); if (icon != null ) { img.setImageDrawable(icon); } else { img.setVisibility(View.GONE); } if (title != null ) { text.setText(title); } else { text.setVisibility(View.GONE); } final int pos = mChildPos; final int actionId = action.getActionId(); container.setOnClickListener( new OnClickListener() { @Override public void onClick(View v) { if (mItemClickListener != null ) { mItemClickListener.onItemClick(PopuJar. this , pos, actionId); } if (!getPopuItem(pos).isSticky()) { mDidAction = true ; dismiss(); } } }); container.setFocusable( true ); container.setClickable( true ); if (mOrientation == HORIZONTAL && mChildPos != 0) { View separator = mInflater.inflate(R.layout.horiz_separator, null ); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT); separator.setLayoutParams(params); separator.setPadding(5, 0, 5, 0); mTrack.addView(separator, mInsertPos); mInsertPos++; } mTrack.addView(container, mInsertPos); mChildPos++; mInsertPos++; } /** * Show quickaction popup. Popup is automatically positioned, on top or bottom of anchor view. * */ public void show (View anchor) { preShow(); int xPos, yPos, arrowPos; mDidAction = false ; int[] location = new int[2]; anchor.getLocationOnScreen(location); Rect anchorRect = new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1] + anchor.getHeight()); //mRootView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); mRootView.measure(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); int rootHeight = mRootView.getMeasuredHeight(); if (rootWidth == 0) { rootWidth = mRootView.getMeasuredWidth(); } int screenWidth = mWindowManager.getDefaultDisplay().getWidth(); int screenHeight = mWindowManager.getDefaultDisplay().getHeight(); //automatically get X coord of popup (top left) if ((anchorRect.left + rootWidth) > screenWidth) { xPos = anchorRect.left - (rootWidth-anchor.getWidth()); xPos = (xPos < 0) ? 0 : xPos; arrowPos = anchorRect.centerX()-xPos; } else { if (anchor.getWidth() > rootWidth) { xPos = anchorRect.centerX() - (rootWidth/2); } else { xPos = anchorRect.left; } arrowPos = anchorRect.centerX()-xPos; } int dyTop = anchorRect.top; int dyBottom = screenHeight - anchorRect.bottom; boolean onTop = (dyTop > dyBottom) ? true : false ; if (onTop) { if (rootHeight > dyTop) { yPos = 15; LayoutParams l = mScroller.getLayoutParams(); l.height = dyTop - anchor.getHeight(); } else { yPos = anchorRect.top - rootHeight; } } else { yPos = anchorRect.bottom; if (rootHeight > dyBottom) { LayoutParams l = mScroller.getLayoutParams(); l.height = dyBottom; } } showArrow(((onTop) ? R.id.arrow_down : R.id.arrow_up), arrowPos); setAnimationStyle(screenWidth, anchorRect.centerX(), onTop); mWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, xPos, yPos); } /** * Set animation style * * @param screenWidth screen width * @param requestedX distance from left edge * @param onTop flag to indicate where the popup should be displayed. Set TRUE if displayed on top of anchor view * and vice versa */ private void setAnimationStyle(int screenWidth, int requestedX, boolean onTop) { int arrowPos = requestedX - mArrowUp.getMeasuredWidth()/2; switch (mAnimStyle) { case ANIM_GROW_FROM_LEFT: mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); break ; case ANIM_GROW_FROM_RIGHT: mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right); break ; case ANIM_GROW_FROM_CENTER: mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); break ; case ANIM_REFLECT: mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Reflect : R.style.Animations_PopDownMenu_Reflect); break ; case ANIM_AUTO: if (arrowPos <= screenWidth/4) { mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Left : R.style.Animations_PopDownMenu_Left); } else if (arrowPos > screenWidth/4 && arrowPos < 3 * (screenWidth/4)) { mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Center : R.style.Animations_PopDownMenu_Center); } else { mWindow.setAnimationStyle((onTop) ? R.style.Animations_PopUpMenu_Right : R.style.Animations_PopDownMenu_Right); } break ; } } /** * Show arrow * * @param whichArrow arrow type resource id * @param requestedX distance from left screen */ private void showArrow(int whichArrow, int requestedX) { final View showArrow = (whichArrow == R.id.arrow_up) ? mArrowUp : mArrowDown; final View hideArrow = (whichArrow == R.id.arrow_up) ? mArrowDown : mArrowUp; final int arrowWidth = mArrowUp.getMeasuredWidth(); showArrow.setVisibility(View.VISIBLE); ViewGroup.MarginLayoutParams param = (ViewGroup.MarginLayoutParams)showArrow.getLayoutParams(); param.leftMargin = requestedX - arrowWidth / 2; hideArrow.setVisibility(View.INVISIBLE); } /** * Set listener for window dismissed. This listener will only be fired if the quicakction dialog is dismissed * by clicking outside the dialog or clicking on sticky item. */ public void setOnDismissListener(PopuJar.OnDismissListener listener) { setOnDismissListener( this ); mDismissListener = listener; } @Override public void onDismiss() { if (!mDidAction && mDismissListener != null ) { mDismissListener.onDismiss(); } } /** * Listener for item click * */ public interface OnPopuItemClickListener { public abstract void onItemClick(PopuJar source, int pos, int actionId); } /** * Listener for window dismiss * */ public interface OnDismissListener { public abstract void onDismiss(); } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
public class PopupWindows { protected Context mContext; protected PopupWindow mWindow; protected View mRootView; protected Drawable mBackground = null ; protected WindowManager mWindowManager; /** * Constructor. * * @param context Context */ public PopupWindows(Context context) { mContext = context; mWindow = new PopupWindow(context); mWindow.setTouchInterceptor( new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { mWindow.dismiss(); return true ; } return false ; } }); mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); } /** * On dismiss */ protected void onDismiss() { } /** * On show */ protected void onShow() { } /** * On pre show */ protected void preShow() { if (mRootView == null ) throw new IllegalStateException( "setContentView was not called with a view to display." ); onShow(); if (mBackground == null ) mWindow.setBackgroundDrawable( new BitmapDrawable()); else mWindow.setBackgroundDrawable(mBackground); mWindow.setWidth(WindowManager.LayoutParams.WRAP_CONTENT); mWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT); mWindow.setTouchable( true ); mWindow.setFocusable( true ); mWindow.setOutsideTouchable( true ); mWindow.setContentView(mRootView); } /** * Set background drawable. * * @param background Background drawable */ public void setBackgroundDrawable(Drawable background) { mBackground = background; } /** * Set content view. * * @param root Root view */ public void setContentView(View root) { mRootView = root; mWindow.setContentView(root); } /** * Set content view. * * @param layoutResID Resource id */ public void setContentView(int layoutResID) { LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); setContentView(inflator.inflate(layoutResID, null )); } /** * Set listener on window dismissed. * * @param listener */ public void setOnDismissListener(PopupWindow.OnDismissListener listener) { mWindow.setOnDismissListener(listener); } /** * Dismiss the popup window. */ public void dismiss() { mWindow.dismiss(); } } |
Popu调用时在onCreate使用如下:
1
2
3
4
5
6
7
8
9
10
11
|
PopuItem userItem = new PopuItem(ID_USER, "用户" , getResources().getDrawable(R.drawable.child_image)); PopuItem grounpItem = new PopuItem(ID_GROUNP, "群组" , getResources().getDrawable(R.drawable.user_group)); //use setSticky(true) to disable PopuJar dialog being dismissed after an item is clicked userItem.setSticky( true ); //create PopuJar. Use PopuJar.VERTICAL or PopuJar.HORIZONTAL param to define layout final PopuJar mPopu = new PopuJar( this , PopuJar.VERTICAL); //add action items into PopuJar mPopu.addPopuItem(userItem); mPopu.addPopuItem(grounpItem); |
显示popu:
1
|
mPopu.show(v); //v表示显示在那个view下面 |