Android Jetpack Compose 入门,写一个简单的APP(一)

770 阅读2分钟

缘由

女朋友最近老是吵着要我写个APP给她,思来想去不知道写个啥好。一次偶然聊天的过程中,我不小心把我们在一起的时间给记错了,被迫写了两百字检讨。

image.png

完事之后我痛定思痛,决心不能再犯这样的错误,于是萌生了干脆就写个记录和女朋友在一起的各种纪念日的APP。刚好最近因为工作需要学习了RN,感觉Compose写法跟RN也挺像的,就用Compose来写叭。

原型

几番思考之后,就决定怎么简单怎么来叭,光速确定好原型图之后就开工叭。

image.png

背景部分

用水波纹动画当作背景,直接约束布局包自定义控件

setContent {
    ConstraintLayout(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth(),
    ) {
        CustomWaveBgView(
            Modifier
                .fillMaxHeight()
                .fillMaxWidth()
        )
    }
}

自定义波纹控件,用Compose自带的 Canvas控件,完整代码

object CustomView {

    private val animatorValue: MutableState<Float> = mutableStateOf(0f)
    val points = ArrayList<Point>()

    @Composable
    fun CustomWaveBgView(modifier: Modifier) {
        val animator = ObjectAnimator.ofFloat(this, "value", 0f, 200f)
        val paint = Paint()
        for (i in 0 until 5) {
            val point = Point()
            points.add(point)
        }
        paint.apply {
            strokeWidth = 5f
            style = PaintingStyle.Stroke
        }
        animator.apply {
            repeatCount = -1
            duration = 5000
            interpolator = LinearInterpolator()
            start()
        }
        Canvas(
            modifier
        ) {
            drawIntoCanvas {
                for (point in points) {
                    if (point.isStart) {
                        paint.color = Color(point.color)
                        paint.alpha = (200 - point.radus) / 200
                        it.drawCircle(
                            Offset(point.x.toFloat(), point.y.toFloat()),
                            point.radus,
                            paint
                        )
                    }
                }
                animatorValue.value
            }
        }
    }

    private fun setValue(vararg: Float) {
        animatorValue.value = vararg
        for (point in points) {
            if (point.startProgress == vararg.toInt()) {
                point.startAnimator()
            }
        }
    }
}

创建了五个point,在每个Point里面开启了一个属性动画,不断的更改半径 radius 的值

在自定义的View中,创建了一个动画,保证Canvas控件一直去刷新(感觉这种方式不太好,实际上animatorValue这个变量根本没有使用,但是目前还是入门阶段,还没找到比较好的方式)

Point代码:

class Point {

    private val animator = ObjectAnimator.ofFloat(this, "value", 0f, 200f)

    var x: Int
    var y: Int
    var startProgress: Int
    var isStart = false
    var radus = 0f
    var color:Int

    init {
        x = 220 + (Math.random() * (getScreenWidth() - 400)).toInt()
        y = 220 + (Math.random() * (getScreenHeight() - 400)).toInt()
        color = Color.rgb(
            (Math.random() * 255).toFloat(),
            (Math.random() * 255).toFloat(),
            (Math.random() * 255).toFloat()
        )
        startProgress = (Math.random() * 200).toInt()
        animator.duration = 5000
        animator.interpolator = DecelerateInterpolator()
        animator.addListener(object:AnimatorListener{
            override fun onAnimationStart(animation: Animator) {
            }

            override fun onAnimationEnd(animation: Animator) {
                isStart = false
                startProgress = (Math.random() * 200).toInt()
            }

            override fun onAnimationCancel(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }
        })
    }

    private fun reset() {
        x = 220 + (Math.random() * (getScreenWidth() - 400)).toInt()
        y = 220 + (Math.random() * (getScreenHeight() - 400)).toInt()
        radus = 0f
    }

    fun startAnimator() {
        reset()
        isStart = true
        animator.start()
    }

    private fun setValue(vararg: Float) {
        radus = vararg
    }
}

动画的最大值是直接写的数字,没有做统一管理,其实不太好,但是这些不是compose里面的内容,所以能跑就行叭。

最后的效果

307d42fedeebeaf246f2018fe344e20b.gif