简介

官方API文档介绍:SurfaceView是View的子类,它内嵌了一个专门用于绘制的Surface,你可以控制这个Surface的格式和尺寸,Surfaceview控制这个Surface的绘制位置。

surface是纵深排序(Z-ordered)的,这表明它总在自己所在窗口的后面。SurfaceView提供了一个可见区域,只有在这个可见区域内的surface内容才可见。surface的排版显示受到视图层级关系的影响,它的兄弟视图结点会在顶端显示。这意味者 surface的内容会被它的兄弟视图遮挡,这一特性可以用来放置遮盖物(overlays)(例如,文本和按钮等控件)。注意,如果surface上面有透明控件,那么每次surface变化都会引起框架重新计算它和顶层控件的透明效果,这会影响性能。

你可以通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口。

SurfaceView变得可见时,surface被创建;SurfaceView隐藏前,surface被销毁。这样能节省资源。如果你要查看 surface被创建和销毁的时机,可以重载surfaceCreated(SurfaceHolder)和 surfaceDestroyed(SurfaceHolder)。

SurfaceView的核心在于提供了两个线程:UI线程和渲染线程。这里应注意:

  • 所有SurfaceView和SurfaceHolder.Callback的方法都应该在UI线程里调用,一般来说就是应用程序主线程。渲染线程所要访问的各种变量应该作同步处理。
  • 由于surface可能被销毁,它只在SurfaceHolder.Callback#surfaceCreated()和 SurfaceHolder.Callback#surfaceDestroyed()之间有效,所以要确保渲染线程访问的是合法有效的surface。

注意:从平台版本Build.VERSION_CODES.N开始,SurfaceView的窗口位置与其他View渲染同步更新。这意味着在屏幕上平移和缩放SurfaceView不会导致渲染失真。当它的窗口异步渲染时,可能会在之前的安卓版本中发生渲染失真。

双缓冲技术

为了防止动画闪烁而实现的一种多线程应用。主要原理:一个画面显示过程中,程序又实时在改变它,前画面还没有显示完,程序又请求重新绘制,这样屏幕就会不停闪烁。为了避免闪烁,可以使用双缓冲技术,将要处理的图片都在内存中处理好之后,再将其显示到屏幕上。这样显示出来的总是完整的图像,不会出现闪烁现象。
在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。

SurfaceView默认使用双缓冲技术,它支持在子线程中绘制图像,这样就不会阻塞主线程了,所以它适合于视频或图像相关的开发。
参考:android双缓冲绘图技术分析

SurfaceView的使用

下面我将用代码形式,展示如何使用SurfaceView。
一、绘制图形

class ImageSurfaceView(context: Context?) : SurfaceView(context), SurfaceHolder.Callback {var surfaceHolder: SurfaceHolder? = nullvar drawThread: DrawThread? = nullinit {surfaceHolder = holdersurfaceHolder?.addCallback(this)//监听surface的状态if (surfaceHolder != null) {drawThread = DrawThread(surfaceHolder!!)}}override fun surfaceCreated(holder: SurfaceHolder?) {//surface创建的时候调用,一般在该方法中启动绘图的线程Log.i("Test", "surface创建")drawThread?.isRunning = truedrawThread?.start()}override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {//surface尺寸发生改变的时候调用,如横竖屏切换,或者初次渲染在屏幕上时Log.i("Test", "surface更新")}override fun surfaceDestroyed(holder: SurfaceHolder?) {//surface被销毁的时候调用,一般在该方法中停止绘图线程Log.i("Test", "surface销毁")drawThread?.isRunning = false}/*** 异步线程,不停地绘制文字*/inner class DrawThread(val sHolder: SurfaceHolder) : Thread() {var isRunning = truevar count = 0override fun run() {while (isRunning) {var c: Canvas? = nulltry {synchronized(sHolder) {c = sHolder.lockCanvas()//获取画布,以执行绘制c?.drawColor(Color.WHITE)//画布背景白色val paint = Paint()paint.color = Color.REDpaint.textSize = 60fc?.drawText("${count++}秒", 200f, 500f, paint)//绘制时sleep(1000)}}catch (e:Exception){}finally {if (c != null) {sHolder.unlockCanvasAndPost(c)//释放画布并显示所绘制的内容到屏幕上}}}}}
}

二、播放视频
使用MediaPlayer+SurfaceView播放视频,安卓还有个VideoView是继承SurfaceView专门用于播放视频的,那个可以自行百度。

class SurfaceActivity : AppCompatActivity(), SurfaceHolder.Callback {//媒体播放控制器private var mediaPlayer: MediaPlayer? = null//视频路径private var videoPath: String? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_surface)把输送给surfaceView的视频画面,直接显示到屏幕上,不要维持它自身的缓冲区sv_video.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS)sv_video.holder.setKeepScreenOn(true)sv_video.holder.addCallback(this)initMedia()btn_play.setOnClickListener {if (mediaPlayer != null && mediaPlayer!!.isPlaying) {pause()} else {start()}}}/*** 初始化媒体播放*/private fun initMedia() {videoPath = "/storage/emulated/0/DCIM/Camera/VID_20200311_082801.mp4"mediaPlayer = MediaPlayer()mediaPlayer?.setDataSource(videoPath)mediaPlayer?.setOnPreparedListener {start()//缓冲完,播放}mediaPlayer?.setOnCompletionListener {Toast.makeText(this,"播放完毕",Toast.LENGTH_SHORT).show()btn_play.text = "重新播放"}}override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {}override fun surfaceDestroyed(holder: SurfaceHolder?) {if (mediaPlayer != null && mediaPlayer!!.isPlaying) {mediaPlayer!!.stop()}}override fun surfaceCreated(holder: SurfaceHolder?) {mediaPlayer?.setDisplay(holder)//设置播放的容器,将MediaPlayer和SurfaceView关联起来mediaPlayer?.prepareAsync()//缓冲}private fun start(){btn_play.text = "暂停"mediaPlayer?.start()}private fun pause(){btn_play.text = "播放"mediaPlayer?.pause()}override fun onDestroy() {super.onDestroy()mediaPlayer?.release()mediaPlayer = null}
}

Android音视频开发(二)SurfaceView相关推荐

