简介

  PopupWindow,顾名思义弹窗.PopupWindow是与AlertDialog在形式上类似的弹窗功能,都是为了在activity最上层显示一个弹窗.但是区别是PopupWindow可以自定义出现的位置,并且可以添加入自己需要的View或者导入自己写好的xml布局

应用场景

  在很多场景下都可以见到它。例如ActionBar/Toolbar的选项弹窗,一组选项的容器,或者列表等集合的窗口等等。

简单的Demo

  为了了解基本的流程,我们来一个最简单demo演示一下.

  创建流程:

  • 用LayoutInflater获得xml布局View .或者直接在代码上new一个View
  • 实例化一个PopupWindow,将View在实例化作为参数传入
  • 配置PopupWindow参数

代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2); TextView textView = new TextView(Main2Activity.this);
textView.setText("测试文本");
final PopupWindow popupWindow = new PopupWindow(textView,200,300);//参数为1.View 2.宽度 3.高度
popupWindow.setOutsideTouchable(true);//设置点击外部区域可以取消popupWindow mTestButton = (Button)findViewById(R.id.test_btn);
mTestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.showAsDropDown(mTestButton);//设置popupWindow显示,并且告诉它显示在那个View下面 }
});
}

效果图:

PopupWindow的配置参数详解

设置内容View

setContentView(View contentView)

除了正常在实例化PopupWindow的时候直接将view传入也可以用这个方法在实例化后重新配置需要的view

设置PopupWindow宽度与高度

setWidth(int width)

setHeight(int height)

除了正常实例化的时候传入宽度与高度,也可以用这个2个方法在实例化后在重新配置需要的宽度与高度

设置PopupWindow背景

setBackgroundDrawable(Drawable background)
final PopupWindow popupWindow = new PopupWindow(textView,200,300);
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(getResources().getDrawable(R.drawable.ic_launcher_background));//设置背景
mTestButton = (Button)findViewById(R.id.test_btn);
mTestButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.showAsDropDown(mTestButton); }
});

设置外部点击退出

setOutsideTouchable(boolean touchable)

这个我在上面的代码已经演示过了

设置PopupWindow可聚焦

setFocusable(boolean focusable)

除了一般的聚焦选中功能,还有一个用处重点!重点!重点!设置了可聚焦后,返回back键按下后,不会直接退出当前activity而是先退出当前的PopupWindow.

设置弹窗弹出的动画高度

setElevation(float elevation)

原本没有设置,弹窗的弹出动画效果位置就只会在控件附件,但是设置后弹窗的起始动画位置就变更远了.请看下面的效果图:

popupWindow.setElevation(1000f);//我将动画位置设置为1000f

设置显示方法

  显示提供了两种形式:

showAtLocation()显示View的内部在指定位置()

  有两个方法重载:

 这个属性一般使用在在整个Activity的window里显示,也就是在整个屏幕内,这个也支持在指定View的内部找到锚点.

 例子1:如果你需要在一个布局的里面的下方显示就只需要设置属性为

   popupWindow.showAtLocation(view,Gravity.BOTTOM,0,0);

 例子2:如果你需要在Activity的window里显示的下方显示就需要设置属性为:

  popupWindow.showAtLocation(activity.getWindow().getDecorView(),Gravity.BOTTOM,0,0);

public void showAtLocation(View parent, int gravity, int x, int y)
public void showAtLocation(IBinder token, int gravity, int x, int y)

showAsDropDown()显示在一个参照物View的外部周围

有三个方法重载:

  注意!这里参照物View的周围,使用这个方法是无法在View的内部找到锚点,它的锚点都是围绕者View的外部四周

public void showAsDropDown(View anchor)
public void showAsDropDown(View anchor, int xoff, int yoff)
public void showAsDropDown(View anchor, int xoff, int yoff, int gravity)

带Gravity参数的方法是API 19新引入的。

这里的xoff与yoff是对应view的坐标偏移量,对应的初始坐标位置是view的左下角.

请注意!在实际使用showAsDropDown()方法的时候,如果只使用showAsDropDown(View anchor, int xoff, int yoff),这个形参会出现在一些品牌的机型上出现一些问题。原因是有些机型初始坐标其实不一定在左下角,而是在左上角。所以,你这个时候设置yoff值就会出现2种不同去情况。怎么解决这个问题呢? 就是尽量使用showAsDropDown(View anchor, int xoff, int yoff, int gravity),这个形参主动设置第4个int gravity的值,来确定初始坐标的位置。

这里我们用一个demo演示一下,假设我现在需要把显示位置移动到目标控件的右上角就需要如下代码:

popupWindow.showAsDropDown(mTestButton,mTestButton.getWidth(),-mTestButton.getHeight())

设置PopupWindow叠放效果

setOverlapAnchor(true);

当然你把PopupWindow的位置设置到可以完全覆盖你指定位置显示PopupWindow的view时,如果设置这个方法为true,那么你无论如何都无法覆盖这个view始终会让这个view漏出一小部分,如效果图所示:

设置PopupWindow可触摸

setTouchable(true);

设置false后,将会阻止PopupWindow窗口里的所有点击事件

设置PopupWindow监听拦截指定触摸事件

popupWindow.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
          //如果这里设置返回true,说明你会消耗这个触摸事件,不会向下传递到内容view里
return false;
}
});

设置PopupWindow覆盖状态栏或者超过屏幕尺寸

允许弹出窗口扩展到屏幕范围之外。默认情况下,窗口被裁剪到屏幕边界。将其设置为false将允许精确定位窗口

popupWindow.setClippingEnabled(false);

设置PopupWindow监听取消事件

popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() { }
});

一些问题总结

解决Android7.0调用showAsDropDown方法失效问题

