一、Android屏幕相关的知识

Android横竖屏设置

Android设置横竖屏的入口多种多样,如下:

1、Activity窗口:应用Mainfest中配置screenOrientation参数、Activity中调用setRequestedOrientation(),这是通过设置Activity的screenOrientation属性

2、系统栏屏幕自动旋转:使用systemui包中的RotationLockTile类的handleClick()方法设置的

3、非Activity窗口:指定WindowManager.LayoutParams.screenOrientation属性

注:屏幕旋转会触发onConfigurationChanged(),如果Activity不设置忽略屏幕方向改变,Activity生命周期会重走,可以按项目需求做相应操作

虽然设置的入口多种多样,中间经过流程也各不相同,但最终的都是调用了PhoneWindowManager的rotationForOrientationLw(int orientation, int lastRotation)的方法(到这一步,已经是最终的切换了,前面还有一些步骤),具体源码就不在贴出,其实大家可以想到,如果修改framework源码,在这里就可实现强制横屏了

Android的屏幕绘制简介

关于android绘制原理比较复杂,特别是具体到View层面,大致就是通过ViewRootImpl与WMS通信(Bind通信),完成performTraversals -> performMeasure() -> performLayout() -> performDraw()流程,最终通过canvs在surface上绘制,生成FrameBuffer去显示,具体细节与本文主题关系不大,暂不深入。时序图如下:

这里我们主要说下view、window、surface、surfaceFlinger的关系:

       View:android 视图组成的基本控件

       Window:屏幕上的某块显示区域,用来承载 View(PhoneWinow就是window的实现类),主要用来提供添加,移除,渲染的能力(继承ViewManager),事件响应,如Toast,状态栏,Activity界面,Dialog,包括锁屏界面(这个有点特殊),window是Z-order的,即window在Z轴是有层级关系的

      Surface:对应一块屏幕缓冲区,每个 window 对应一个 Surface

      SurfaceFlinger:管理surface,Android 的一个服务进程,负责管理 Surface

      WindowManagerService(WMS):Android 框架层的一个服务进程,用来管理 Window

下面三张图可以帮助大家了解下:

Window的层级

通过上面知识,大家了解到window是有层级的,在系统中,WindowManager中使用WindowManager.LayoutParams的type字段来存储window的层级,由于window本身存在父子关系,具体层级关系如下:

窗口层级(type)

层级值

Application windows(应用窗口)

1~99

Sub-windows(子窗口)

1000~1999

System windows(系统窗口)

2000~2999

注意:从表面上看系统窗口 > 子窗口 > 应用窗口,从数值上来说是正确的,但是如果说 Window Layer的层级关系(大部分情况都是按照层级关系),这个说法就是错误的,举个很简单的例子,壁纸层 属于系统窗口管理,但是Window Layer的层级关系 却是最底端;WindowType 的值划分是为了更好的管理Window的类别、权限、依赖关系,和实际的Window Layer层级并没有关系。

从层级到Z-order(android定义的z轴界面层级,有1-33,33级)android有一套对应关系,具体在WindowManagerPolicy的getWindowLayerFromTypeLw()方法中,源码就不贴出了,部分对应和z轴定义如下截图

最终在Framework中计算方式:Layer = Z-Order * 10000 + 1000,即SurfaceFlinger中的混合顺序,我们可以通过adb shell dumpsys SurfaceFlinger来看下层级,下面截图是我在强制横屏demo下场景下截的图(如果window没有长宽,是不会在SurfaceFlinger中显示)

横竖屏设置选项

这里我们介绍下横竖屏的设置选项。默认是unspecified,即由系统决定

注意:虽然Android只提供了几种旋转角度,但其实framework可以设置任意角度

二、强制横屏实现

通过前面知识介绍,我们知道了几种设置横竖屏的方法,这里使用添加高layer的window并设置横竖屏

申请在其他应用上层显示权限

1.判断权限

2.申请权限

添加window并进行横竖屏设置

由于window本身并不是一个真正view,仅仅是个载体,我们需要添加一个长宽均0的view,代码如下:

1.创建布局

2.添加window

这里有个小技巧,我们使用service去实现,并且stopself(),这样状态栏不会有notification。

可能大家会疑惑,为什么我只是使用WindowManger.addview(),并没有创建新的window,其实使用WindowManager 的addview方法,系统会自动创建一个window,可以通过 Android Studio的layout inspector工具查看页面

三、原理介绍

屏幕方向的确定的过程

从上到下遍历窗口堆栈,在可见的窗口中确定一个基准screenOrientation

1、非Activity窗口的screenOrientation如果不是(SCREEN_ORIENTATION_UNSPECIFIED、SCREEN_ORIENTATION_BEHIND)两个值,则结束遍历

2、一旦遍历到一个Activity窗口,接下来仅在Activity窗口中遍历,不再关心非Activity窗口总结来讲就是根据窗口的优先级高低来确定屏幕旋转方向,这也是我们方案的基本原理

转屏的准备

大家可能考虑到,系统检测到要改变屏幕方向,接下来屏幕上能看到的所有窗口都要以新的尺寸来重新绘制,由于各个窗口的重绘不可能在同一时刻完成,也不可能同时刷新,如果我们什么都不做,在屏幕上将会看到各种闪烁。这个应该怎么办?

系统解决方案:

1、截屏保存屏幕状态 (WindowManagerService.screenRotationAnimation())