  1. Android 音视频开发(二) -- Camera1 实现预览、拍照功能

    音视频 系列文章 Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍 ...

  2. Android 音视频开发(二):使用 AudioRecord 采集音频PCM并保存到文件(学习笔记)

    关于 AudioRecord Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风 ...

  3. android音频开发6,Android 音视频开发(一) : 通过三种方式绘制图片

    想要逐步入门音视频开发,就需要一步步的去学习整理,并积累.本文是音视频开发积累的第一篇. 对应的要学习的内容是:在 Android 平台绘制一张图片,使用至少 3 种不同的 API,ImageView ...

  4. Android 音视频开发(三) -- Camera2 实现预览、拍照功能

    音视频 系列文章 Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍 ...

  5. Android 音视频开发(六) -- Android Mediaprojection 截屏和录屏

    Android 音视频开发(一) – 使用AudioRecord 录制PCM(录音):AudioTrack播放音频 Android 音视频开发(二) – Camera1 实现预览.拍照功能 Andro ...

  6. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  7. Android 音视频开发(一) -- 使用AudioRecord 录制PCM(录音);AudioTrack播放音频

    前言,音视频这块,确实比较难入门,本着学习的态度,我这边也跟着 Android 音视频开发入门指南 打怪升级,留下个脚印,大家共勉. 音视频 系列文章 Android 音视频开发(一) – 使用Aud ...

  8. Android 音视频开发之基础篇 使用 SurfaceView绘制一张图片

    Android 音视频开发 上一篇文章:使用 imageview绘制一张图片 任务一 SurfaceView绘制一张图片 文章目录 Android 音视频开发 前言 一.surfaceview是什么? ...

  9. Android 音视频开发之基础篇 使用 imageview绘制一张图片

    Android 音视频开发 任务一 ImageView 绘制图片 文章目录 Android 音视频开发 任务一 ImageView 绘制图片 前言 一.配置activity_main.xml 二.添加 ...

最新文章

  1. 【Python】Listbox组件 Scrollbar组件 Scale组件
  2. 本地应用 v-model
  3. R语言PCA主成分分析(Principle Component Analysis)实战2
  4. fix issues
  5. opencv 霍夫曼变换 直线提取
  6. error while loading shared libraries: libopencv_highgui.so.3.2: cannot open shared object file 的解决办法
  7. x86异常处理与中断机制(1)概述中断的来源和处理方式
  8. 微信又更新了,“拍一拍”玩法升级...
  9. 性能测试搭建Jmeter分布式压测与监控
  10. 自动劫持root密码
  11. 基于Python的指数基金量化投资 - 指数投资技巧(二)定期不定额
  12. 百度地图ipa包使用的Framework解读
  13. Linux系统:安装QQ教程
  14. 成为成功的软件开发顾问的5个关键
  15. winscp,winscp连接
  16. 服务器网站权限,在服务器上设置网站权限
  17. 《楚门的世界》观后感
  18. 【附源码】计算机毕业设计java学习资源共享网站设计与实现
  19. 中断优先级分组与抢占优先级和响应优先级的关系
  20. 赶紧收下这四个安卓手机通讯录丢失怎么恢复的技巧吧

热门文章

  1. 新学期,新FLAG|去追逐梦想还是......
  2. MFC选择文件对话框和选择文件夹对话框
  3. 基于PHP+MySQL的个性化智能餐饮推荐系统
  4. 用python连接xmapp数据库
  5. 使用命令行编译、运行Java程序
  6. 《大数据之路-阿里巴巴大数据实践》第一章 总述
  7. Object转boolean类型,Object转int类型,打包报错,提示:object找不到int
  8. 怎么禁止windows音频设备图形隔离程序_Windows 10中音频设备图形间隔内存占用较高的处理方法...
  9. 3. iphone项目如何联机调试和发布程序(99$)
  10. Android开发宇视监控播放,宇视科技视频监控(EZPlayer)