You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android带进度条的Toast视图:实现从左到右的抖动动画

Android Toast从左到右展开动画+进度条实现方案

1. 替换中心展开为从左到右展开动画

原growFromCenter函数以视图中心为缩放支点,要改成从左到右展开,只需调整缩放动画的X轴支点为视图左边缘,以下是两种实现方式:

方式一:基于ScaleAnimation改造

private fun View.growFromLeft(
    duration: Long,
    @FloatRange(from = 0.0, to = 1.0) startScaleRatio: Float,
    endAnimCallback: () -> Unit = {},
) {
    // X轴从左边缘(0f)开始缩放,Y轴保持垂直中心不缩放
    val growFromLeft = ScaleAnimation(
        startScaleRatio, 1f, // X轴缩放比例从startRatio到1
        1f, 1f, // Y轴保持原尺寸不变(需垂直缩放可改为startRatio到1)
        Animation.RELATIVE_TO_SELF, 0f, // X轴支点:视图左边缘
        Animation.RELATIVE_TO_SELF, 0.5f // Y轴支点:视图垂直中心
    )
    growFromLeft.duration = duration
    growFromLeft.fillAfter = true
    growFromLeft.interpolator = FastOutSlowInInterpolator()
    growFromLeft.setAnimationListener(object : Animation.AnimationListener {
        override fun onAnimationStart(p0: Animation?) = Unit
        override fun onAnimationEnd(p0: Animation?) = endAnimCallback.invoke()
        override fun onAnimationRepeat(p0: Animation?) = Unit
    })
    startAnimation(growFromLeft)
}

方式二:基于ObjectAnimator实现(更灵活)

private fun View.expandFromLeft(duration: Long, endAnimCallback: () -> Unit = {}) {
    pivotX = 0f // 固定缩放支点为视图左边缘
    scaleX = 0f // 初始宽度为0
    ObjectAnimator.ofFloat(this, "scaleX", 0f, 1f).apply {
        this.duration = duration
        interpolator = FastOutSlowInInterpolator()
        addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) = Unit
            override fun onAnimationEnd(animation: Animator?) = endAnimCallback.invoke()
            override fun onAnimationCancel(animation: Animator?) = Unit
            override fun onAnimationRepeat(animation: Animator?) = Unit
        })
        start()
    }
}

2. 与进度条结合的解决方案

方案一:展开完成后启动进度条

确保Toast完全展开后再开始进度倒计时,避免动画冲突:

// 调用示例
toastView.expandFromLeft(300) {
    val progressBar = toastView.findViewById<ProgressBar>(R.id.toast_progress)
    // 进度条从100倒转到0,模拟倒计时
    ObjectAnimator.ofInt(progressBar, "progress", 100, 0).apply {
        duration = 2000 // 进度条持续时长
        interpolator = LinearInterpolator()
        start()
    }
}

方案二:同步展开与进度条动画

若需要两个动画同时执行,用AnimatorSet组合控制:

private fun startCombinedAnimations(toastView: View, progressBar: ProgressBar) {
    // 从左到右展开动画
    val expandAnim = ObjectAnimator.ofFloat(toastView, "scaleX", 0f, 1f).apply {
        pivotX = 0f
        duration = 300
        interpolator = FastOutSlowInInterpolator()
    }
    // 进度条动画(总时长=展开时长+停留时长)
    val progressAnim = ObjectAnimator.ofInt(progressBar, "progress", 0, 100).apply {
        duration = 2300
        interpolator = LinearInterpolator()
    }
    // 组合动画:同时启动
    AnimatorSet().apply {
        play(expandAnim).with(progressAnim)
        start()
    }
}

3. 添加抖动效果

在展开动画完成后,添加横向抖动动画实现需求:

private fun View.shake(duration: Long = 500) {
    val shakeAnim = TranslateAnimation(0f, 10f, 0f, 0f).apply {
        this.duration = duration
        interpolator = CycleInterpolator(5f) // 抖动循环次数
        fillAfter = false
    }
    startAnimation(shakeAnim)
}

// 调用示例
toastView.expandFromLeft(300) {
    toastView.shake()
    // 启动进度条...
}

内容的提问来源于stack exchange,提问作者Sharan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:35:49