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

Android BottomSheet中间状态实现问题:拖拽时出现抖动

解决BottomSheet三状态切换抖动问题

问题描述

需要实现BottomSheet的三状态平滑切换:

  • 向上滑动:底部折叠态 → 屏幕中间态 → 顶部展开态
  • 向下滑动:顶部展开态 → 屏幕中间态 → 底部折叠态

当前代码在拖拽到中间位置时出现抖动,推测是状态计算逻辑冲突导致循环回调。

问题原因

原代码在onSlide回调中频繁修改peekHeight并强制切换STATE_COLLAPSED/STATE_EXPANDED,导致BottomSheetBehavior内部状态紊乱,触发重复回调引发抖动;同时错误复用了折叠/展开状态,没有利用BottomSheet原生的半展开能力。

解决方案

利用Material Design BottomSheetBehavior原生的**半展开(STATE_HALF_EXPANDED)**状态,通过配置锚点参数实现三状态切换,避免手动修改状态引发冲突:

  1. 初始化时配置三个核心参数:底部折叠高度、半展开位置比例、允许三状态切换
  2. 移除onSlide中的强制状态修改逻辑,让BottomSheet自行处理过渡

修复后的代码

package com.example.test

import android.os.Bundle
import android.util.TypedValue
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import com.google.android.material.bottomsheet.BottomSheetBehavior

class MainActivity : AppCompatActivity() {
    private lateinit var bottomSheetBehavior: BottomSheetBehavior<ConstraintLayout>
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val bottomSheet = findViewById<ConstraintLayout>(R.id.bottomSheet)
        bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
        
        // 初始化三状态核心配置
        initBottomSheetConfig()
        
        bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
            override fun onStateChanged(bottomSheet: View, newState: Int) {
                // 可在此根据状态变化添加自定义逻辑,比如更新UI
                when(newState) {
                    BottomSheetBehavior.STATE_COLLAPSED -> {} // 底部折叠态
                    BottomSheetBehavior.STATE_HALF_EXPANDED -> {} // 屏幕中间态
                    BottomSheetBehavior.STATE_EXPANDED -> {} // 顶部展开态
                    else -> {}
                }
            }

            override fun onSlide(bottomSheet: View, slideOffset: Float) {
                // 移除原强制状态切换逻辑,避免与原生行为冲突
            }
        })
    }

    private fun initBottomSheetConfig() {
        // 设置底部折叠态高度(32dp)
        bottomSheetBehavior.peekHeight = TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            32f,
            resources.displayMetrics
        ).toInt()
        
        // 设置半展开态为屏幕垂直中间(占屏幕高度50%)
        bottomSheetBehavior.halfExpandedRatio = 0.5f
        
        // 允许在折叠、半展开、展开三个状态间切换
        bottomSheetBehavior.skipCollapsed = false
        
        // 禁用内容适配,确保半展开态严格按比例显示
        bottomSheetBehavior.isFitToContents = false
    }
}

关键说明

  • 依赖原生STATE_HALF_EXPANDED状态,无需手动计算位置,彻底避免状态循环
  • halfExpandedRatio控制半展开位置,0.5对应屏幕垂直中线
  • skipCollapsed = false是三状态切换的核心开关,允许BottomSheet在三个状态间平滑过渡
  • 移除onSlide中的强制状态修改,让BottomSheetBehavior自行处理拖拽逻辑,消除抖动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 05:17:11