Обновление библиотеки androidx.compose.material3:material3 с версии 1.3.2 до 1.4.0 вносит существенные изменения в физику анимации компонуемого BottomSheetScaffold. Новые анимации слишком «прыгучие» и чувствительны, что серьезно ухудшает удобство использования вложенного прокручиваемого содержимого.
Когда LazyColumn или другой прокручиваемый компонент помещается внутри нижнего листа, жест перетаскивания листа становится слишком чувствительным и теперь перехватывает события вертикальной прокрутки, предназначенные для вложенного содержимого. Когда пользователь пытается прокрутить список, сам лист начинает сворачиваться. Это чрезвычайно затрудняет навигацию по содержимому нижнего листа и приводит к разочарованию и ухудшению пользовательского опыта. Такое поведение является прямым регрессом по сравнению с версией 1.3.2, где вложенная прокрутка работала предсказуемо.
В этом посте представлен минимальный воспроизводимый пример ошибки. Цель состоит в том, чтобы найти технический обходной путь для восстановления ожидаемого, менее чувствительного поведения прокрутки из версии 1.3.2 в ожидании официального исправления библиотеки.
Минимальный воспроизводимый пример (MRE)
Следующий код представляет собой отдельный автономный файл MainActivity.kt, который демонстрирует проблему. Для этого требуются только зависимости, перечисленные во фрагменте build.gradle.kts ниже.
MainActivity.kt:
Код: Выделить всё
package com.example.bottomsheetbug
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// A standard MaterialTheme setup.
MaterialTheme {
BottomSheetBugScreen()
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BottomSheetBugScreen() {
val scope = rememberCoroutineScope()
val scaffoldState = rememberBottomSheetScaffoldState(
bottomSheetState = rememberStandardBottomSheetState(
initialValue = SheetValue.PartiallyExpanded,
skipHiddenState = false
)
)
BottomSheetScaffold(
scaffoldState = scaffoldState,
sheetPeekHeight = 128.dp,
sheetContent = {
// A long list of items to ensure the content is scrollable.
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.height(600.dp) // Ensure the column has a fixed, scrollable height
) {
item {
Text(
"Scrollable Content",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(16.dp)
)
}
items(List(100) { "Item #${it + 1}" }) {
Text(it, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp))
}
}
}) { innerPadding ->
Box(
Modifier
.fillMaxSize()
.padding(innerPadding),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text("Content Area")
Spacer(Modifier.height(20.dp))
// STEP 1: Run the app and click this button to expand the bottom sheet.
Button(onClick = {
scope.launch { scaffoldState.bottomSheetState.expand() }
}) {
Text("Expand Bottom Sheet")
}
}
}
}
// STEP 2: Attempt to scroll the list of items up and down.
//
// OBSERVED BEHAVIOR (in v1.4.0): Even small vertical scrolls are intercepted
// by the sheet's drag gesture, causing it to feel "sticky" and try to collapse.
// The animation is overly bouncy.
//
// EXPECTED BEHAVIOR (as in v1.3.2): The list should scroll smoothly.
// The sheet should only begin to collapse with a distinct downward drag gesture
// after the list has been scrolled to the top.
}
Код: Выделить всё
dependencies {
// Use the Compose Bill of Materials (BOM) to manage library versions
implementation(platform("androidx.compose:compose-bom:2025.10.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
// The specific Material 3 library where the bug is observed
implementation("androidx.compose.material3:material3:1.4.0")
// To test the old, correct behavior, downgrade the line above to:
// implementation("androidx.compose.material3:material3:1.3.2")
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.2")
implementation("androidx.activity:activity-compose:1.9.0")
}
Ожидаемое поведение (в версии 1.3.2):
В версии 1.3.2 взаимодействие было точным и предсказуемым. Механизм вложенной прокрутки позволял LazyColumn использовать все жесты вертикальной прокрутки до тех пор, пока не была достигнута граница содержимого (верхняя часть списка). Только тогда последующие жесты вниз будут интерпретироваться как перетаскивание для сворачивания листа.
Фактическое поведение (в версии 1.4.0):
В версии 1.4.0 BottomSheetScaffold демонстрирует слишком чувствительную и упругую физику движения. Такая высокая чувствительность является прямой причиной проблемы вложенной прокрутки. Лист чрезмерно реагирует на любую разницу вертикальной прокрутки, в результате чего намерение пользователя прокручивать LazyColumn ошибочно интерпретируется как намерение перетащить и закрыть лист.
Свидетельство/предположение основной причины
Код: Выделить всё
// in androidx.compose.material3.BottomSheetScaffold.kt
// TODO Load the motionScheme tokens from the component tokens file
val anchoredDraggableMotion: FiniteAnimationSpec =...
[*]Об этой проблеме было сообщено и подтверждено на официальном трекере проблем Google: https://issuetracker.google.com/issues/293394923
[*]Короткое видео с примером BottomSheet
Подробнее здесь: https://stackoverflow.com/questions/797 ... -in-v1-4-0
Мобильная версия