Android SurfaceView 你了解么?SurfaceView实现签名

367 阅读3分钟

这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战

前言

前几天在看自定义View的一些东西,然后突然脑子冒出来一个东西,很早之前自己写的一个播放器,用的是Android自带的视频播放器,还用的MediaPlayer + surfaceView,纯简单的播放,暂停,没有任何业务,但是后来发现业务堆砌上来后,满足不了了,就换了封装好的vitamio,然后一直用了1年多吧,最后公司发展,用了百度的播放器了,一直没更换过了,当然这只是个经历,想说的就是我也用过surfaceView,哈哈

SurfaceView 和 View 的区别

其实简单的说就是一个是在主线程刷新,一个是在子线程中刷新UI
View在UI线程去更新自己;
SurfaceView则在一个子线程中去更新自己
SurfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面在UI的主线程中更新动画,时间一旦太长就会出现问题
SurfaceView在新的线程中更新画面所以不会阻塞你的UI主线程,但是涉及到线程同步,需要SurfaceView中 thread处理.
举个栗子:
我们自己手动的点击事件,触发的动画用View,需要一直动一直刷新的动画用surfaceView

SurfaceView的使用

需要创建一个新的扩展了SurfaceView的类,并实现SurfaceHolder.Callback

class MySurfaceView : SurfaceView, SurfaceHolder.Callback, Runnable {
   
constructor(context: Context?) : this(context, null)
constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
    context,
    attrs,
    defStyleAttr
    ) 
override fun surfaceCreated(p0: SurfaceHolder) {
    Log.e("surfaceCreated", "surfaceCreated")
}

override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
    Log.e("surfaceChanged", "surfaceChanged")
}

override fun surfaceDestroyed(p0: SurfaceHolder) {
   Log.e("surfaceDestroyed", "surfaceDestroyed")
}
}

用法很简单,下面写一个手绘签名得了栗子:

class MySurfaceView : SurfaceView, SurfaceHolder.Callback, Runnable {
    private var mSurfaceHolder: SurfaceHolder? = null

    //绘图的Canvas
    private var mCanvas: Canvas? = null

    //子线程标志位
    private var mIsDrawing = false
    private var mPaint: Paint? = null
    private var mPath: Path? = null
    private var bitmap: Bitmap? = null

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        mPaint = Paint()
        mPaint?.setColor(Color.BLACK)
        mPaint?.setStyle(Paint.Style.STROKE)
        mPaint?.setAntiAlias(true)
        mPaint?.setStrokeWidth(5f)
        mPath = Path()
        //路径起始点(0, 100)
        //路径起始点(0, 100)
        mPath?.moveTo(0f, 100f)
        initView()
    }

    /**
     * 初始化View
     */
    private fun initView() {
        mSurfaceHolder = holder
        mSurfaceHolder?.addCallback(this)
        isFocusable = true
        keepScreenOn = true
        isFocusableInTouchMode = true
    }

    override fun surfaceCreated(p0: SurfaceHolder) {
        mIsDrawing = true
        Thread(this).start()
    }

    override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
        Log.e("surfaceChanged", "surfaceChanged")
    }

    override fun surfaceDestroyed(p0: SurfaceHolder) {
        mIsDrawing = false
    }

    override fun run() {
        while (mIsDrawing) {
            drawSomething()
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val x = event.x.toInt()
        val y = event.y.toInt()
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                Thread.sleep(10)
                mPath!!.moveTo(x.toFloat(), y.toFloat())
            }
            MotionEvent.ACTION_MOVE -> mPath!!.lineTo(x.toFloat(), y.toFloat())
            MotionEvent.ACTION_UP -> {
            }
        }
        return true
    }

    /***
     * 处理画布事件
     */
    private fun drawSomething() {
        try {
            //获得canvas对象
            mCanvas = mSurfaceHolder!!.lockCanvas()
            //绘制背景
            mCanvas?.drawColor(Color.WHITE)
            //绘制路径
            mCanvas?.drawPath(mPath!!, mPaint!!)

        } catch (e: Exception) {
        } finally {
            if (mCanvas != null) {
                //释放canvas对象并提交画布
                mSurfaceHolder!!.unlockCanvasAndPost(mCanvas)
            }
        }
    }

    /***
     * 清除画布内容
     */
    fun clearContent() {
        mSurfaceHolder!!.addCallback(this)
        mPath = Path()
    }


    /***
     * 获取画布内容,并返回bitmap对象
     */
    fun getImage(): Bitmap {
        bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888)
        var mCanvas = Canvas(bitmap!!)
        mCanvas?.drawColor(Color.WHITE)
        mCanvas?.drawPath(mPath!!, mPaint!!)
        return bitmap!!
    }

}

总结

拿起来,放下去,再拿起来,感觉还是很好,能自己想写点什么就写点什么,哪怕是记录一个时间点,也是很好的,以后看看,原来我在这里还留下了点东西,一起学习吧