Android中的PopupWindow
上来先说我遇到的问题:
需求:点击按钮实现PopupWindow弹窗并加载动画
(很简单的需求,可是我却踩到了很多的坑)
坑:
1.控制PopupWindow的位置
2.点击PopupWindow外部区域,消失
3.PopupWindow中条目的加载动画(布局的书写,展示不同的动画效果)
说实话,PopubWindow真的是我的弱实力群体里边的。昨天我们公司的android实习生想实现一个效果,如图:
很简单吧,就是一个PopubWindow,里边附带了几条item(item有动画。就是这么简单)。难道是我太笨了?搜索大脑的记忆,竟然没有一点关于
PopupWindow的东西。what?
没办法了,google吧。一阵搜索之后,写出了如下的demo
public class MainActivity extends AppCompatActivity {
private LinearLayout ll1,ll2,ll3;
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
View convertView = inflater.inflate(R.layout.popup_layout,null);
final PopupWindow popupWindow = new PopupWindow();
popupWindow.setContentView(convertView);
popupWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
popupWindow.setFocusable(true);
/**
* 解决坑2
* 如果想点击屏幕外部区域PopupWindow消失,
* 必须设置以下两个属性,且必须在showAsDropDown()/showAtLocation()方法之前
*/
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.popup_bg));
popupWindow.setOutsideTouchable(false);
//解决坑1
popupWindow.showAsDropDown(btn);
ll1 = convertView.findViewById(R.id.ll1);
ll2 = convertView.findViewById(R.id.ll2);
ll3 = convertView.findViewById(R.id.ll3);
ObjectAnimator anim1 = ObjectAnimator.ofFloat(ll1,"translationY",-UIHelper.dip2px(MainActivity.this,60),0).setDuration(1000);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(ll2,"translationY",UIHelper.dip2px(MainActivity.this,0),UIHelper.dip2px(MainActivity.this,60)).setDuration(1000);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(ll3,"translationY",UIHelper.dip2px(MainActivity.this,0),UIHelper.dip2px(MainActivity.this,120)).setDuration(1000);
anim1.start();
anim2.start();
anim3.start();
}
});
}
}
------------------------------------------------------------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<!--
解决坑3
我在外边嵌套了一层FrameLayout先把PopupWindow的布局撑起来
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="180dp">
<RelativeLayout
android:id="@+id/ll_popup"
android:layout_width="130dp"
android:layout_height="180dp"
android:layout_gravity="right">
<LinearLayout
android:id="@+id/ll1"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#00ff00"
android:orientation="vertical"/>
<LinearLayout
android:id="@+id/ll2"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#f0d0f0"
android:orientation="vertical"/>
<LinearLayout
android:id="@+id/ll3"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#0000ff"
android:orientation="vertical"/>
</RelativeLayout>
</FrameLayout>
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下是PopupWindow知识整理:
PopupWindow是对于屏幕添加一个显示区域,由于对位置和内容都非常自由所以常常在开发中用到。
其中很重要的两个方法
随意更换位置很重要的两个方法
showAsDropDown(View anchor) 相对于某个控件的位置,无偏移
showAsDropDown(View anchor,int xoff,int yoff) 相对于某个控件的位置,同事可以设置偏移
showAtLocation(View parent,int gravity,int x,int y) 相对于父控件的位置,同时可以设置偏移量
1.创建
一般用的构造方法
//创建一个空的PopupWindowPopupWindow()
//contentView PopupWindow内部的布局内容PopupWindow(View contentView)
// 指定PopupWindow的宽,高PopupWindow(int width,int height)
//接收四个参数//View contentView PopupWindow内部的布局内容//int width,height PopupWindow的宽,高//boolean focusable 是否获取焦点PopupWindow(View contentView,int width,int height,boolean focusable)
通过上下文创建PopupWindow,创建后默认有一个透明的背景,默认宽高(0,0),没有内容和焦点的PopupWindow。具体作用我也不知道,估计是写自定义控件的吧,但是PopupWindow并没有继承View,一般不使用该构造。
PopupWindow(Context context)PopupWindow(Context context,AttributeSet attrs)PopupWindow(Context context,AttributeSet attrs,int defStyleAttr)PopupWindow(Context context,AttributeSet attrs,int defStyleAttr,int defStyleRes)
创建PopupWindow必要的三个条件void setHeight(int height)void setWidth(int width)void setContentView(View contentView)缺少一个就无法显示
前面提到PopupWindow需要设置宽高,那如果想用布局中的宽高怎么办呢?可以用到LayoutParams.WRAP_CONTENT 包裹布局,布局多大就显示多大的PopupWindow
2.显示
显示PopupWindow可以分为两种方式a.依附某个控件 showAsDropDownb.设置屏幕坐标 showAtLocation
a.相对于当前控件
默认是PopupWindow的左上角对齐控件的左下角,或者设置Gravity.RIGHT,PopupWindow的右上角对齐控件的右下角
不存在Gravity.TOP或Gravity.BOTTOM效果
//弹窗显示在anchor控件左下方void showAsDropDown(View anchor)//以控件左下角为原点的偏移坐标void showAsDropDown(View anchor,int xoff,int yoff)//以控件哪个位置为原点进行偏移void showAsDropDown(View anchor,int xoff,int yoff,int gravity)
b.相对于当前窗口
当前窗口的任意位置(不包括状态栏)
//相对当前窗口//parent:该属性主要是当前任意控件对象即可(View和ViewGroup都行),该参数主要是为了得到该对象的getWindowToken()方法//gravity 屏幕位置//x,y 偏移坐标void showAtLocation(View parent,int gravity,int x,int y)
需要注意的是多次调用show方法,只会执行第一句mPopupWindow.showAtLocation(popupwindow, Gravity.TOP, 100, 0); // 只有该行生效mPopupWindow.showAtLocation(popupwindow, Gravity.LEFT, 100, 0);mPopupWindow.showAtLocation(popupwindow, Gravity.RIGHT, 100, 0);mPopupWindow.showAtLocation(popupwindow, Gravity.BOTTOM, 100,
3.隐藏PopupWindow
小心,这里有一个坑这里有一个方法,setOutSideTouchable(boolean)android 6.0 系统以上 直接setOutsideTouchable(true);点击popupwindow外部会消失adnroid 6.0 系统之前setBackgroupDrawable(new ColorDrawable(0x00000000));setOutsideTouchable(true);
且,必须设置在showAsDropDown()/showAtLocation()方法调用之前
4.状态
a.可被点击//判断是否可被点击boolean isTouchable()//设置是否可点击void setTouchable(boolean touchable)b.多点触控//判断是否多点触控boolean isSplitTouchEnabled()//设置是否多点触控void setSplitTouchEnabled()
5.忽略CheekPress事件
当物体触摸在屏幕上的尺寸超过手指尺寸范围,将被判定为CheekPress事件(脸颊点击)void setIgnoreCheekPress() //默认为false,既不忽略
6.解决NavigationBar重叠
这是Android5.5(API22)后添加的方法,默认为truue,为true时将不会与导航栏重叠