文档章节

android的WindowManager.addView弹窗添加

小米墨客
 小米墨客
发布于 2015/09/25 18:24
字数 1074
阅读 429
收藏 0

touch here android在WindowManager添加View 作者:feiyangxiaomi

[TOC]

#1. 事情的起因 项目的驱动,希望提供一个弹窗,这个弹窗的特点是:

  • 非阻塞试弹窗,弹窗弹出的时候,点击弹窗外的屏幕区域,--不选PopupWindow(开源项目QuickAction不能用)
  • 弹窗需要内部能够点击某一项并做出相应,--不选Toast

此时考虑在界面上加入一个View,通过WindowManager.addView方法去添加弹出图层,这里先贴出一个图,看一下这个效果是否是你的菜: //截图 效果

#2. 为什么选择WindowManager.addView WindowManager用来在应用与window之间的管理接口,管理窗口顺序,消息等。对于windowManager来说一个系统只有一个,它是由系统底层实现的,用于负责调度当前显示那个窗口,消息处理我们获得一个windowManager的方式如下:

WindowManager windowManager = (WindowManager)context().getSystemService(Context.WINDOW_SERVICE);

调用比较简单。

#3.代码实现 把这个弹窗叫做PopupAction,后面统一为这个称呼。 ##显示PopupAction代码

    /**
     * Show quick menu popup. Popup is automatically positioned, on top of anchor view. Calc of anchor and mRootView
     * view for look out the poosition. Every side margin of 10dp and the arrow at the top of anchor.
     * 
     * @param context the global information about an applicaion environment
     * @param anchor view of call for
     * @param actions action list items {@link #addActionItem(List)}
     */
    public void show(Context context, View anchor, List<ActionItem> actions) {
        mContext = context;
        if (mContext == null) {
            Log.i("MenuDialog", "context is null");
            return;
        }
        int xPos;
        int yPos;
        int arrowPos;
        int[] location = new int[2];
		
		//添加菜单项
        addActionItem(actions);
		
        mShowAction = true;
		//计算要弹出的位置
        anchor.getLocationOnScreen(location);
        Rect anchorRect =
                new Rect(location[0], location[1], location[0] + anchor.getWidth(), location[1] + anchor.getHeight());

        int rootHeight = mRootView.getMeasuredHeight();
        int rootWidth = mRootView.getMeasuredWidth();

        xPos = anchorRect.centerX() - (rootWidth / 2);
		
        //对弹窗靠近左边和右边的处理
        if (xPos < 20) {
            xPos = 20;
        }
        DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
        if ((dm.widthPixels - anchorRect.centerX()) < rootWidth / 2) {
            xPos = dm.widthPixels - rootWidth - 20;
        }
        arrowPos = anchorRect.centerX() - xPos;
        yPos = anchorRect.top - rootHeight;
		
		//设置箭头位置
        showArrow((R.id.arrow_down), arrowPos);
		
		//添加图层弹窗
        android.view.WindowManager.LayoutParams params =
                (android.view.WindowManager.LayoutParams) mRootView.getLayoutParams();

        params.x = xPos;
        params.y = yPos;
        mWM.addView(mParentView, params);
        mParentView.addView(mRootView);
        mParentView.setOnTouchListener(this);

		//设置弹出动画
        Animation animationUp = AnimationUtils.loadAnimation(mContext, R.anim.grow_from_bottom);
        mRootView.startAnimation(animationUp);
    }

其中初始化View,添加菜单项和设置点击菜单项的点击回调,参考QuickAction的代码,这里不再介绍。

#4.本文的目标点 ##WindowManager和WindowManager.LayoutParams

  1. 添加的view不显示,引出WindowManager.LayoutParams用什么type?
  2. 属性WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,如何响应点击outside和back键盘?可以看下stackoverflow很有意思
  3. 属性WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY能不能用? 对于WindowManager.LayoutParams配置代码:
	mParams = new WindowManager.LayoutParams();
	mParams.height = LayoutParams.WRAP_CONTENT;
	mParams.width = LayoutParams.WRAP_CONTENT;
	mParams.format = PixelFormat.TRANSLUCENT;
	mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
	mParams.flags =
			WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
	mParams.gravity = Gravity.TOP | Gravity.LEFT;
	mRootView.setLayoutParams(mParams);

