iis服务器助手广告广告
返回顶部
首页 > 资讯 > 移动开发 >结合Windows窗口深入分析Android窗口的实现
  • 526
分享到

结合Windows窗口深入分析Android窗口的实现

Android窗口Android窗口机制 2023-05-16 11:05:45 526人浏览 独家记忆
摘要

目录前言对于Window的认识阶段寻找真正的WindowWindow到底是什么Activity-Window-View的关系前言 从windows窗口的概念开始,通过对比去理解And

前言

windows窗口的概念开始,通过对比去理解Android窗口体系,本文没有深入源码,重在理解概念

代码都是抄来抄去,概念也是互相借鉴 🐶,先看看Windows窗口的一些概念。

概念如下:

是我们使用软件时看到的界面,包含各种各样的控件,与用户交互

窗口有三种类型: 系统窗口类,应用程序全局窗口,应用程序局部窗口

窗口具有Z轴层级

可以设置窗口的大小与位置

平时打开文件夹,微信网易云,AndroidStudio都是打开一个窗口。

了解Android窗口的同志们可能会感觉到Windows窗口的概念好熟悉呀。

窗口这个概念在Android中并不清晰,手机移动终端屏幕太小。很少有机会和Windows一样一块屏幕同时展示多个窗口。

操作也不一样,在Windows中可以随意对 不同窗口调整,最大化最小化,拖拽,改变尺寸,切换窗口巴拉巴拉的一顿操作。

所以Windos天生就更容易理解窗口,毕竟能够直接操作。打开微信和网易云一眼就能看出 这是两个窗口。

Windows先放一哈,视线会到Android,看一个情景,包含:Activity,Dialog,Toast。 问:图里有几个窗口

答:三个,Activity应用窗口,Dialog子窗口,Toast系统窗口。

如果没看过源码的同志肯定会犹豫,说到底还是移动端手机屏幕太小了,没办法给人直观感性的认识窗口。

通过对比还是看出窗口的一些特性:

具有层级概念,在上述场景中Activity层级最低,Dialog次之,Toast最高

窗口可以设置位置大小,屏幕中的一块区域展示内容。只不过Activity是全屏的,不像Windows可以最大化最小化, 用户手动改变窗口大小,弱化了窗口的概念。

对于Window的认识阶段

第一阶段

刚刚学习Android的时候,都听说过一个概念,Activity代表一个界面。实际开发起来也是如此,在Activity中加载xml文件,绑定数据与view。

Activity == UI

第二阶段

看了几篇文章,接触了Window,WMS 概念 。发现Activity并不是UI界面,Activity内部持有Window对象,Window的实现类PhoneWindow内部持有DecorView作为根布局,开发人员编写的xml 会添加到DecorView中。 哦!结合对WMS粗浅的理解,WMS是窗口管理服务,window不就是窗口么,可能window在创建完成后最终传递给WMS管理。 Window == UI

第三阶段

之后深入到源码中发现Window虽然翻译过来是窗口,但实际上并不是真正的窗口。

理由有二:Window并没有与WMS交互,Window没有view管理之类的功能。

首先可以确定的是wms是系统窗口服务,所有窗口都要与wms打交道。如果window代表的窗口,那么它或者它的唯一子类PhoneWindow,必然存在Binder机制与wms交互,然而并没有。

既然Window没有与wms交互,那它做了什么工作呢?

面向对象中,设计一个类的意义可以从它的属性以及暴露的方法来推测。

如下是从:PhoneWindow中摘取的一些通过名字可以大概推测出作用的属性

大部分都是关于资源的设置:状态栏,导航栏,是否透明,转场动画,应用主题等等

private DecorView mDecor;
private TextView mTitleView;
int mStatusBarColor = 0;
int mNavigationBarColor = 0;
private int mTitleColor = 0;
private CharSequence mTitle = null;
boolean mIsFloating;
private boolean mIsTranslucent;
private LayoutInflater mLayoutInflater;
private Transition mEnterTransition = null;
private Transition mReturnTransition = USE_DEFAULT_TRANSITION;
private int mTheme = -1;
private boolean mIsStartingWindow;

Window类注释 — 百度翻译

Abstract base class for a top-level window look and behavior policy. An instance of this class should be used as the top-level view added to the window manager. It provides standard UI policies such as a background, title area, default key processing, etc.

