Проблема LazyColumn flingBehavior в Jetpack ComposeAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Проблема LazyColumn flingBehavior в Jetpack Compose

Сообщение Anonymous »

Я использовал следующий код в Jetpack Compose, чтобы расположить элементы в центре экрана, и мне это удалось, но когда я нажимаю на элемент, элемент перемещается вниз, и эффект flingBehavior исчезает. Кроме того, элемент расположен немного ниже точного центра.
Я хочу, чтобы ширина элементов была фиксированной, но их высота была равна WrapContentHeight(), поэтому я сделал это таким образом. Я не хочу фиксировать их на определенной высоте.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MyProductMenuCards(
navController: NavController,
categoryIndex: Int,
darkTheme: Boolean,
clicked: (Boolean) -> Unit,
productCount: (Int) -> Unit,
onCenterColorChanged: (Color) -> Unit,
onCenterImageChanged: (Int) -> Unit
) {

val viewModel: ProductsViewModel = hiltViewModel()
val list by viewModel.productsState.collectAsState()
val density = LocalDensity.current
val state = rememberLazyListState()
val context = LocalContext.current
val snappingLayout = remember(state) { SnapLayoutInfoProvider(state) }
val flingBehavior = rememberSnapFlingBehavior(snappingLayout)
val coroutineScope = rememberCoroutineScope()

val filteredList by remember {
derivedStateOf {
val selectedCategory = if (categoryIndex == 0) Category.Yemekler else Category.Icecekler
list.filter { it.category == selectedCategory }
}
}

productCount(filteredList.size)

var clicked by remember { mutableStateOf(null) }
var selectedIndex by remember { mutableStateOf(-1) }
var columnHeight by remember { mutableStateOf(0) }

// HER ÖĞENIN YÜKSEKLİĞİNİ SAKLA
val itemHeights = remember { mutableStateMapOf() }

// Snap position'ı takip et
val centeredItemIndex by remember(state.firstVisibleItemIndex, state.firstVisibleItemScrollOffset) {
derivedStateOf {
val visibleItems = state.layoutInfo.visibleItemsInfo
if (visibleItems.isEmpty()) return@derivedStateOf -1

val firstVisible = state.firstVisibleItemIndex
val scrollOffset = state.firstVisibleItemScrollOffset

if (scrollOffset > visibleItems.firstOrNull()?.size?.div(2) ?: 0) {
firstVisible + 1
} else {
firstVisible
}
}
}

LaunchedEffect(centeredItemIndex) {
if (centeredItemIndex != -1) {
selectedIndex = centeredItemIndex
}
}

// Seçili index'i güncelle
val currentSelectedIndex = if (selectedIndex != -1) selectedIndex else centeredItemIndex

// Merkezdeki öğenin yüksekliğine göre padding hesapla
val verticalPadding by remember(columnHeight, currentSelectedIndex) {
derivedStateOf {
if (columnHeight > 0 && currentSelectedIndex >= 0) {
val centerItemHeight = itemHeights[currentSelectedIndex] ?: 0
if (centerItemHeight > 0) {
((columnHeight - centerItemHeight) / 2).coerceAtLeast(0)
} else {
0
}
} else {
0
}
}
}

Box {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.onGloballyPositioned { columnHeight = it.size.height },
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp),
state = state,
flingBehavior = flingBehavior,
contentPadding = PaddingValues(vertical = with(density) { verticalPadding.toDp() })
) {
items(count = filteredList.size) { index ->
if (!darkTheme) {
MyProductMenuCard(
state = state,
currentSelectedIndex = currentSelectedIndex,
index = index,
productModel = filteredList[index],
clicked = (clicked == filteredList[index]),
onFavoriteUpdate = {
viewModel.updateProduct(it)
},
onCardClick = {
coroutineScope.launch {
state.animateScrollToItem(index)
selectedIndex = index

val productJson = Gson().toJson(filteredList[index])
val encodedJson = URLEncoder.encode(productJson, StandardCharsets.UTF_8.name())
navController.navigate("detaysayfa/$encodedJson")
}
},
onHeightMeasured = { height ->
// HER ÖĞENIN YÜKSEKLİĞİNİ SAKLA
itemHeights[index] = height
}
)
} else {
MyProductMenuCardDarkTheme(
state = state,
index = index,
productModel = filteredList[index],
onFavoriteUpdate = {
viewModel.updateProduct(it)
},
onCardClick = {
coroutineScope.launch {
val layoutInfo = state.layoutInfo
val center = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2
val itemInfo = layoutInfo.visibleItemsInfo.firstOrNull { it.index == index }

itemInfo?.let {
val targetOffset = (it.offset + it.size / 2 - center).toFloat()
state.animateScrollBy(targetOffset)
} ?: run {
state.animateScrollToItem(index)
}

val productJson = Gson().toJson(filteredList[index])
val encodedJson = URLEncoder.encode(productJson, StandardCharsets.UTF_8.name())
navController.navigate("detaysayfa/$encodedJson")
}
},
onHeightMeasured = { height ->
// HER ÖĞENIN YÜKSEKLİĞİNİ SAKLA
itemHeights[index] = height
}
)
}
}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... ck-compose
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»