原理是重写showAsDropDown,将PopupWindow对话框的高度设置成整个屏幕这么大,然后在减去这View指定的底部坐标值。有点治标不治本的味道。

但是,在个别对话框宽度是屏幕的宽度,但是高度是某个View下边与屏幕底部的长度的时候有很好的实现。

如图所示:

没有对话框的时候

有对话框的时候

    @Override
public void showAsDropDown(View anchor) {
if(Build.VERSION.SDK_INT >= 24) {
Rect rect = new Rect();
anchor.getGlobalVisibleRect(rect);
DisplayMetrics outMetrics = new DisplayMetrics();
Context context = anchor.getContext();
((Activity) context).getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics);
int h = outMetrics.heightPixels - rect.bottom;
setHeight(h);
}
super.showAsDropDown(anchor);
}

end

Android 开发 PopupWindow弹窗的更多相关文章

  1. Android开发 PopupWindow弹窗调用第三方地图(百度,高德)实现导航功能

    博客描述:后台返回地点的经纬度在地图上进行描点,点击导航弹出PopupWindow进行选择地图操作,如果手机中没有安装地图,提示没有,否则传值调起地图进行导航操作 看一下实现的效果,没图说再多都白搭 ...

  2. android开发 PopupWindow 设置充满屏幕

    View qrcode_view = this.getLayoutInflater().inflate(R.layout.taskdetail_qrcode,null); final PopupWin ...

  3. Android:PopupWindow简单弹窗改进版

    Android:PopupWindow简单弹窗 继续上一节的内容,改进一下,目标是点击菜单后把菜单收缩回去并且切换内容,我使用的是PopupWindow+RadioGroup public class ...

  4. Android进阶2之PopupWindow弹窗(有点悬浮窗的感觉)

    PopupWindow是一个可以用来显示一个任意的视图的弹出窗口,他需要完全依赖layout布局. 它没什么界面,在弹出的窗口中完全显示布局中的控件. 上面两个美女头就是弹窗PopupWindow显示 ...

  5. Android开发技巧——使用PopupWindow实现弹出菜单

    在本文当中,我将会与大家分享一个封装了PopupWindow实现弹出菜单的类,并说明它的实现与使用. 因对界面的需求,android原生的弹出菜单已不能满足我们的需求,自定义菜单成了我们的唯一选择,在 ...

  6. 【Android开发日记】Popupwindow 完美demo

    Popupwindow 完美demo实现 图示: 关键代码说明: 1.弹出popupwindow,背景变暗 ColorDrawable cd = new ColorDrawable(0x000000) ...

  7. 【Android开发坑系列】之PopupWindow

    PopupWindow在4.0之前的版本有个系统级别的BUG,必须借助一段自定义的fix代码来修复.其中mPopPm就是PopupWindow实例.java.lang.NullPointerExcep ...

  8. 【转】Android开发规范

    转自:https://github.com/Blankj/AndroidStandardDevelop 摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规 ...

  9. 【转】Android 开发规范(完结版)

    摘要 1 前言 2 AS 规范 3 命名规范 4 代码样式规范 5 资源文件规范 6 版本统一规范 7 第三方库规范 8 注释规范 9 测试规范 10 其他的一些规范 1 前言 为了有利于项目维护.增 ...

随机推荐

  1. 2018-2019-2 20165313 《网络对抗技术》 Exp6 信息搜集与漏洞扫描

    一.实践目标 掌握信息搜集的最基础技能与常用工具的使用方法. 二.实践内容. (1)各种搜索技巧的应用 (2)DNS IP注册信息的查询 (3)基本的扫描技术:主机发现.端口扫描.OS及服务版本探测. ...

  2. day1||python

    测试题: 0. Python 是什么类型的语言? Python是一种面向对象.解释型.动态类型计算机程序设计语言解释型:程序无需编译成二进制代码,而是在执行时对语句一条一条编译动态类型:在程序执行过程 ...

  3. 如何让input框显示在一行?

    案例: <input type="float:left" value="aaaa"> <input type="float:left ...

  4. Linux第九节课学习笔记

    fdisk可添加.删除.转换分区. 创建主分区:n-p-w:扩展分区:n-e:逻辑分区:n-l. SWAP分区专用格式化命令mkswap,专用挂载命令swapon. 磁盘容量配额中,硬限制必须,软限制 ...

  5. js数据三大储存格式

    一.String格式  做为一个前端者 你第一手得到的数据都是字符串 二.数组格式 1.定义  var arr=[“张三”,”李四”,”王五”]; 数据通过索引去查找对应的元素   arr[3] 2. ...

  6. BZOJ5311,CF321E 贞鱼

    题意 Problem 5311. -- 贞鱼 5311: 贞鱼 Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 677  Solved: 150[Subm ...

  7. Noname

    版本: LayaAir IDE 2.0.1beta laya.core.js ___Laya ColorUtils LayaGLQuickRunner DrawTextureCmd Point Col ...

  8. Java...点点点语法

    https://blog.csdn.net/IT_faquir/article/details/49131173

  9. 18.11 ROM、RAM、DRAM、SRAM和FLASH区别

    ROM(Read Only Memory)和RAM(Random Access Memory)指的都是半导体存储器.ROM在系统停止供电的时候仍然可以保持数据,而RAM通常都是在掉电之后就丢失数据,但 ...

  10. 亲测实验,stm32待机模式和停机模式唤醒程序的区别,以及唤醒后程序入口

    这两天研究了STM32的低功耗知识,低功耗里主要研究的是STM32的待机模式和停机模式.让单片机进入的待机模式和停机模式比较容易,实验中通过设置中断口PA1来响应待机和停机模式. void EXTI1 ...