顶级窗口外观和行为策略的抽象基类。此类的实例应用作添加到窗口管理器的顶级视图。它提供标准的UI策略,例如背景、标题区域、默认键处理等。

结合window类注释可以做出结论,Window也是一层封装,提供通用页面模板,并不是真正的window。

寻找真正的Window

上面讨论了Window类 并不是真正的Window,只是一层封装。系统提供了WindowManager 允许开发人员添加Window。

如下代码是在Activity获取windowManager 添加Window。为什么apiaddView 。不应该是addWindow 才对么? 难道view才是window?(下面代码会报错 添加系统window需要权限)

val wm:WindowManager =windowManager
val layoutParams = WindowManager.LayoutParams()
layoutParams.run{
		width = WindowManager.LayoutParams.WRAP_CONTENT
		height = WindowManager.LayoutParams.WRAP_CONTENT
		fORMat = PixelFormat.TRANSLUCENT
		gravity = Gravity.STARTor Gravity.TOP
		flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
		type =
		        if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
		else WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
}
val view :View = LayoutInflater.from(this).inflate(R.layout.xxx,null)
wm.addView(view, layoutParams)

跟踪源码

WindowManager 是个接口,实现类为 WindowManagerImpl

WindowManagerImpl 内部把逻辑转发给WindowManagerGlobal

WindowManagerGlobal 调用 ViewRootImpl

ViewRootImpl 通过WindowSession 与 wms 完成进程间通信

具体方法调用流程

WindowManager.addView()WindowManagerImpl.addView()WindowManagerGlobal.addView()ViewRootImpl.setView()WindowSession.addToDisplayAsUser()

ViewRootImpl类核心逻辑如下:

WindowManager.addView() 在应用层最终调用 ViewRootImpl.setView()

添加的View通过 WindowSession 进入 wms,方法 IWindowSession.addToDisplay 第一个参数 mWindow 代表真正的window。

mWindow的实现类W,类型是 IWindow.Stub ,Binder对象 对其他进程暴露方法。

W类 持有ViewRootImpl ,公开的接口方法内部调用ViewRootImpl 类。

所以 IWindowSession 是把一个Binder对象传递给WMS,WMS通过进程间通信操作ViewRootImpl ,ViewRootImpl 操作View

ViewRootImpl 操作的View

对应到当前场景是 windowManager.addView() 添加的View

对应到Activity则是PhoneWindow中DecorView

经过这一顿分析 好像没有确定Window的实体对象 难以捉摸。它不像一个User类,Person类那样明晃晃的放在开发者面前。原本以为 传递给WMS肯定会是Window了,结果是Binder,WMS进程间通信最终操控的是View。

public final class ViewRootImpl implements ViewParent,
        View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
	final W mWindow;
	View mView;
	final IWindowSession mWindowSession;
	public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
            int userId) {
			mView = view;
			res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
                            getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
                            mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                            mAttachInfo.mDisplayCutout, inputChannel,
                            mTempInsets, mTempControls);
	}
	static class W extends IWindow.Stub {
        private final WeakReference<ViewRootImpl> mViewAncestor;
        private final IWindowSession mWindowSession;
				W(ViewRootImpl viewAncestor) {
            mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
            mWindowSession = viewAncestor.mWindowSession;
        }
				....
				@Override
        public void hideInsets(@InsetsType int types, boolean fromIme) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.hideInsets(types, fromIme);
            }
        }
        @Override
        public void moved(int newX, int newY) {
            final ViewRootImpl viewAncestor = mViewAncestor.get();
            if (viewAncestor != null) {
                viewAncestor.dispatchMoved(newX, newY);
            }
        }
				....省略其他方法
	}
}

Window到底是什么

window是一个抽象的概念,对应手机屏幕的一块区域,实际是view。

View成了Window??? 什么场景下可以把View叫做Window呢?

想象一个场景:一个Activity内有DialogA,DialogB

这个场景会创建三个Window,Activity一个,Dialog两个,对应三个xml布局。是三个抽象的Window,对应三个具体的View,应该叫做View树

它们彼此之间互不影响,为DialogA添加View,不会影响到Activity和DialogB。因为它们属于不同的Window。

这也应该是添加Window的Api 叫做 addView() 而不是 addWidnow() 的原因。

根本就没有具体的Window,只有具体的View,Window是抽象的。

