步骤 1: 创建心形Drawable资源

首先,我们需要创建一个心形的Drawable资源。这可以通过在res/drawable目录下创建一个XML文件来完成。

<!-- res/drawable/heart_shape.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportWidth="100"
    android:viewportHeight="100">
    <path
        android:fillColor="#FF0000"
        android:pathData="M50,10 C30,70 20,80 50,90 C80,80 70,70 50,10 Z" />
</vector>

步骤 2: 创建自定义View

接下来,我们需要创建一个自定义View来绘制心形,并实现动态效果。

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils

class HeartTree @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val paint = Paint().apply {
        color = ContextCompat.getColor(context, R.color.heart_color)
        isAntiAlias = true
    }

    private val heartDrawable: VectorDrawableCompat
    private var heartSize = 50f
    private var heartX = 0f
    private var heartY = 0f
    private var heartAlpha = 255

    init {
        heartDrawable = VectorDrawableCompat.create(resources, R.drawable.heart_shape, context.theme)!!
        heartDrawable.setBounds(0, 0, heartSize.toInt(), heartSize.toInt())
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        heartDrawable.alpha = heartAlpha
        heartDrawable.draw(canvas)
    }

    fun startAnimation() {
        val xAnimator = ObjectAnimator.ofFloat(this, "heartX", 0f, width.toFloat())
        val yAnimator = ObjectAnimator.ofFloat(this, "heartY", 0f, height.toFloat())

        val alphaAnimator = ObjectAnimator.ofInt(this, "heartAlpha", 0, 255).apply {
            addUpdateListener { animation ->
                heartAlpha = animation.animatedValue as Int
                invalidate()
            }
        }

        val animatorSet = AnimatorSet().apply {
            playTogether(xAnimator, yAnimator, alphaAnimator)
            duration = 5000
            repeatCount = ObjectAnimator.INFINITE
            repeatMode = ObjectAnimator.REVERSE
        }

        animatorSet.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator) {
                // 动画结束后重新开始
                animatorSet.start()
            }
        })

        animatorSet.start()
    }

    fun setHeartX(value: Float) {
        heartX = value
        invalidate()
    }

    fun setHeartY(value: Float) {
        heartY = value
        invalidate()
    }

    fun setHeartAlpha(value: Int) {
        heartAlpha = value
        invalidate()
    }
}

步骤 3: 创建布局

接下来,我们需要创建一个布局文件来放置自定义View

<!-- res/layout/activity_main.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp">

    <com.example.yourapp.HeartTree
        android:id="@+id/heart_tree"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

步骤 4: 实现逻辑

MainActivity中,我们需要初始化自定义View,并启动动画。

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.yourapp.HeartTree
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    private lateinit var heartTree: HeartTree

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

        heartTree = findViewById(R.id.heart_tree)

        // 启动动画
        heartTree.startAnimation()
    }
}

说明

  • Drawable资源: 我们创建了一个心形的Drawable资源。
  • 自定义View: 在自定义View中实现了心形的绘制和动画效果。
  • 布局文件: 在布局文件中定义了一个自定义View
  • 启动动画: 在MainActivity中初始化自定义View,并启动动画。

这个示例展示了如何在Android中创建一个动态的心形树效果。你可以根据需要调整动画参数,例如改变动画的速度、方向或添加更多的心形元素。