Android-----PopupWindow

本文详细探讨了Android中PopupWindow的使用,包括如何创建、显示PopupWindow,以及设置显示位置,如相对于当前控件和窗口。此外,还讨论了如何隐藏PopupWindow,管理其状态,忽略CheekPress事件以及解决与NavigationBar重叠的问题。对于Android开发者来说,掌握这些内容能提升UI交互的用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.创建
一般用的构造方法

//创建一个空的PopupWindow
PopupWindow()

//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.依附某个控件 showAsDropDown
b.设置屏幕坐标 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时将不会与导航栏重叠



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值