理解了什么是Window之后,在简单说一下添加window的Api。

View表示需要在屏幕展示的内容

layoutParams 则是对内容进行约束,基本的宽高,位置。

layoutParams.type 设置window类型,其实是弹窗的显示层级。

应用window:1 ~ 99

子window:1000 ~ 1999

系统window:2000~ 2999

数值越大层级越高,层级高覆盖层级低的,一般通过常量设置,系统window需要申请权限

layoutParams.flags 设置Window不同场景下的逻辑,比如:

// 全屏显示,隐藏所有的 Window 装饰,比如在游戏、播放器中的全屏显示 public static final int FLAG_FULLSCREEN = 0x00000400;

// 表示比FLAG_FULLSCREEN低一级,会显示状态栏 public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;

// 当用户的脸贴近屏幕时(比如打电话),不会去响应此事件 public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;

// 全屏显示,隐藏所有的 Window 装饰,比如在游戏、播放器中的全屏显示 public static final int FLAG_FULLSCREEN = 0x00000400;

// 表示比FLAG_FULLSCREEN低一级,会显示状态栏 public static final int FLAG_FORCE_NOT_FULLSCREEN = 0x00000800;

// 当用户的脸贴近屏幕时(比如打电话),不会去响应此事件 public static final int FLAG_IGNORE_CHEEK_PRESSES = 0x00008000;

val wm:WindowManager =windowManager
val layoutParams = WindowManager.LayoutParams()
layoutParams.run{
		width = WindowManager.LayoutParams.WRAP_CONTENT
		height = WindowManager.LayoutParams.WRAP_CONTENT
		format = PixelFormat.TRANSLUCENT
		gravity = Gravity.STARTor Gravity.TOP
		x = 0
		y = 0
		flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
		type =
		        if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
		else WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
}
val view :View = LayoutInflater.from(this).inflate(R.layout.xxx,null)
wm.addView(view, layoutParams)

Activity-Window-View的关系

Activity是一层封装,屏蔽复杂的系统实现细节,抽象出UI生命周期,方便开发人员工作,专注于界面样式的编写

Window,指PhoneWindow,页面通用模板,所有的Window都需要主题,状态栏,导航栏,背景等等设置。PhoneWindow是对上述内容的一个模板实现。

软件设计中很重要的一点就是找到业务当中的 “变与不变”。 在Window体系中,一个页面通用不变的部分交给PhoneWindow实现。变化的部分就是View,让开发人员能够自由定制。

PhoneWindow的存在也是帮Activity减轻负担,指责单一是一个好理解并且非常有效的原则。Activity已经非常复杂了, 设计出PhoneWindow把UI相关的代码从Activity中剥离出去。

由了上述层层抽象封装才有了最初学习Android时的概念,Activity == 页面。

到此这篇关于结合Windows窗口深入分析Android窗口的实现的文章就介绍到这了,更多相关Android窗口内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 结合Windows窗口深入分析Android窗口的实现

