Popupwindow的使用

项目中经常会使用到popupwindow做菜单选项,这个类在使用中有一些经常被遗忘的细节,今天用一个实例来总结一个popupwindow较常用的用法。

效果图:

MainActivity.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
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
public class MainActivity extends Activity {  

private ImageButton ibOperationMore;

List<Map<String, String>> moreList;
private PopupWindow pwMyPopWindow;// popupwindow
private ListView lvPopupList;// popupwindow中的ListView
private int NUM_OF_VISIBLE_LIST_ROWS = 3;// 指定popupwindow中Item的数量

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

iniData();

iniPopupWindow();

// 更多操作按钮
ibOperationMore = (ImageButton) findViewById(R.id.ib_operate_more);
ibOperationMore.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {

if (pwMyPopWindow.isShowing()) {

pwMyPopWindow.dismiss();// 关闭
} else {

pwMyPopWindow.showAsDropDown(ibOperationMore);// 显示
}

}
});
}

private void iniData() {

moreList = new ArrayList<Map<String, String>>();
Map<String, String> map;
map = new HashMap<String, String>();
map.put("share_key", "复制");
moreList.add(map);
map = new HashMap<String, String>();
map.put("share_key", "删除");
moreList.add(map);
map = new HashMap<String, String>();
map.put("share_key", "修改");
moreList.add(map);
}

private void iniPopupWindow() {

LayoutInflater inflater = (LayoutInflater) this
.getSystemService(LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.task_detail_popupwindow, null);
lvPopupList = (ListView) layout.findViewById(R.id.lv_popup_list);
pwMyPopWindow = new PopupWindow(layout);
pwMyPopWindow.setFocusable(true);// 加上这个popupwindow中的ListView才可以接收点击事件

lvPopupList.setAdapter(new SimpleAdapter(MainActivity.this, moreList,
R.layout.list_item_popupwindow, new String[] { "share_key" },
new int[] { R.id.tv_list_item }));
lvPopupList.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {

Toast.makeText(MainActivity.this,
moreList.get(position).get("share_key"),
Toast.LENGTH_LONG).show();
}
});

// 控制popupwindow的宽度和高度自适应
// 也可以写成在实例化时候写成: pwMyPopWindow = new PopupWindow(layout,width,height);
lvPopupList.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
pwMyPopWindow.setWidth(lvPopupList.getMeasuredWidth());
pwMyPopWindow.setHeight((lvPopupList.getMeasuredHeight() + 20) * NUM_OF_VISIBLE_LIST_ROWS);

// 控制popupwindow点击屏幕其他地方消失
pwMyPopWindow.setBackgroundDrawable(this.getResources().getDrawable(
R.drawable.bg_popupwindow));// 设置背景图片,不能在布局中设置,要通过代码来设置
pwMyPopWindow.setOutsideTouchable(true);// 触摸popupwindow外部,popupwindow消失。这个要求你的popupwindow要有背景图片才可以成功,如上
}

}

activity_main.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
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="#ffffff" >

<LinearLayout
android:id="@+id/ll_head_bar"
style="@style/header_linear_layout"
android:layout_alignParentTop="true" >

<Button
android:id="@+id/btn_back"
style="@style/header_button_back"
android:layout_marginLeft="8dip" />

<TextView
style="@style/header_text_view"
android:visibility="invisible" />

<ImageButton
android:id="@+id/ib_operate_more"
style="@style/header_button_operate"
android:layout_marginLeft="8dip"
android:layout_marginRight="10dip"
android:src="@drawable/ico_headbar_more" />
</LinearLayout>

</RelativeLayout>

list_item_popupwindow.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >

<TextView
android:id="@+id/tv_list_item"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:minHeight="40dp"
android:minWidth="120dp"
android:textSize="20sp"
android:textColor="@color/popupwindow_list_item_text_selector"
/>

</LinearLayout>

task_detail_popupwindow.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>"

<ListView
android:id="@+id/lv_popup_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:listSelector="#00000000"
android:divider="@drawable/ico_list_item_line_popupwindow"
android:focusableInTouchMode="true"
/>

</LinearLayout>

注意:如果你想让自己的popupwindow在Activity启动的时候就显示的话,不能放在onCreate方法中,因为这个时候,界面组件还未加载好,所以会提示你你的Activity是否已经启动了,你可以放在onAttachedToWindow方法中。

关于显示的位置还有一个方法showAtLocation(parent, gravity, x, y)

