开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情
前言
因为过年多放了几天假,明天周六还得补班,所以也没什么时间去思考写什么,今天正好和掘友聊了我们安卓NDK开发的问题,但我是真的不会,所以今天的文章就是看看和播放有关的控件——SurfaceView。
正文
首先,这个控件是继承自View的,是和View一个阵营,所以它和View以及相关子类组件都有一些相同的地方,但也有更多自己的特性:
SurfaceView 概况
从官方给的注释来看,其实该控件是用来提供嵌入在视图层次结构内的专用绘图图面,这个视图里内嵌了一个专门用于绘制的Surface,我们可以去控制 Surface 的大小 和格式,而SurfaceView 来控制这个Surface的绘制位置。
此外,该绘制的UI在一个独立的线程中进行绘制,这样不会占用主线程资源,所以可以绘制比较复杂的UI,也不用担心用户的控制得不到回应,于是就被广泛用于游戏、视频与摄像头画面等场景。
Surface特性
注释中还提到Surface是纵深排序(Z ordered),这就导致它位于持有其 SurfaceView 的窗口后面,而SurfaceView可以提供一个可见窗口,而只有在这个可见窗口的Surface才能被显示出来,这个窗口外的就看不到了。此外,我们的Surface还受到了视图层级的影响,它的兄弟视图会在顶层,导致我们的Surface会被其遮挡,当然,这也是我们使用它的一个目的,我们常见的加载转圈就是这个原理实现的。
- Surface在SurfaceView可见时创建,隐藏时就被销毁,以节省资源消耗,
- 如果想访问Surface,我们可以通过 SurfaceHolder 接口,调用getHolder() 方法即可得到这个接口。
- 想要知道Surface的创建和销毁的历程可以通过复写surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)方法
- SurfaceView 和 SurfaceHolder.Callback 的方法都应该在UI线程(一般主线程)里调用,渲染线程所需要访问的各种变量都应该同步处理。
- 由于我们的Surface可能会被销毁,它只在 SurfaceHolder.Callback.surfaceCreated() 和 SurfaceHolder.Callback.surfaceDestroyed()之间有效,所以要保证绘制线程在访问底部的Surface时,Surface是合法有效的。
这块内容基本上也是我们使用SurfaceView的注意点与使用方法的说明。
注意事项
注意: 从版本 Build.VERSION_CODES.N开始,SurfaceView的窗口位置与其他视图渲染同步更新。这意味着在屏幕上转换和缩放 SurfaceView 不会导致渲染伪影。当屏幕窗口异步定位时,这种渲染伪影可能还是会在以前版本平台上发生。
以上就是官方的英文注释对SurfaceView以及其Surface的特性介绍与相关使用时的注意事项,这就基本可以去直接上手使用SurfaceView了。
而我们SurfaceView在布局的使用还是很简单的,主要在Activity代码上有点麻烦:
<SurfaceView
android:id="@+id/vSurfaceView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
总结
写了半天,发现都还没开始使用SurfaceView,下一篇开始使用SurfaceView控件。