博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]Android 之 Window、WindowManager 与窗口管理
阅读量:6499 次
发布时间:2019-06-24

本文共 4511 字,大约阅读时间需要 15 分钟。

这篇是对前两天研究的悬浮窗的内容的一个小小的资料整理吧。首先是转载一篇介绍Android窗口的内容,觉得写得不错:

为防止丢失还是把内容也拷一遍吧(*^__^*) 嘻嘻……

其实在android中真正展示给用户的是window和view,activity在android中所其的作用主要是处理一些逻辑问题,比如生命周期的管理、建立窗口等。在android中,窗口的管理还是比较重要的一块,因为他直接负责把内容展示给用户,并和用户进行交互。响应用户的输入等。

在讲窗口管理时,有必要先说下ViewManager这个接口,这个接口主要有以下的实现子接口和实现类,分别是:WindowManager和ViewGroup里面还有三个重要的方法:

  • addView(); 
  • updateViewLayout();
  • removeView();

在WindowManager中,addView方法表示的是将主窗口中的顶级view(也就是DecorView)添加到WindowManager中,并建立会话。接下来会详细介绍。我们先来看看Window

Window:

Windowandroid中的窗口,表示顶级窗口的意思,也就是主窗口,它有两个实现类,PhoneWindowMidWindow,我们一般的activity对应的主要是PhoneWindow,在activity中经常使用的setContentView等方法也是在这个里面实现的。

