快捷搜索:  汽车  科技

android studio adview讲解(多媒体绘制之SurfaceView的使用)

android studio adview讲解(多媒体绘制之SurfaceView的使用)<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_heig

引子

SurfaceView 是Android中较为特殊的视图,它继承自View,但与View不同的是它用于单独的绘画图层,平行与当前activity的独立绘画图层,且它的图层在层次排列上在Activity图层的下面,因此需要在Activity图层上限时一块透明的区域,用于显示SurfaceView图层,所以其本质是SurfaceView本身任然为Activity其上的一个透明子View 只是SurfaceView中有一个Surface对象用于绘制一个平行与当前Activity且处于surfaceView之下的图层。Surface相较于Acitivity图层的不同在于,Activity图层之上的每一个View的绘制都会导致Activity的重绘,View通过刷新来重绘视图,Android系统通过发出VSYNC信号来进行屏幕的重绘,刷新的时间间隔一般为16ms,在一些需要频繁刷新的界面,如果刷新执行很多逻辑绘制操作,就会导致刷新使用时间超过了16ms,就会导致丢帧或者卡顿,比如你更新画面的时间过长,那么你的主UI线程会被你的绘制函数阻塞,那么将无法响应按键,触屏等消息,会造成 ANR 问题。而与View不同SurfaceView的绘制方式效率非常高,因为SurfaceView的窗口刷新的时候不需要重绘应用程序的窗口,SurfaceView拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面,由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行行绘制,由于不占用主线程资源 使得它可以实现大多复杂而高效的界面绘制,如视频播放 VideoView 和OpenGl es的 GLSurfaceView。

android studio adview讲解(多媒体绘制之SurfaceView的使用)(1)

SurfaceView的特点
  • SurfaceView属于被动绘制
    当SurfaceView为可见状态下调用surfaceCreated() 创建其内的Surface图层,并可以进行绘制的初始化操作。当surfaceView为隐藏状态(不可见)当前surface会被销毁。属于被动调用,但并不是说不能主动绘制,一般的,在SurfaceHolder.Callback的surfaceCreated与surfaceDestroyed之间都是可以正常进行绘制的。
  • SurfaceView 可在任意线程进行绘制
    与一般的View必须在主线程中绘制不同 SurfaceView由于其特有的单独图层的特性让其可以在任意线程中绘制,可以减少对主线程资源的持有和完成大多比较平凡耗时的绘制工作。
  • SurfaceVie使用双缓冲机制
    双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。在图形图像处理编程过程中 双缓冲是一种基本的技术。在Android中当要绘制的数据量比较大,绘图时间比较长时,重复绘图会出现闪烁现象,引起闪烁现象的主要原因是视觉反差比较大,使用双缓冲技术可以有效解决这个问题。
SurfaceView的使用

1、创建一个自定义的SurfaceView 并实现其内的SurfaceHolder.Callback 如下:

package cn.enjoytoday.shortvideo.test.ui.customsurface import android.content.Context import android.graphics.* import android.util.AttributeSet import android.view.SurfaceHolder import android.view.SurfaceHolder.SURFACE_TYPE_NORMAL import android.view.SurfaceView import java.lang.Exception /** * 作者:hfcai * 时间:19-4-22 * 博客: http://www.enjoytoday.cn * 描述:自定义SurfaceView */ class CustomerSurfaceView(context: Context attributes: AttributeSet? defStyleAttr:Int) :SurfaceView(context attributes defStyleAttr) SurfaceHolder.Callback { var mIsDrawing = false var x =1 var y = 0; private var mPath:Path?=null private var mPaint: Paint?=null var mCanvas:Canvas?=null /** * 图层改变,当Surface的状态(大小和格式)发生变化的时候会调用该函数,在surfaceCreated调用后该函数至少会被调用一次 */ override fun surfaceChanged(holder: SurfaceHolder? format: Int width: Int height: Int) { } /** * 图层销毁 surfaceView隐藏前surface会被销毁 */ override fun surfaceDestroyed(holder: SurfaceHolder?) { mIsDrawing =false } /** * 图层创建 surfaceView可见时surface会被创建 * 创建后可以开始绘制surface界面 * */ override fun surfaceCreated(holder: SurfaceHolder?) { holder?.let { mIsDrawing =true SinThread().start() // mCanvas = it.lockCanvas() //lockCanvas锁定整个画布,不缓存绘制,同步线程锁 // mCanvas =it.lockCanvas(Rect(0 0 200 200)) //锁定指定位置画布 指定范围外的画布不重新绘制(缓存) // //解除线程锁 并提交绘制显示图像 // it.unlockCanvasAndPost(mCanvas) } } /** * 构造方法 */ constructor(context: Context attributes: AttributeSet?):this(context attributes -1) constructor(context: Context):this(context null) init { //初始化操作 holder.addCallback(this) isFocusable = true isFocusableInTouchMode = true keepScreenOn = true } /** * 刷新绘制 */ fun refreshSin(){ SinThread().start() } fun cos(){ CosThread().start() } /** * 正弦函数 */ inner class SinThread :Thread(){ override fun run() { x =1 y=0 mPaint = Paint() mPaint?.strokeWidth=12f mPaint?.color = Color.BLUE mPath = Path() while (mIsDrawing) { try { mCanvas = holder.lockCanvas() mCanvas?.drawColor(Color.WHITE) mCanvas?.drawPath(mPath mPaint) } catch (e: Exception) { e.printStackTrace() } finally { if (mCanvas != null) { holder?.unlockCanvasAndPost(mCanvas) } } x =1 if (x<=width) { y = (100*Math.sin(x*2*Math.PI/180) 400).toInt() mPath?.lineTo(x.toFloat() y.toFloat()) }else{ break } } } } /** * 余弦函数 */ inner class CosThread :Thread(){ override fun run() { x =1 y=0 mPaint = Paint() mPaint?.strokeWidth=12f mPaint?.color = Color.BLUE mPath = Path() while (mIsDrawing) { try { mCanvas = holder.lockCanvas() mCanvas?.drawColor(Color.WHITE) mCanvas?.drawPath(mPath mPaint) } catch (e: Exception) { e.printStackTrace() } finally { if (mCanvas != null) { holder?.unlockCanvasAndPost(mCanvas) } } x =1 if (x<=width) { y = (100*Math.cos(x*2*Math.PI/180) 400).toInt() mPath?.lineTo(x.toFloat() y.toFloat()) }else{ break } } } } }

如上,完成一个被动绘制和开放两个主动绘制的方法。

2、在xml中使用

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <cn.enjoytoday.shortvideo.test.ui.customsurface.CustomerSurfaceView android:id="@ id/customerSurfaceView" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_width="match_parent" android:layout_height="300dp"/> <LinearLayout app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/customerSurfaceView" android:layout_marginTop="20dp" android:padding="10dp" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@ id/beginDraw" android:text="开始绘制" android:onClick="onClick" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:id="@ id/cosDraw" android:text="绘制cos" android:onClick="onClick" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout>

3、 在activity控制

class CustomSurfaceActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_custom_surface) } /** * 点击事件监听 */ fun onClick(view: View){ when(view.id){ R.id.beginDraw -> customerSurfaceView.refreshSin() R.id.cosDraw -> customerSurfaceView.cos() } } }

猜您喜欢: