前言
在Android中更新UI操作都需要在主线程中操作。但是SurfaceView例外,他可以在子线程中更新View,这使他可以做一些复杂的动画更新而不必担心造成主线程的阻塞。接下来就开始介绍一下SurfaceView的使用。
实现
SurfaceView通过SurfaceHolder.Callback来通知SurfaceView的创建和销毁
surfaceView.holder.addCallback(object :SurfaceHolder.Callback{
//改变
override fun surfaceChanged(holder: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {
}
//销毁
override fun surfaceDestroyed(holder: SurfaceHolder?) {
}
//创建
override fun surfaceCreated(holder: SurfaceHolder?) {
}
})
在SurfaceView创建完成之后就可以对其进行绘制了,而他的绘制是可以放在子线程中的
//获取画布
val canvas=surfaceView.holder.lockCanvas()
//提交画布
surfaceView.holder.unlockCanvasAndPost(canvas)
创建动画
下面就是一个使用SurfaceView创建动画的简单示例
class MainActivity : Activity() {
var surfaceView: SurfaceView? = null
var mPath = Path()
var mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
var mCanvas: Canvas? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surfaceView = findViewById(R.id.surface_view)
surfaceView.holder.addCallback(object:SurfaceHolder.Callback{
override fun surfaceChanged(holder: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
}
override fun surfaceCreated(holder: SurfaceHolder?) {
mPaint.color = Color.BLACK
mPaint.style = Paint.Style.STROKE
mPaint.strokeWidth = 10f
mPaint.strokeCap = Paint.Cap.ROUND
mPaint.strokeJoin = Paint.Join.ROUND
mPath.moveTo(0f, 100f)
Thread(Runnable {
kotlin.run {
draw(0)
}
}).start()
}
})
}
private fun draw(x: Int) {
if (x > 1080) {
return
}
val y = (50 * Math.sin(x * Math.PI / 180) + 100).toInt()
mPath.lineTo(x + 3f, y.toFloat())
try {
mCanvas = holder.svView.holder.lockCanvas()
mCanvas?.drawColor(Color.WHITE)
mCanvas?.drawPath(mPath, mPaint)
} catch (e: Exception) {
e.printStackTrace()
} finally {
if (mCanvas != null)
holder.svView.holder.unlockCanvasAndPost(mCanvas)
}
draw(x + 3)
}
}
其他用途
SurfaceView还可以和MediaPlayer一起使用实现视频播放,以下就是简单的示例:
class MainActivity : Activity() {
var surfaceView: SurfaceView? = null
val url = "https://apd-fec3435b8e24a9f3815c886baf4b7682.v.smtcdns.com/om.tc.qq.com/A3h5f3r8PilbVshgbDGWN3dyaZ8zUFk92BfD1Npo4MBA/h0560ixm63g.mp4?sdtfrom=v1103&guid=2cd4a548b5a2146345f8214435e93e24&vkey=10A496F49B3530CF50C56B617F6DB75C6A69850F6E8AD27EF01C74C9B06E07A95E952146937CD25966DF570C447F3AA1570F392682DEEDA0953F1CA68941B5C3FD7552C0D4DC7666322C5B6EF983BCB32A09AD04252FD6CB536BBBB81CC1BAD7CB31E90E1D341D675E08ED216DCA77E0D868B2EE67C3D6F5&platform=2"
val player = MediaPlayer()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
surfaceView = findViewById(R.id.surface_view)
Thread(Runnable {
player.setDataSource(this, Uri.parse(url))
player.prepare()
}).start()
surfaceView.holder.addCallback(object:SurfaceHolder.Callback{
override fun surfaceChanged(holder: SurfaceHolder?, p1: Int, p2: Int, p3: Int) {
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
}
override fun surfaceCreated(holder: SurfaceHolder?) {
player.setDisplay(holder)
}
})
player.setOnPreparedListener(object : MediaPlayer.OnPreparedListener {
override fun onPrepared(p0: MediaPlayer?) {
player.start()
player.isLooping = true
}
})
}
}
参考
SurfaceView
Android之SurfaceView使用总结
Android SurfaceView的使用
android中使用surfaceview+MediaPlayer播放视频