setZOrderOnTop(true) 以修改 mSubLayer

简介: q

LayoutInflater 布局填充阶段,按既有的布局填充流程,将 SurfaceView 构造并加入到视图树的某个结点;接下来,根布局会通过深度遍历依次执行 onAttachedToWindow() 处理视图挂载窗口的事件:

// /frameworks/base/core/java/android/view/SurfaceView.java
@Override
protected void onAttachedToWindow() {

// ...
mParent.requestTransparentRegion(SurfaceView.this);   // 1.
ViewTreeObserver observer = getViewTreeObserver();
observer.addOnPreDrawListener(mDrawListener);         // 2.

}

@UnsupportedAppUsage
private final ViewTreeObserver.OnPreDrawListener mDrawListener = new ViewTreeObserver.OnPreDrawListener() {

@Override
public boolean onPreDraw() {
    updateSurface();                                 // 3.
    return true;
}

};

protected void updateSurface() {
// ...
mSurfaceSession = new SurfaceSession();
mSurfaceControl = new SurfaceControl.Builder(mSurfaceSession); // 4
//...
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
步骤 1 中,SurfaceView 会向父视图依次向上请求创造一份透明区域,根视图统计到最终的信息后,通过 Binder 通知 WindowManagerService 将对应区域设置为透明。

步骤 2、3、4 是在同一个方法的调用栈中,由此可见,SurfaceView 向系统请求透明区域后,会立即创建一个与绘图表面的连接 SurfaceSession ,并创建一个对应的控制器 SurfaceControl,便于对这个独立的绘图表面进行直接通信。

由此可见,Android 自有的视图树体系中,SurfaceView 作为一个普通的 View 被挂载上去之后,通过 Binder 通信,WindowManagerService 将其所在区域设置为透明(挖洞);并建立了与独立绘图表面的连接,后续便可与其直接通信。

  1. 子图层类型

在阐述绘制流程之前,读者需简单了解 子图层类型 的概念。

上文说到,SurfaceView 的绝大多数使用场景中,其 z 轴的位置通常是在页面的 最下方 。但在实际开发中,随着业务场景复杂度的上升,仍然有部分场景是无法被满足的,比如:在页面的最上方播放一条全屏的视频广告。

因此,SurfaceView 的设计中引入了一个 子图层类型 的概念,用于定义这个独立的 Surface 相比较当前页面窗口 (即Activity) 的位置:

// /frameworks/base/core/java/android/view/SurfaceView.java
public class SurfaceView extends View {

// SurfaceView 的子图层类型
int mSubLayer = APPLICATION_MEDIA_SUBLAYER;

// SurfaceView 是否展示在当前窗口的最上方
// 该方法在挖洞和绘制流程中都有使用,最终影响到用户的视觉效果
private boolean isAboveParent() {

return mSubLayer >= 0;

}
}

// /frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java
public interface WindowManagerPolicyConstants {
// ...
int APPLICATION_MEDIA_SUBLAYER = -2;
int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
int APPLICATION_PANEL_SUBLAYER = 1;
int APPLICATION_SUB_PANEL_SUBLAYER = 2;
int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3;
// ...
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
如代码所示,mSubLayer 默认值为 -2,这表示 SurfaceView 默认总是在 Activity 的下方,想要让 SurfaceView 展示在 Activity 上方,可以调用 setZOrderOnTop(true) 以修改 mSubLayer 的值:
————————————————

相关文章
|
编译器 API 容器
Compose:从重组谈谈页面性能优化思路,狠狠优化一笔
Compose:从重组谈谈页面性能优化思路,狠狠优化一笔
705 0
|
Android开发
Android 13 Qs面板的加载流程
Android 13 Qs面板的加载流程
1541 0
Android 13 Qs面板的加载流程
|
自然语言处理 关系型数据库 MySQL
MySQL MATCH 匹配中文 无法查询的问题如何处理?
【8月更文挑战第29天】MySQL MATCH 匹配中文 无法查询的问题如何处理?
615 7
|
Android开发 开发者 索引
Android实战经验之如何使用DiffUtil提升RecyclerView的刷新性能
本文介绍如何使用 `DiffUtil` 实现 `RecyclerView` 数据集的高效更新,避免不必要的全局刷新,尤其适用于处理大量数据场景。通过定义 `DiffUtil.Callback`、计算差异并应用到适配器,可以显著提升性能。同时,文章还列举了常见错误及原因,帮助开发者避免陷阱。
1028 9
|
缓存 网络协议 编译器
针对Android系统工程师的C/C++学习目录
针对Android系统工程师的C/C++学习目录
225 0
|
Java Go Android开发
Android——编译(三):android.bp的相关知识
Android——编译(三):android.bp的相关知识
1501 0
|
存储 缓存 分布式数据库
[笔记]Windows核心编程《十七》内存映射文件(二)
[笔记]Windows核心编程《十七》内存映射文件(二)
504 0
|
XML Shell Linux
Windows下成功安装Repo和下载Android源码方法总结
Windows下成功安装Repo和下载Android源码方法总结
|
XML 前端开发 Java
Android Kotlin/Java 动态设置 shape/drawable 等状态效果
      小菜最近遇到一个小需求,程序里面有个别页面,需要动态的调整某个页面的样式,包括一键变灰等效果。       以前页面是用 shape 和 drawable 之类实现的效果。
3970 0
|
开发框架 JavaScript 前端开发
npm run build 后如何直接运行项目
npm run build 后如何直接运行项目