2、用第一步的截屏生成一个非常高层级的,完全不透明的Layer,让用户在视觉上一直停留在竖屏状态,由于是完全不透明,所以在它下方的所有内容完全不可见,那么就尽情地绘制吧(WindowManagerService .updateRotationUncheckedLocked())

3、方向改变前哪些窗口可见,就必须等待那些窗口绘制完成,这个很好理解

4、截屏Layer为整体,施加旋转并淡出的动画,重绘的所有横屏界面为另一个整体,也施加一个旋转动画,这样当动画结束时看到的就是重绘后的横屏界面。还有一点需要注意,转屏过程中系统会禁用所有其它动画,避免动画的叠加。

(WMS.startAnimation()->
WMS.performSurfacePlacementInner->
WindowAnimator.animateLocked()->
WindowStateAnimator.computeShownFrameLocked())
过程演示图如下:

Android强制系统横屏的原理和实现相关推荐

  1. Android 强制设置横屏或竖屏 设置全屏

    Android 强制设置横屏或竖屏 设置全屏 全屏 在Activity的onCreate方法中的setContentView(myview)调用之前添加下面代码 requestWindowFeatur ...

  2. android 屏幕录制方案,ShareREC for Android全系统录屏原理解析

    本文是Mob开发者平台技术副总监余勋杰基于MediaProjection实现Android全系统录屏功能的原理解析,包括了结合MediaRecorder和MediaCodec两套方案. 文 / 余勋杰 ...

  3. android设置系统横屏方案

    效果如下: 实现方案: 1.ChangeOrientationService.java /*** @描述 强制旋转屏幕服务* @作者 tll* @时间 2018/1/5*/public class C ...

  4. Android强制设置横屏或竖屏

    全屏 在Activity的onCreate方法中的setContentView(myview)调用之前添加下面代码 requestWindowFeature(Window.FEATURE_NO_TIT ...

  5. android 强制设置横屏 判断是横屏还是竖屏

    判断activity 是横屏还是竖屏  方法 1: //根据设备配置信息 Configuration cf= this.getResources().getConfiguration(); //获取设 ...

  6. Android 强制设置横屏或竖屏

    在AndroidManifest.xml的activity节点中设置 横屏: 更改为 android:screenOrientation="landscape" 竖屏:更改为 an ...

  7. Android 系统(57)---深入理解Android输入系统

    <深入理解Android 卷III>第五章 深入理解Android输入系统 <深入理解Android 卷III>即将发布,作者是张大伟.此书填补了深入理解Android Fra ...

  8. 深入Android系统(十二)Android图形显示系统-2-SurfaceFlinger与图像输出

    最近有些忙,切实体验了一把拖更的羞耻感 ( *︾▽︾) 本文和上一篇深入Android系统(十二)Android图形显示系统-1-显示原理与Surface关系比较密切,撸完前篇更易理解本文啦 (๑‾ ...

  9. Android Q 强制黑暗模式(ForceDark) | 原理 实践

    搜狐技术产品(sohu-tech) | 来源 Hi,大家好,这里是承香墨影! Android Q 版本增加了 ForceDark 功能,可以快速实现应用的黑暗模式.本文主要讲述了 Android Q ...

  10. android 版本更新原理,Android系统Recovery工作原理之使用update.zip升级过程分析(二)...

    Android系统Recovery工作原理之使用update.zip升级过程分析(二)---update.zip差分包问题的解决 在上一篇末尾提到的生成差分包时出现的问题,现已解决,由于最近比较忙,相 ...

最新文章

  1. 3种常见的linux版本,查看linux版本的三种常用方法
  2. PHP+MySql获取自动增长字段的新添加记录ID值
  3. git rebase教程
  4. linux小白-基础命令-ls
  5. 现代c++之列表初始化/统一初始化
  6. 在Eclipse中有效使用JUnit
  7. Eigen(1)配置VS2015
  8. 一步步学习SPD2010--第九章节--使用可重用工作流和工作流表单(1)--创建和使用可重用工作流...
  9. 特斯拉开始发布其汽车的开源Linux软件代码
  10. iOS 蓝牙扫描枪功能
  11. 【三角】和差角公式的证明与积化和差和差化积公式的推导
  12. 构建新型现代化智慧博物馆之物联网环境监控方案
  13. 5G 技术特性、频段、架构、部署极5G 手机
  14. KP700 comfort 精致面板与西门子1200CPU进行时钟同步
  15. 多元回归分析(multiple regression)及其应用
  16. Esp8266进阶之路14 esp8266的 FreeRtos系统学习的正确姿势,环境配置环境、烧录。(附带demo)
  17. Mysql数据库SaaS多租户实现方案
  18. 工作中常用的Linux命令(持续更新)
  19. linux查看gc日志,将GC日志输出到文件
  20. 学Python基础面向对象看这一篇文章就够了【全网首推】

热门文章

  1. 大学英语B116-写作
  2. 计算机自动开机什么愿意,电脑自动开关机是什么原因 怎么解决呢
  3. Python 逐行读取txt文件,批量下载文件
  4. 法语计算机相关书籍,法语网络计算机相关词汇
  5. [机器学习与scikit-learn-29]:算法-回归-普通线性回归LinearRegression拟合线性分布数据的代码示例
  6. 行动是最好的告白,钟意社科院杜兰金融管理硕士项目的你不要错过机会
  7. 谷歌浏览器快速保存整个网页的方法
  8. webgl的平行光漫反射示例
  9. 使用QT+webassembly构建在线报表设计器
  10. 《管理者财务知识一本通》读书笔记一