Android SurfaceView,扫二维码动画

975 阅读1分钟
class FlappyBird : SurfaceView, Runnable {
    //轻量级同步,因为surfaceview是在工作线程中绘制的
    @Volatile
    private var isRunning = false

    var xx = 0f

    //以(0,0),(w,h)2点确定的矩形
    private val mDestRect: RectF by lazy { RectF(0.0f, 0.0f, width.toFloat(), height.toFloat()) }

    // 背景图
    private val mBg: Bitmap by lazy { BitmapFactory.decodeResource(resources, R.drawable.bg1) }

    //floor图
    private val mFloorBm: Bitmap by lazy {
        BitmapFactory.decodeResource(resources, R.drawable.floor_bg)
    }

    private val mThread by lazy { Thread(this) }
    private var mSpeed: Int = 0

    constructor(context: Context?) : super(context)

    //surfaceview开始创建,从宽高旧值0,0,变成xml布局中surfaceview定义的宽高如(1080,2156)
    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        Log.i("tag-->", "$w,$h,$oldw,$oldh")
    }

    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
        //先执行constructor,再onSizeChanged,再surfaceCreated
        holder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
                Log.i("tag-->", "surfaceCreated")
                // 监听到Surface创建完毕
                isRunning = true
                mThread.start()
            }

            override fun surfaceChanged(
                holder: SurfaceHolder, format: Int,
                width: Int, height: Int
            ) {
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                //surface销毁
                isRunning = false
            }
        })
        //这个surfaceview设置获得焦点等...
        isFocusable = true
        isFocusableInTouchMode = true
        keepScreenOn = true
        Log.i("tag-->", "constructor")
        //2dp
        mSpeed = Utils.dp2px(getContext(), 2)
    }


    override fun run() {
        while (isRunning) {
            //如果正在运行,就每隔50毫秒进行绘制
            val start = System.currentTimeMillis()
            drawSelf()
            val end = System.currentTimeMillis()
            if (end - start < 50) {
                Thread.sleep(50 - (end - start))
            }
        }
    }

    //循环调用drawSelf,drawSelf自定义,其他固定写法
    private fun drawSelf() {
        val canvas = holder.lockCanvas()
        if (canvas != null) {
            //绘制背景图
            canvas.drawBitmap(mBg, null, mDestRect, null)
            xx -= mSpeed
            canvas.save()
            canvas.translate(xx, height * 4 / 5F)
            Log.i("tag-->", "$xx")
            val mPaint = Paint()
            mPaint.shader = BitmapShader(mFloorBm, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP)
            canvas.drawRect(
                xx, 0f, -xx + width.toFloat(), height - height * 4 / 5F, mPaint
            )
            canvas.restore()
            mPaint.shader = null

            holder.unlockCanvasAndPost(canvas)
        }
    }
}

补充扫二维码动画

val translateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate1)
capture_scan_line.startAnimation(translateAnimation)
-----------------------------------------------------------------------------
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <translate
        android:duration="3000"
        android:fromXDelta="0"
        android:fromYDelta="-100%"
        android:repeatCount="-1"
        android:toXDelta="0"
        android:toYDelta="0" />
</set>

图片: