自定义视图 (四) SurfaceView 绘图

1. 自定义View, 测试耗时绘制卡顿, MyView.kt

class MyView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
    private val mTag = "MyTag"
    private var centerX = 0f
    private var centerY = 0f
    private var colors =
        arrayOf(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.GRAY)
    private val paint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 5f
    }

    //  一秒刷新60帧 60HZ 16毫秒保证执行完draw方法,不会觉得卡顿
    override fun draw(canvas: Canvas?) {
        super.draw(canvas)
        repeat(3000) {
            paint.color = colors.random()
            canvas?.drawCircle(centerX, centerY, it.toFloat() / 5, paint)
        }
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        centerX = event?.x ?: 0f
        centerY = event?.y ?: 0f
        invalidate()
        return super.onTouchEvent(event)
    }
}

2. 自定义SurfaceView,测试耗时绘制,不影响主线程,MySurfaceView.kt

class MySurfaceView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : SurfaceView(context, attrs) {
    private val mTag = "MyTag"
    private var centerX = 0f
    private var centerY = 0f
    private var colors =
        arrayOf(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.GRAY)
    private val paint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 5f
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        centerX = event?.x ?: 0f
        centerY = event?.y ?: 0f

        val canvas = holder.lockCanvas()
        canvas.drawColor(Color.BLACK)
        repeat(3000) {
            paint.color = colors.random()
            canvas.drawCircle(centerX, centerY, it.toFloat() / 5, paint)
        }
        holder.unlockCanvasAndPost(canvas)
        return super.onTouchEvent(event)
    }
}

3. 绘制水波纹动效,BubbleSurfaceView.kt

class BubbleSurfaceView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : SurfaceView(context, attrs) {
    private var colors =
        arrayOf(Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW, Color.MAGENTA, Color.GRAY)
    private val paint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 5f
        //离散路径效果 segmentLength:片段的长度  deviation:波动的程度
         //pathEffect = DiscretePathEffect(30f, 20f)
        pathEffect = ComposePathEffect(CornerPathEffect(30f), DiscretePathEffect(30f, 20f))
    }

    private data class Bubble(val x: Float, val y: Float, val color: Int, var radius: Float)

    private val bubblesList = mutableListOf<Bubble>()

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        val x = event?.x ?: 0f
        val y = event?.y ?: 0f
        val color = colors.random()
        val bubble = Bubble(x, y, color, 1f)
        bubblesList.add(bubble)
        if (bubblesList.size > 30) bubblesList.removeAt(0)
        return super.onTouchEvent(event)
    }

    init {
        CoroutineScope(Dispatchers.Default).launch {
            while (true) {
                if (holder.surface.isValid) {
                    val canvas = holder.lockCanvas()
                    //重置Canvas
                    canvas.drawColor(Color.BLACK)
                    //toList: 在副本上操作,保证同一时刻不操作同一个list,否则会报错
                    //filter: 过滤小于1000的才执行
                    bubblesList.toList().filter { it.radius < 3000 }.forEach {
                        paint.color = it.color
                        canvas.drawCircle(it.x, it.y, it.radius, paint)
                        it.radius += 10f
                    }
                    holder.unlockCanvasAndPost(canvas)
                }
            }
        }
    }
}

4. 布局文件引用自定义View, activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.surfaceview.BubbleSurfaceView
        android:id="@+id/view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ProgressBar
        android:visibility="invisible"
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="91dp"
        android:layout_height="85dp"
        android:layout_marginTop="64dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/view" />
</androidx.constraintlayout.widget.ConstraintLayout>

5. 调用布局文件 MainActivity.kt

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

6. 效果图

猜你喜欢

转载自blog.csdn.net/u011193452/article/details/128298124