本文链接: http://www.lsjlt.com/news/209757.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 结合Windows窗口深入分析Android窗口的实现
    目录前言对于Window的认识阶段寻找真正的WindowWindow到底是什么Activity-Window-View的关系前言 从windows窗口的概念开始,通过对比去理解And...
    99+
    2023-05-16
    Android窗口 Android窗口机制
  • Android窗口层级(Window Type)分析
    前言 Android的窗口Window分为三种类型: 应用Window,比如Activity、Dialog;子Window,比如PopupWindow;系统Window,比如Toast、系统状态栏、导...
    99+
    2023-10-26
    android 窗口层级
  • Android实现左滑关闭窗口
    前言 目前市场很多的APP都带有窗口滑动切换关闭,这种切换,使得用户操作比较爽,而且觉得功能点上也比较大气,在此就是自己总结了一个简易的方法,直接替换在基础窗口里面,使用安卓最基础的...
    99+
    2024-04-02
  • pyqt5主窗口按键弹出子窗口的实现
    目标:主窗口保持,通过按键弹出子窗口 步骤一:pyqt5创建主窗口,并设置按键 from PyQt5.QtWidgets import * import sys # 主窗口 cla...
    99+
    2023-02-07
    pyqt5主窗口按键弹出子窗口 pyqt5 弹出窗口
  • android多窗口模式怎么实现
    Android多窗口模式可以通过以下几个步骤实现:1. 在AndroidManifest.xml文件中声明`android:resi...
    99+
    2023-09-18
    android
  • C# MSN Messenger的窗口的实现浅析
    MSN Messenger是微软推出的一款即时通讯软件,它可以实现用户之间的文字聊天、传输文件、语音通话等功能。在C#中实现MSN ...
    99+
    2023-09-22
    C#
  • windows窗口的组成部分有哪些
    Windows窗口的组成部分包括: 标题栏:位于窗口的顶部,显示窗口的名称和控制按钮,如最小化、最大化和关闭按钮。 菜单栏:...
    99+
    2024-02-29
    windows
  • QT编写窗口插件实现调用窗口的自适应
    前言 最近项目中遇到插件架构,将几个功能模块分别写成了dll供主程序调用。本文主要在QT下实现这样一个功能: 编写一个dll,里面包含一个QDialog对话框作为主窗口。该dll提供...
    99+
    2024-04-02
  • vue+electron实现创建多窗口及窗口间的通信(实施方案)
    目录一、前言二、实施方案1.创建多窗口2.多窗口间的通信三、后记一、前言 对于一个桌面应用来说,有时候单独一个窗口用户使用起来会不太方便,比方说写日报或者查看文件等,若是在同一窗口内...
    99+
    2024-04-02
  • SQL 窗口函数实现高效分页查询的案例分析
    🍺不闻不若闻之,闻之不若见之,见之不若知之,知之不若行之。学至于行之而止矣。——荀子 大家好!我是只谈技术不剪发的 Tony 老师。 在使用 SQL 语句实...
    99+
    2024-04-02
  • Vue在原窗口与新窗口打开外部链接的实现代码
    目录Vue如何在原窗口与新窗口打开外部链接总结补充:vue跳转外部链接vue跳转外部链接Vue如何在原窗口与新窗口打开外部链接 Vue项目中如果是页面中的内部跳转,可以用this.$...
    99+
    2023-02-02
    Vue打开外部链接 Vue新窗口打开外部链接 vue外部链接
  • Flink的窗口操作怎么实现
    Flink中的窗口操作通过使用DataStream API中的WindowAssigner和WindowOperator来实现。窗口...
    99+
    2024-04-02
  • PyQT5 QTDesigner窗口及组成的实现
    一、主窗口成员 主窗口中的菜单栏、工具栏和状态栏 1.菜单栏 我们可以直接在QTDesigner中输入菜单选项即可。这些菜单选项本质上都是动作,关于动作,在下面章节进行描述。 2...
    99+
    2024-04-02
  • Java C++分别实现滑动窗口的最大值
    目录1、题目2、思路3、c++代码4、java代码1、题目 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。 示例: 提示: 你可以假设 k 总是有效的...
    99+
    2024-04-02
  • Android popupWindow弹出窗体实现方法分析
    本文实例讲述了Android popupWindow弹出窗体实现方法。分享给大家供大家参考,具体如下: 建立popupwindow显示的布局页面(普通的view任意布局)<?xml version="1.0" encoding...
    99+
    2023-05-31
    android popupwindow 弹出窗体
  • Java多线程窗口售票的示例分析
    这篇文章主要为大家展示了“Java多线程窗口售票的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java多线程窗口售票的示例分析”这篇文章吧。具体代码如下:第一种:package&nbs...
    99+
    2023-05-30
    java
  • Bootstrap中模态窗口源码的示例分析
    这篇文章将为大家详细讲解有关Bootstrap中模态窗口源码的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。具体内容如下 +function ($)...
    99+
    2024-04-02
  • Pyqt5如何实现窗口缩放,控件在窗口内自动伸缩的操作
    这篇文章给大家分享的是有关Pyqt5如何实现窗口缩放,控件在窗口内自动伸缩的操作的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。在Qtdesigner中新建一个主界面如下所示:ctrl+R 预览从预览图中可以看出这...
    99+
    2023-06-08
  • 如何理解Flex弹出窗口实现和子父Flex窗口的数据交换
    本篇文章给大家分享的是有关如何理解Flex弹出窗口实现和子父Flex窗口的数据交换,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Flex弹出窗口的实现以及子父Flex窗口的数据...
    99+
    2023-06-17
  • Java 滑动窗口最大值的实现
    一、题目 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回滑动窗口...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作