Class FlappyBird: SurfaceView, Runnable {// Lightweight synchronization, because the SurfaceView is drawn in the worker thread @volatile private var isRunning =falseVar xx = 0f var xx = 0f private val mDestRect: RectF by lazy {RectF(0.0f, 0.0f, width.tofloat (), height.tofloat ())} Bitmap by lazy {BitmapFactory. DecodeResource (resources, R.d. Rawable bg1)} / / floor figure 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 is created from the previous value of 0,0, to the width and height defined by the surfaceview in the XML layout such as (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"// Monitor the Surface creation isRunning =truemThread.start() } override fun surfaceChanged( holder: SurfaceHolder, format: Int, width: Int, height: Int) {} Override fun surfaceDestroyed(holder: SurfaceHolder) {// Surface destroy isRunning =false}}) // This surfaceView is set to get focus etc... isFocusable =true
        isFocusableInTouchMode = true
        keepScreenOn = true
        Log.i("tag-->"."constructor")
        //2dp
        mSpeed = Utils.dp2px(getContext(), 2)
    }


    override fun run() {
        while(isRunning) {// If running, Val start = system.currentTimemillis () drawSelf() val end = system.currentTimemillis ()if(end-start < 50) {thread. sleep(50 - (end-start))}}drawSelf() {
        val canvas = holder.lockCanvas()
        if(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)
        }
    }
}
Copy the code

Add scanning two-dimensional code animation

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>
Copy the code

Image: