先来看一下PopupWindow的描述:
A popup window that can be used to display an arbitrary view. The popup window is a floating container that appears on top of the current activity.PopupWindow 是弹出窗口,可以用来显示任意一个视图。出现的弹出窗口是一个在当前Activity之上的浮动容器。
PopupWindow常用的构造方法:
- PopupWindow(Context context)
Create a new empty, non focusable popup window of dimension (0,0).参数为上下文,创建一个高宽为0 的没有焦点的PopupWindow
Create a new empty, non focusable popup window of dimension (0,0).无参,创建一个高宽为0 的没有焦点的PopupWindow
- PopupWindow(View contentView)
Create a new non focusable popup window which can display the contentView.参数为要显示的View,即PopupWindow要显示的视图
- PopupWindow(int width, int height)
Create a new empty, non focusable popup window.参数为要显示的View的宽度和高度
- PopupWindow(View contentView, int width, int height)
Create a new non focusable popup window which can display the contentView.参数为要显示的View,宽度和高度
PopupWindow常见方法:
- dismiss()使PopupWindow消失
- getWidth()得到PopupWindow宽度
- getHeight()得到PopupWindow高度
- isOutsideTouchable()设置popupwindow外部可点击
- setAnimationStyle(int animationStyle)为PopupWindow设置动画效果
- setContentView(View contentView)如果不在构造方法中指定要显示的View,则可以使用此方法
- setHeight(int height)设置PopupWindow高度,如果当前的PopupWindow正显示,那么下次显示时才会有效
- setWidth(int width)设置PopupWindow宽度,如果当前的PopupWindow正显示,那么下次显示时才会有效
- showAsDropDown(View anchor)指定PopupWindow显示在控件的左下方
- showAsDropDown(View anchor, int xoff, int yoff)
- showAsDropDown(View anchor, int xoff, int yoff, int gravity)
(和上面的方法一样,虽然多了一个参数,但貌似官方文档上对其描述都一样)
- showAtLocation(View parent, int gravity, int x, int y)
随意指定啦
- setBackgroundDrawable(Drawable background)设置PopupWindow背景,可为NULL
其实PopupWindow的基本设置都大同小异,关键还在于要显示的contentView和其显示的位置,contentView中你可以随意布局,
添加各种效果,满足项目
需要。
注意:popupwindow中包含Spinner时,点击Spinner的时候会报错,在spinner的xml中添加一个属性:
android:spinnerMode="dialog"即可(公司项目也曾遇到类似情况)
先看一下最常见的一种
效果图:
private void setMyPop(){
mPopTop = new PopupWindow(context);
int w = ScreenUtils.getScreenWidth(context);
int h = ScreenUtils.getScreenHeight(context);
mPopTop.setWidth(w / 2);
mPopTop.setHeight(LayoutParams.WRAP_CONTENT);
mPopTop.setFocusable(true);获取焦点
mPopTop.setTouchable(true);
mPopTop.setOutsideTouchable(true);//设置popupwindow外部可点击
// mPopTop.update();// 刷新状态
ColorDrawable dw = new ColorDrawable(0000000000);// 实例化一个ColorDrawable颜色为半透明
mPopTop.setBackgroundDrawable(dw);// 点back键和其他地方使其消失,设置了这个才能触发OnDismisslistener ,设置其他控件变化等操作
mPopTop.setAnimationStyle(R.style.AnimationPreview);//设置显示和消失动画
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View conentView = inflater.inflate(R.layout.pop_top, null);
setContentViewClickListener(conentView);
mPopTop.setContentView(conentView);
}
在上面的代码中对PopupWindow进行了一些常用设置,包括主要的高度宽度设置,要显示的View以及动画效果等等。
conentView的XML代码:
<?xml version="1.0" encoding="utf-8"?>
<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="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/pop_layout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:alpha="0.8"
android:background="@drawable/popover_background"
android:gravity="center_horizontal"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/lin_car_empty"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="8dp" >
<TextView
android:id="@+id/tv_car_empty"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:text="空车"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0.1dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:background="@drawable/divider_horizontal_line" />
<LinearLayout
android:id="@+id/lin_car_half"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="8dp" >
<TextView
android:id="@+id/tv_car_half"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:text="半载"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0.1dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:background="@drawable/divider_horizontal_line" />
<LinearLayout
android:id="@+id/lin_car_full"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="8dp" >
<TextView
android:id="@+id/tv_car_full"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:text="满载"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0.1dp"
android:layout_marginLeft="0dp"
android:layout_marginRight="0dp"
android:background="@drawable/divider_horizontal_line" />
<LinearLayout
android:id="@+id/lin_car_rest"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:padding="8dp" >
<TextView
android:id="@+id/tv_car_rest"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginLeft="10dp"
android:gravity="center"
android:text="勿扰"
android:textColor="#FFFFFF"
android:textSize="18sp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
setContentViewClickListener(conentView)是为要显示的View设置点击事件(在这里添加业务逻辑),我这里只是简单的Toast。
private void setContentViewClickListener(View conentView){
LinearLayout lin_car_full = (LinearLayout) conentView
.findViewById(R.id.lin_car_full);
LinearLayout lin_car_empty = (LinearLayout) conentView
.findViewById(R.id.lin_car_empty);
LinearLayout lin_car_half = (LinearLayout) conentView
.findViewById(R.id.lin_car_half);
LinearLayout lin_car_rest = (LinearLayout) conentView
.findViewById(R.id.lin_car_rest);
lin_car_empty.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
T.showLong(context, "空车");
mPopTop.dismiss();
}
});
lin_car_full.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
T.showLong(context, "满载");
mPopTop.dismiss();
}
});
lin_car_half.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
T.showLong(context, "半载");
mPopTop.dismiss();
}
});
lin_car_rest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
T.showLong(context,"勿扰");
mPopTop.dismiss();
}
});
}
然后调用,使其显示出来。
mPopTop.showAsDropDown(rel_titlebar, ScreenUtils.getScreenWidth(context)/4, 0); //titleBar 正下方中间位置
或者
mPopTop.showAtLocation(rel_titlebar, Gravity.TOP, 0, height +ScreenUtils.getStatusHeight(context)); //titleBar 正下方中间位置
说明:
ScreenUtils.getStatusHeight(context)为状态栏的高度
rel_titlebar即titleBar
height为titleBar的高度,
关于测量控件的高度宽度,下面是具体代码
//测量titleBar高度
ViewTreeObserver vto = rel_titlebar.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
if (hasMeasured == false) {
height = rel_titlebar.getMeasuredHeight();
// int width = rel_titlebar.getMeasuredWidth();
// 获取到宽度和高度后,可用于计算
hasMeasured = true;
}
return true;
}
});
如果调用
mPopTop.showAsDropDown(rel_titlebar);//titleBar 正左下方
则会显示在正左下方:
还有的PopupWindow是全屏显示的
private void showFullPop() {
View view = LayoutInflater.from(this).inflate(R.layout.pop_full,
null);
LinearLayout layout_all;
RelativeLayout layout_choose;
RelativeLayout layout_photo;
RelativeLayout layout_cancel;
layout_choose = (RelativeLayout) view.findViewById(R.id.layout_choose);
layout_photo = (RelativeLayout) view.findViewById(R.id.layout_photo);
layout_cancel=(RelativeLayout) view.findViewById(R.id.layout_cancel);
layout_photo.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
T.showLong(context,"点击拍照");
mPopBottom.dismiss();
}
});
layout_choose.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
T.showLong(context,"点击相册");
mPopBottom.dismiss();
}
});
layout_cancel.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
T.showLong(context,"点击取消");
mPopBottom.dismiss();
}
});
mPopBottom = new PopupWindow(view);
// mPopBottom.setTouchInterceptor(new OnTouchListener() {
// @Override
// public boolean onTouch(View v, MotionEvent event) {
// if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
// mPopBottom.dismiss();
// return true;
// }
// return false;
// }
// });
mPopBottom.setWidth(WindowManager.LayoutParams.MATCH_PARENT);
mPopBottom.setHeight(WindowManager.LayoutParams.MATCH_PARENT);
mPopBottom.setTouchable(true);
mPopBottom.setFocusable(true);
mPopBottom.setOutsideTouchable(true);
ColorDrawable dw = new ColorDrawable(0000000000);
mPopBottom.setBackgroundDrawable(dw);
// 动画效果 从底部弹起
mPopBottom.setAnimationStyle(R.style.Animations_GrowFromBottom);
mPopBottom.showAtLocation(rel_titlebar, Gravity.BOTTOM, 0, 0);//parent view随意
}
注意这里我们设置View的高度和宽度都为MATCH_PARENT,设置的动画效果为从底部弹出。
效果图:
在布局中添加一个ListView,然后给ListView设置点击事件:
lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
int[] location = new int[2];
view.getLocationOnScreen(location);
mPopTop.showAtLocation(view, Gravity.NO_GRAVITY, ScreenUtils.getScreenWidth(context) / 4, location[1]);
// mPopTop.showAtLocation(view, Gravity.NO_GRAVITY,ScreenUtils.getScreenWidth(context) / 4, location[1]);
}
});
说明:
通过view.getLocationInWindow(location); 获取控件在屏幕内的绝对坐标,location[0]为X坐标值,location[1]为Y坐标值。
这里只是为了演示,没有设置新的PopupWindow,关于PopupWindow的位置,你可以根据项目的实际情况,指定其显示在Item的上面或者下面,或者任意位置。
效果图:
另外,如果你想在PopupWindow中显示gridView之类更复杂的View,只需在XML中布局或者在Java代码中动态布局就可以了。