这里的参数parent指的是这个popupwindow相对的是哪个父类,比如你想要让这个popupwindow相对于整个屏幕那么你的parent可以是View parent = this.getWindow().getDecorView();

parent.getHeight()得到的值是你的屏幕的高度(像素)。

这个时候,x,y就是它在这个parent中的相对位置了。Gravity默认是左上Left,Top

例如:下面的代码设置了popupwindow在屏幕的左下角的位置。

1
2
View parent = this.getWindow().getDecorView();//高度为手机实际的像素高度  
pwMyPopWindow.showAtLocation(parent, Gravity.NO_GRAVITY, (int)(parent.getWidth()/18), parent.getHeight() - btnAddTask.getHeight() - (int)(parent.getHeight()/9));

还有一些style,color之类的属性这里就不贴出来了。

项目地址:

https://github.com/michaelye/PopupwindowDemo.git


PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种;按照参照物的不同,可以分为相对于某个控件(Anchor锚)和相对于父控件。具体如下

  1. showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移
  2. showAsDropDown(View anchor, int xoff, int yoff):相对某个控件的位置,有偏移
  3. showAtLocation(View parent, int gravity, int x, int y):相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移

常用方法:
popupWindow.setAnimationStyle(R.style.PopMenuAnimation); //设置popwindow出现和消失动画
popupWindow.setFocusable(true); //获取popwindow焦点
popupWindow.setOutsideTouchable(true); //设置popwindow如果点击外面区域,便关闭。

参考:
Android中的PopupWindow详解
Android-自定义PopupWindow


Android中PopupWindow的用法(位置、动画、焦点)

在Android中有很多级别的Window,不同级别的Window按照z-index方向分布。下面看看Android控件(view)PopupWindow的用法(位置、动画、焦点)。

1、创建PopouWindow及相关参数设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//创建一个包含自定义view的PopupWindow
private PopupWindow makePopupWindow(Context cx) {
PopupWindow window;
window = new PopupWindow(cx);
TextView contentView = new TextView(cx);
contentView.setGravity(Gravity.CENTER);
final Resources res = cx.getResources();
// contentView.setBackgroundColor(R.color.page_window_bgcolor);
// window.setBackgroundDrawable(new
// ColorDrawable(res.getColor(R.color.page_window_bgcolor)));
contentView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT));
//设置PopupWindow显示和隐藏时的动画
window.setAnimationStyle(R.style.AnimationFade);
//设置PopupWindow的大小(宽度和高度)
window.setWidth(res.getDimensionPixelSize(R.dimen.page_window_width));
window.setHeight(res.getDimensionPixelSize(R.dimen.page_window_height));
//设置PopupWindow的内容view
window.setContentView(contentView);
//设置PopupWindow外部区域是否可触摸
window.setOutsideTouchable(true);
return window;
}

2、PopupWindow显示和隐藏的动画设置

XML配置代码:

1
2
3
4
5
<!-- PopupWindow窗口淡入淡出动画 -->
<style name="AnimationFade">
<item name="android:windowEnterAnimation">@anim/fade_in</item>
<item name="android:windowExitAnimation">@anim/fade_out</item>
</style>

JAVA代码:
window.setAnimationStyle(R.style.AnimationFade);

3、PopupWindow的焦点设置

1
2
3
window.setFocusable(true); //设置PopupWindow可获得焦点
window.setTouchable(true); //设置PopupWindow可触摸
window.setOutsideTouchable(true); //设置非PopupWindow区域可触摸

4、PopupWindow的显示及显示位置设置

1
2
window.showAtLocation();
window.showAsDropDown();

下面说说PopupWindow的如何隐藏、显示及显示位置(showAtLocation/showAsDropDown)。

1、PopupWindow的隐藏

1
2
3
4
final PopupWindow window = mPageStatWin;
if(null != window && window.isShowing()) {
win.dismiss();
}

2、PopupWindow的显示及位置设置

window.showAtLocation(parent, Gravity.RIGHT | Gravity.BOTTOM, 10,10);
第一个参数指定PopupWindow的锚点view,即依附在哪个view上。
第二个参数指定起始点为parent的右下角,第三个参数设置以parent的右下角为原点,向左、上各偏移10像素。

1
2
3
4
//将PopupWindow作为anchor的下拉窗口显示。即在anchor的左下角显示
window.showAsDropDown(anchor);
//xoff,yoff基于anchor的左下角进行偏移。
window.showAsDropDown(anchor, xoff, yoff);

如果没有充足的空间显示PopupWindow,那么PopupWindow的左下角将位于anchor的左上角来显示。