Android中如何调整BottomSheetBehaviour(持久化底部弹窗)的动画速度?
调整Android BottomSheetBehavior动画速度的方法
我之前也碰到过BottomSheet动画过快的问题,尤其是从STATE_HIDDEN到STATE_EXPANDED的过渡,下面两种方案可以帮你自定义动画速度:
方案一:重写BottomSheetBehavior自定义动画(推荐)
这种方法最可靠,通过继承BottomSheetBehavior并重写动画创建逻辑,完全掌控动画时长和过渡效果。
步骤1:创建自定义BottomSheetBehavior类
import android.content.Context import android.util.AttributeSet import android.view.View import android.animation.Animator import android.animation.ValueAnimator import com.google.android.material.bottomsheet.BottomSheetBehavior class SlowBottomSheetBehavior<V : View>(context: Context, attrs: AttributeSet?) : BottomSheetBehavior<V>(context, attrs) { // 自定义动画时长,这里设为2000毫秒(可根据需求调整) private val customDuration = 2000L override fun createAnimation( view: V, start: Float, end: Float, duration: Long, listener: AnimationListener ): Animator { // 判断是否是从隐藏(start=0)到展开(end=1)的状态转换 if (start == 0f && end == 1f) { return ValueAnimator.ofFloat(start, end).apply { this.duration = customDuration // 控制BottomSheet的translationY实现滑动效果 addUpdateListener { anim -> val progress = anim.animatedValue as Float view.translationY = (1 - progress) * view.height } // 回调Behavior的动画监听 addListener(object : Animator.AnimatorListener { override fun onAnimationStart(anim: Animator) = listener.onAnimationStart() override fun onAnimationEnd(anim: Animator) = listener.onAnimationEnd() override fun onAnimationCancel(anim: Animator) = listener.onAnimationCancel() override fun onAnimationRepeat(anim: Animator) = listener.onAnimationRepeat() }) } } // 其他状态转换(比如展开到隐藏)使用默认动画 return super.createAnimation(view, start, end, duration, listener) } }
步骤2:在布局中使用自定义Behavior
把布局里默认的BottomSheetBehavior替换成你自定义的类:
<LinearLayout android:id="@+id/bottom_sheet_container" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_behavior="com.your.package.name.SlowBottomSheetBehavior"> <!-- 这里放你的BottomSheet内容 --> </LinearLayout>
方案二:通过反射修改默认Spring动画参数
如果不想重写Behavior,可以尝试反射修改默认的Spring动画参数(注意:反射依赖内部实现,可能随库版本变化失效)。
默认的BottomSheet使用SpringAnimation,调整它的stiffness(刚度)和dampingRatio(阻尼比)可以改变动画速度:
import com.google.android.material.bottomsheet.BottomSheetBehavior import android.view.View import androidx.dynamicanimation.animation.SpringAnimation import androidx.dynamicanimation.animation.SpringForce // 获取BottomSheetBehavior实例 val bottomSheetView: View = findViewById(R.id.bottom_sheet_container) val behavior = BottomSheetBehavior.from(bottomSheetView) // 反射获取内部的SpringAnimation对象 try { val field = BottomSheetBehavior::class.java.getDeclaredField("mSpringAnimation") field.isAccessible = true val springAnim = field.get(behavior) as SpringAnimation // 降低刚度(值越小,动画越慢),默认是SpringForce.STIFFNESS_MEDIUM(1500f) springAnim.spring.stiffness = 500f // 调整阻尼比(值越大,弹跳越少),默认是SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY(0.5f) springAnim.spring.dampingRatio = 0.7f } catch (e: Exception) { // 反射失败时降级处理 e.printStackTrace() }
注意事项
- 如果你需要调整
STATE_EXPANDED到STATE_HIDDEN的动画速度,只需在方案一的createAnimation方法中增加对start=1f && end=0f的判断即可。 - 方案一的自定义动画要确保
translationY的计算正确,否则会出现滑动异常。
内容的提问来源于stack exchange,提问作者Prabhashankar Kannapan
相关产品推荐
相关产品推荐

