1介绍
android的对话框有两种一种是AlertDialog、另一种就是本文要讲的PopupWindow。
与AlertDialog的区别
- AlertDialog不能指定显示位置,只能默认显示在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。而PopupWindow是可以指定显示位置的,随便哪个位置都可以,更加灵活。
1.1方法
1)构造
public PopupWindow(Context context)
public PopupWindow(View contentView)
public PopupWindow(View contentView, int width, int height)
public PopupWindow(View contentView, int width, int height, boolean focusable)
使用PopupWindow的构造函数必须具有contentView、width、height这三个属性缺一不可。
PopupWindow本身没有布局。所以必须有以上三个属性
如果使用public PopupWindow(Context context)这个构造函数的话当前对象还要添加setContentView、setWidth、setHeight。
View contentView=LayoutInflater.from(MainActivity.this).inflate(R.layout.view_popup, null);
PopupWindow pw= PopupWindow(context);
pw.setContentView(contentView);
pw.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
pw.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
1.2显示
showAsDropDown(View anchor)
:(相对某个控件的位置(正左下方),无偏移)showAsDropDown(View anchor, int xoff, int yoff)
:(相对某个控件的位置,有偏移;xoff表示x轴的偏移,正值表示向左,负值表示向右;yoff表示相对y轴的偏移,正值是向下,负值是向上;)showAtLocation(View parent, int gravity, int x, int y)
:(gravity:相对于父控件的位置(例如正中央Gravity.CENTER
,下方Gravity.BOTTOM
等),可以设置偏移或无偏移)
2例子
View布局:view_test.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:orientation="vertical">
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试1"/>
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试2"/>
<TextView
android:id="@+id/tv_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试3"/>
</LinearLayout>
</RelativeLayout>
activity代码:
privite void showPopWindow(View parent){
View testView= layoutInflater.inflate(R.layout.popupview_renzheng, null);
PopupWindow popupWindow = new PopupWindow(testView, getWindowManager().getDefaultDisplay().getWidth(),android.view.ViewGroup.LayoutParams.WRAP_CONTENT, true);// 创建一个PopuWidow对象
//充满屏幕:ViewGroup.LayoutParams.MATCH_PARENT
popupWindow.setFocusable(true);// 使其聚集
//mPopupWindow.setBackgroundDrawable(getResources().getDrawable(R.mipmap.ic_launcher));设置背景
//popupWindow.getBackground().setAlpha(100); //设置透明度
popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);//防止虚拟软键盘呗弹出菜单遮住
popupWindow.setOutsideTouchable(true);// 设置允许在外点击消失
popupWindow.setFocusable(true);//是否具有获取焦点的能力
popupWindow.setTouchable(true);//是否响应touch事件
popupWindow.setBackgroundDrawable(new BitmapDrawable());// 这个是为了点击“返回Back”也能使其消失,并且并不会影响你的背景
WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
popupWindow.showAsDropDown(parent, 0, 0);//parent父控件
popupWindow.setAnimationStyle(R.style.testStyle);//设置动画所对应的style
TextView test1=testView.findViewById(R.id.tv_1);
text1.setOnClickListener(v -> {
Toast.makeText(this,"测试1",Toast.LENGTH_LONG).show();
popupWindow.dismiss();//关闭
});
}
public void shadowMatch(float b) {//阴影
WindowManager.LayoutParams attributes = getWindow().getAttributes();
attributes.alpha = b;
getWindow().setAttributes(attributes);
}
进出场动画style.xml文件中添加:
<style name="testStyle" parent="@android:style/Animation.Activity">
<item name="android:windowEnterAnimation">@anim/enter_animation</item>
<item name="android:windowExitAnimation">@anim/exit_animation</item>
</style>
anim下新建以下两个布局
<!--进场动画:enter_animation.xml-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000">
<alpha android:fromAlpha="1" android:toAlpha="0"/>
<translate android:fromXDelta="100%p"
android:fromYDelta="100%p"
android:toXDelta="0"
android:toYDelta="0"/>
</set>
<!--离场动画:exit_animation.xml-->
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000">
<alpha android:fromAlpha="0" android:toAlpha="1"/>
<translate android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%p"
android:toYDelta="100%p"/>
</set>
屏蔽返回键与空白键关闭:
//在Android 6.0以上 ,只能通过拦截事件来解决
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
popupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
if ((event.getAction() == MotionEvent.ACTION_DOWN)
&& ((x < 0) || (x >= metrics.widthPixels) || (y < 0) || (y >= metrics.heightPixels))) {
return true;
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
return true;
}
return false;
}
});
}else{//在Android 6.0以下使用
popupWindow.setOutsideTouchable(false);
}
数据获取
// 获取屏幕的width和height
iphoneWidth= getWindowManager().getDefaultDisplay().getWidth();
iphoneHeight= getWindowManager().getDefaultDisplay().getHeight();
//获取pop框的宽和高
popWidth = popupWindow.getWidth();
popHeight = popupWindow.getHeight();