可以看到这里使用的type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;,后面介绍一下几种类型。 flag使用

  • LayoutParams.FLAG_NOT_TOUCH_MODAL表示可以点击弹窗之外的屏幕区域,这是必须的。
  • LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH表示可以监听外部点击事件,这时候可以dismiss掉当前的弹窗,也是必需的。
  • WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 表示当前弹窗捕获得焦点,但能点击,非常重要。不然键盘区域的所有touch事件都会收不到。

|Constants|| |---|--| |TYPE_ACCESSIBILITY_OVERLAY|窗口重叠仅由AccessibilityService截取用户交互,而不改变窗口的无障碍服务可以内省。| |TYPE_APPLICATION|应用窗口| |TYPE_APPLICATION_ATTACHED_DIALOG|和TYPE_APPLICATION_PANEL类似,但是不作为一个应用的一部分,显示在窗口的顶层| |TYPE_APPLICATION_PANEL|应用顶层图层| |TYPE_APPLICATION_MEDIA|播放器图层| |TYPE_APPLICATION_STARTING|应用开始事的图层| |TYPE_APPLICATION_SUB_PANEL|应用子面板| |TYPE_PHONE |电话图层,部分手机无法使用,已测试| |~|| |TYPE_SYSTEM_ALERT|系统通知,使用时发现该图层会独立在应用之上| |TYPE_SYSTEM_DIALOG|系统对话框,使用时发现该图层会独立在应用之上| |TYPE_SYSTEM_ERROR|系统错误,非常靠上| |TYPE_SYSTEM_OVERLAY|系统普通图层| |TYPE_TOAST|系统toast| 参考网上实例的时候,建议不要采用系统图层,网上的好多实例都是采用:TYPE_SYSTEM_ALERT,不合理。

###WindowManager.addView的动画效果 动画部分可以采用: WindowManager.windowAnimations=R.style.xxx但是不建议使用,该资源在官网上说是鼻息使用系统资源,因为window manager拿到应用的资源。 那怎么办?参考:WindowManager with Animation (is it possible?) 代码如下所示:

	mParentView = new FrameLayout(mContext);
	mWM.addView(mParentView, params);
	mParentView.addView(mRootView);
	Animation animationUp = AnimationUtils.loadAnimation(mContext, R.anim.grow_from_bottom);
	mRootView.startAnimation(animationUp);

借助于ViewGroup(定义的mParentView),使用动画效果,小技巧很不错。

#参考

  1. QuickAction
  2. WindowManager with Animation (is it possible?)
  3. 官方文档

© 著作权归作者所有

小米墨客
粉丝 67
博文 16
码字总数 65581
作品 0
海淀
程序员
私信 提问
Activity、Window、View三者关系

目录介绍 01.Window,View,子Window 02.什么是Activity 03.什么是Window 04.什么是DecorView 05.什么是View 06.关系结构图 07.Window创建过程 08.创建机制分析 8.1 Activity实例的创建 8.2 ...

潇湘剑雨
05/29
11
0
Android窗口机制(四)ViewRootImpl与View和WindowManager

Android窗口机制系列 Android窗口机制(一)初识Android的窗口结构 Android窗口机制(二)Window,PhoneWindow,DecorView,setContentView源码理解 Android窗口机制(三)Window和WindowMan...

亭子happy
02/26
14
0
bugly的flutter版已完成,欢迎使用

目前支持Android(更新统计、原生异常上报、flutter异常上报)、iOS(统计、原生异常上报、flutter异常上报) 项目地址:github.com/crazecoder/… 一、引入 二、项目配置 在android/app/bui...

用户未登录
01/22
0
0
Android 与 WebView 数据交互

1. 创建Android 项目 打开Android Studio 创建一个空的Android项目 打开Android虚拟机,这里使用的是Genymotion 2. 添加webview 清空layout内容,添加WebView控件 此时运行项目,发现android...

塔歌
2018/07/24
0
0
混子前端在开发公众号嵌套webview遇到的常见问题

相信很多前端伙伴在开发手机端总会遇到这样那样的一些兼容坑,无论是在开发微信小程序 公众号嵌套webview 还是原生内嵌App,那混子前端之前在开发公众号嵌套webview 时遇到了几个常见问题,在...

Terrence Lu
06/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
7
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
10
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
9
0
前端——使用base64编码在页面嵌入图片

因为页面中插入一个图片都要写明图片的路径——相对路径或者绝对路径。而除了具体的网站图片的图片地址,如果是在自己电脑文件夹里的图片,当我们的HTML文件在别人电脑上打开的时候图片则由于...

被毒打的程序猿
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部