求助:将Bottom Sheet Card View转换为Top Sheet Card View
改造Bottom Sheet为Top Sheet的实现方案
没问题!要把你现有的Bottom Sheet改成从顶部弹出的Top Sheet,我们需要自定义一个CoordinatorLayout.Behavior(因为原生BottomSheetBehavior仅支持从底部展开)。下面是完整的改造步骤和代码:
1. 创建自定义TopSheetBehavior类
这个类会处理Sheet从顶部展开/隐藏的布局与动画逻辑:
import android.content.Context import android.util.AttributeSet import android.view.View import androidx.coordinatorlayout.widget.CoordinatorLayout class TopSheetBehavior<V : View>(context: Context, attrs: AttributeSet) : CoordinatorLayout.Behavior<V>(context, attrs) { companion object { const val STATE_HIDDEN = 1 const val STATE_EXPANDED = 2 } private var currentState = STATE_HIDDEN override fun onLayoutChild(parent: CoordinatorLayout, child: V, layoutDirection: Int): Boolean { // 初始时将Sheet放在屏幕顶部之外,完全隐藏 parent.onLayoutChild(child, layoutDirection) child.y = -child.height.toFloat() return true } fun setState(state: Int) { currentState = state val child = child ?: return when (state) { STATE_EXPANDED -> { // 展开:将Sheet移动到屏幕顶部,完全显示 child.animate().y(0f).setDuration(300).start() } STATE_HIDDEN -> { // 隐藏:将Sheet移回顶部之外 child.animate().y(-child.height.toFloat()).setDuration(300).start() } } } fun getState(): Int = currentState }
注:如果你仍在使用
android.support库,请把androidx.coordinatorlayout.widget.CoordinatorLayout替换为android.support.design.widget.CoordinatorLayout
2. 修改布局文件(activity_main.xml)
替换原来的BottomSheetBehavior引用,同时给CardView设置顶部对齐:
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activities.SheetBehaviourActivity"> <Button android:id="@+id/testing_bottom_sheet_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="Expand Sheet" /> <androidx.cardview.widget.CardView android:id="@+id/bottom_sheet_container" android:layout_width="match_parent" android:layout_height="300dp" android:layout_gravity="top" app:cardBackgroundColor="@android:color/holo_blue_light" app:cardCornerRadius="20dp" app:layout_behavior=".TopSheetBehavior" /> <!-- 替换为自定义Behavior --> </androidx.coordinatorlayout.widget.CoordinatorLayout>
同样,若使用
android.support库,需将androidx相关控件替换为对应support版本(比如android.support.v7.widget.CardView)
3. 修改Activity代码(SheetBehaviorActivity.kt)
替换原来的BottomSheetBehavior为自定义的TopSheetBehavior,调整状态判断逻辑:
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.widget.Button import androidx.cardview.widget.CardView class SheetBehaviourActivity : AppCompatActivity() { lateinit var sheetBehavior: TopSheetBehavior<*> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val btn: Button = findViewById(R.id.testing_bottom_sheet_btn) btn.setOnClickListener { if (sheetBehavior.getState() != TopSheetBehavior.STATE_EXPANDED) { sheetBehavior.setState(TopSheetBehavior.STATE_EXPANDED) btn.text = "Close sheet" } else { sheetBehavior.setState(TopSheetBehavior.STATE_HIDDEN) btn.text = "Expand sheet" } } val sheetContainer = findViewById<CardView>(R.id.bottom_sheet_container) sheetBehavior = TopSheetBehavior.from(sheetContainer) // 初始状态设为隐藏 sheetBehavior.setState(TopSheetBehavior.STATE_HIDDEN) } }
关键说明
- 自定义
TopSheetBehavior通过控制View的y坐标实现展开/隐藏动画,初始时将CardView放在屏幕顶部外(y = -height),展开时移动到y=0的位置。 - 你可以根据需求调整动画时长(代码里的
300毫秒),或者扩展半展开等更多状态逻辑。
内容的提问来源于stack exchange,提问作者rengineer
相关产品推荐
相关产品推荐