1 @Override 2 public void setContentView(View view,ViewGroup.LayoutParams params)  3 { 4      if (mContentParent == null)  5     { 6         installDecor(); 7     }  8     else  9     {10         mContentParent.removeAllViews();11     }12     mContentParent.addView(view, params);13     final Callback cb = getCallback();14     if (cb != null) 15     {16            cb.onContentChanged();  //窗口类容发生变化时更新17     }18 }
View Code

 每个主窗口中都有一个View,称之为DecorView,是主窗口中的顶级view(实际上就是ViewGroup),在View中有两个成员变量叫做mParent、mChildren,它是用来管理view的上下级关系的。而ViewGroup是对一组View的管理。因此,在ViewGroup中建立了所有view的关系网。而最终ViewGroup附属在主窗口上。这样就很容易在窗口中通过findViewById找到具体的View了。view中的事件处理也是根据这个路径来处理的。

我们再来看看ActivityThead中的两个重要的方法(至于ActivityThead将在一篇中详细介绍):

  • performLaunchActivity( );
  • handleResumeActivity( );

在performLaunchActivity中,会调用activity.attach方法建立一个window, 在handleResumeActivity方法中启动activity的时候,会将主窗口加入到WindowManager中

1 View decor =r.window.getDecorView();  //获得窗口的顶级View 2 decor.setVisibility(View.INVISIBLE); 3 ViewManager wm= a.getWindowManager(); //WindowManager继承自ViewManager 4 WindowManager.LayoutParams l= r.window.getAttributes(); 5  6 a.mDecor = decor; 7 l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; 8 l.softInputMode |= forwardBit; 9 10 if (a.mVisibleFromClient) 11 {12          a.mWindowAdded = true;13          wm.addView(decor, l);  //实际上是把主窗口的顶级view加入到WindowMangaer14 }
View Code

我们再来看看WindowManager。

WindowManager:

WindowManager主要用来管理窗口的一些状态、属性、view增加、删除、更新、窗口顺序、消息收集和处理等。

通过Context.getSystemService(Context.WINDOW_SERVICE)的方式可以获得WindowManager的实例.

WindowManager继承自ViewManager,里面涉及到窗口管理的三个重要方法,分别是:

  • addView(); 
  • updateViewLayout();
  • removeView();  

WindowManager中还有一个重要的静态类LayoutParams.通过它可以设置和获得当前窗口的一些属性。

我们先来看看addView()方法,在addView中,会利用LayoutParams获得window的View属性,并为每个window创建ViewRoot,ViewRoot是View和WindowManager之间的桥梁,真正把View传递给WindowManager的是通过ViewRoot的setView()方法,ViewRoot实现了View和WindowManager之间的消息传递。在将主窗口添加到WindowManger时,它首先会建立一个代理对象:

              wm=(WindowManagerImpl)context.getSystemService(Context.WINDOW_SERVICE)

并且打开会话(IWindowSession),之后Window将通过该会话与WindowManager建立联系,

来看下setView方法:

1 try  2 { 3     res =sWindowSession.add(mWindow, mWindowAttributes, 4     getHostVisibility(), mAttachInfo.mContentInsets); 5 }  6 catch (RemoteException e)  7 { 8     mAdded = false; 9     mView = null;10     mAttachInfo.mRootView =null;11     unscheduleTraversals();12     throw newRuntimeException("Adding window failed", e);13 } 14 finally 15 {16     if (restore) 17     {18         attrs.restore();19     }20 }
View Code

在这段代码中,ViewRoot通过IWindowSession把窗口添加到WindowManager中。ViewRoot继承了Handler,实际上它的本质就是一个Handler,窗口中View的事件处理、消息发送、回调等将通过ViewRoot来处理。

这样就完成了把窗口添加到WindowManager中,并交由WindowManager来管理窗口的view、事件、消息收集处理等。

 

知道原理之后添加悬浮窗的工作就比较简单了,主要关键点有以下几个:

1. 首先是AndroidManifest.xml文件中添加权限<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

2. 获取WindowManager窗口mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);

3. 设置窗口属性:

1 //设置window type   2 wmParams.type = LayoutParams.TYPE_PHONE;    3 //设置图片格式,效果为背景透明   4 wmParams.format = PixelFormat.RGBA_8888;    5 //设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)   6 wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;         7 //调整悬浮窗显示的停靠位置为左侧置顶   8 wmParams.gravity = Gravity.LEFT | Gravity.TOP;          9 // 以屏幕左上角为原点,设置x、y初始值,相对于gravity  10 wmParams.x = 0;  11 wmParams.y = 0;  12   13 //设置悬浮窗口长宽数据    14 wmParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  15 wmParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  16   17  /*// 设置悬浮窗口长宽数据 18 wmParams.width = 200; 19 wmParams.height = 80;*/  20      21 LayoutInflater inflater = LayoutInflater.from(getApplication());  22 //获取浮动窗口视图所在布局  23 mFloatLayout = (LinearLayout) inflater.inflate(R.layout.float_layout, null);  24 //添加mFloatLayout  25 mWindowManager.addView(mFloatLayout, wmParams);
View Code

转载于:https://www.cnblogs.com/Pitty/articles/3861211.html

你可能感兴趣的文章
dotConnect for Oracle
查看>>
Eclipse下C/C++开发环境搭建
查看>>
Eclipse中设置在创建新类时自动生成注释
查看>>
我的友情链接
查看>>
CoreOS 手动更新
查看>>
golang 分页
查看>>
再论机械式针对接口编程
查看>>
25 个 Linux 性能监控工具
查看>>
C#程序员整理的Unity 3D笔记(十三):Unity 3D基于组件的思想
查看>>
Tengine-2.1.1 ngx_http_concat_module 400问题
查看>>
Windows中挂载安装ISO文件
查看>>
Wayland 1.0发布
查看>>
golang的goroutine是如何实现的?
查看>>
乐视云基于Kubernetes的PaaS平台建设
查看>>
R 学习笔记《十》 R语言初学者指南--图形工具
查看>>
PHP通过读取DOM抓取信息
查看>>
DICOM医学图像处理:DICOM网络传输
查看>>
nio和传统Io的区别
查看>>
移动端网页布局中需要注意事项以及解决方法总结
查看>>
(原创)Linux下查看系统版本号信息的方法
查看>>