1.前言
从零开始的车载Android HMI是一个系列性的文章,目的在于展示一些在Android手机应用开中不常用,但是在车载应用开发中较为常用的一系列Android HMI 组件,希望能够帮助初入车载应用开发的同学了解车载应用开发过程中常用的各种UI 组件。
RE: 从零开始的车载Android HMI(一) - Lottie
RE: 从零开始的车载Android HMI(二) - Widget

本文参考资料:
2.SurfaceView 简介
相信每一个Android初学者在自学Android编程时都使用过VideoView来播放视频,当打开VideoView的源码时,会发现VideoView并不是直接继承自我们常用的ViewGroup或是View,它实际上继承自一种更特殊的View - SurfaceView
2.1.SurfaceView 是什么
简单来说,SurfaceView就是一个嵌入了Surface的特殊View,Surface中有一个独立的画布Canvas用于绘制内容,SurfaceView本质上是这个Surface的容器,用于控制Surface的格式、尺寸等基础信息。
SurfaceView显示内容时,会在Window上挖一个洞,SurfaceView绘制的内容显示在这个洞里,其他的View继续显示在Window上。
2.2.SurfaceView 应用场景
SurfaceView的出现并不是为了取代View,当界面绘制需要频繁刷新,或刷新时需要处理的数据量较大时,就应该考虑使用SurfaceView,例如:视频播放、展示摄像头数据。在车载应用开发中,我们通常使用SurfaceView展示Camera的数据,例如 泊车雷达 等应用。如果需要对来自Camera的数据进行二次处理后再展示,应该使用TextureView。
3.SurfaceView 基础用法
接下来我们写一个简单绘的图板,来看一下SurfaceView的基础用法是怎样的。

1.创建一个继承自SurfaceView的自定义View,并初始化Paint、Path
init {
paint = Paint(Paint.ANTI_ALIAS_FLAG)
paint.color = Color.BLUE
paint.style = Paint.Style.STROKE
paint.strokeWidth = 5f
path = Path()
}
2.获取SurfaceHolder,并监听Surface生命周期
init {
...
// 为了代码的可读性,这里并没有使用Kotlin的简写
surfaceHolder = getHolder()
surfaceHolder?.addCallback(this)
}
override fun surfaceCreated(holder: SurfaceHolder) {
flag = true
drawCanvas()
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
flag = false
}
SurfaceHolder从名字上就能看出,他是Surface的持有对象,必须通过它才能获取到绘图所必须的画布。下一节会详细介绍。
3.监听手势
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
path.moveTo(event.x, event.y)
return true
}
MotionEvent.ACTION_MOVE -> {
path.lineTo(event.x, event.y)
}
}
return super.onTouchEvent(event)
}
通过onTouchEvent监听到屏幕上的手势移动,并将轨迹保存在Path中。
4.在子线程中将轨迹绘制到画布上
private fun drawCanvas() {
Thread {
while (flag) {
val canvas = surfaceHolder.lockCanvas()
canvas.drawPath(path, paint)
surfaceHolder.unlockCanvasAndPost(canvas)
}
} .start()
}
在这一步中,通过SurfaceHolder获取到SurfaceView自带的缓冲画布,并对这个画布加锁surfaceHolder.lockCanvas()。
在绘制完成后,将缓冲画布释放,并将画布的内容更新到主线程的画布上surfaceHolder.unlockCanvasAndPost(canvas),这样缓冲画布的内容就显示到屏幕上了。
完整的源码如下所示:
class CustomSurfaceView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
) : SurfaceView(context, attrs), SurfaceHolder.Callback {
private val paint: Paint
private val path: Path
private val surfaceHolder: SurfaceHolder
private var flag: Bo

本文详细介绍了车载应用开发中SurfaceView的使用,包括其概念、应用场景、基础用法、双缓冲机制及其注意事项,为初学者提供实用的开发指导。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



