Я хочу создать пользовательский Lazylayout в JetPack Compose, который отображает стопку баннеров, аналогично стеку карт. Дизайн выглядит следующим образом:
Требования:
в то время, только три banners/cards visible in the lootout. /> Самая верхняя карта центрируется, а два других частично видны
по бокам (то есть «Peeking»). < /li>
Только верхняя карта подходит, а направление смахивания - только горизонтальный
(слева или справа). Вверху, поддержание поведения стека. Макет показывает три видимых баннера, сложенных такими, что: < /p>
На верхней карте центрирована, а два других взглядов с боковых сторон. src = "https://i.sstatic.net/dav1k9p4.gif"/>]
Проблема:
После переворота верхней карты, она снова возвращается к вершине, вместо после того, как он перемещается на конец или наносит первое, сначала Swip, а затем и Swip, а затем и наносит на первое место. Работа. @Composable
fun LazyStackLayout(
modifier: Modifier = Modifier,
state: LazyStackItemState,
itemOffset: Dp = 50.dp,
offSetItemScale: Float = 0.8f,
offsetAlpha: Float = 0.8f,
itemContent: LazyStackItemScope.() -> Unit
) {
val scope = rememberCoroutineScope()
val stackItemProvider = rememberLazyStackItemProvider(content = itemContent)
LazyLayout(
{ stackItemProvider }, modifier.pointerInput(state.currentIndex) {
detectHorizontalDragGestures(
onDragEnd = {
val threshold = size.width / 3f
when {
state.swipeOffsetX.value > threshold -> {
scope.launch {
state.rightSwipe(size)
}
}
state.swipeOffsetX.value < -threshold -> {
scope.launch {
state.leftSwipe(size)
}
}
else -> {
// Not enough swipe, reset
scope.launch {
state.swipeOffsetX.animateTo(0f)
}
}
}
},
onHorizontalDrag = { change, dragAmount ->
change.consume()
scope.launch {
state.swipeOffsetX.snapTo(state.swipeOffsetX.value + dragAmount)
}
}
)
},
null
) { constraints ->
val offsetValue = with(density) {
itemOffset.toPx().roundToInt()
}
layout(constraints.maxWidth, constraints.maxHeight) {
val itemsToMeasure = listOf(state.currentIndex, state.rightItemIndex, state.leftItemIndex)
val placeables = mutableListOf
()
itemsToMeasure.forEach { index ->
val placeable = measure(index, constraints)
placeables.addAll(placeable)
}
val x0 = (constraints.maxWidth - placeables[0].width) / 2
val y0 = (constraints.maxHeight - placeables[0].height) / 2
placeables[0].placeRelativeWithLayer(
x0,
y0,
2f
) {
transformOrigin = TransformOrigin(0.5f,0.5f)
rotationY = state.swipeOffsetX.value/10
alpha = 1f
scaleY = 1f
this.translationX = state.swipeOffsetX.value
}
val x1 = ((constraints.maxWidth - placeables[1].width) / 2) + offsetValue
val y1 = (constraints.maxHeight - placeables[1].height) / 2
placeables[1].placeRelativeWithLayer(x1, y1, 1f) {
transformOrigin = TransformOrigin(0.5f,0.5f)
rotationY = state.swipeOffsetX.value/10
alpha = offsetAlpha
scaleY = offSetItemScale
}
val x2 = ((constraints.maxWidth - placeables[2].width) / 2 )- offsetValue
val y2 = (constraints.maxHeight - placeables[2].height) / 2
placeables[2].placeRelativeWithLayer(x2, y2, 1f) {
transformOrigin = TransformOrigin(0.5f,0.5f)
rotationY = state.swipeOffsetX.value/10
alpha = offsetAlpha
scaleY = offSetItemScale
}
}
}
}
class LazyStackItemState(val items: List) {
val itemCount: Int = items.size
var currentIndex by mutableIntStateOf(0)
private set
val swipeOffsetX by mutableStateOf(Animatable(0f))
var rightItemIndex by mutableIntStateOf(currentIndex + 1)
private set
var leftItemIndex by mutableIntStateOf(items.lastIndex)
private set
suspend fun rightSwipe(size: IntSize) {
swipeOffsetX.animateTo(size.width.toFloat())
rightItemIndex = currentIndex
currentIndex = (currentIndex - 1 + itemCount) % itemCount
leftItemIndex = currentIndex - 1
swipeOffsetX.snapTo(-size.width.toFloat())
swipeOffsetX.animateTo(0f)
}
suspend fun leftSwipe(size: IntSize) {
swipeOffsetX.animateTo(-size.width.toFloat())
leftItemIndex = currentIndex
currentIndex = (currentIndex + 1 + itemCount) % itemCount
rightItemIndex = currentIndex + 1
swipeOffsetX.snapTo(size.width.toFloat())
swipeOffsetX.animateTo(0f)
}
}
@Composable
fun UseLazyStackLayout(modifier: Modifier = Modifier) {
val myDataItems = remember {
List(10) { index -> "Item $index" }
}
LazyStackLayout(
modifier = modifier,
state = LazyStackItemState(myDataItems)
) {
items(myDataItems) { value ->
Card(
modifier = Modifier
.size(200.dp),
elevation = CardDefaults.cardElevation(4.dp)
) {
Box(contentAlignment = Alignment.Center, modifier = Modifier.fillMaxSize()) {
Text(text = value, style = MaterialTheme.typography.headlineMedium)
}
}
}
}
}
< /code>
Мой дальнейший вопрос заключается в том, как работает Lazyrow или Lazycolumn, поставщик предметов? У меня был мутабллейс, который, конечно, неэффективен. (Я посмотрел исходный код, но он слишком сложный, чтобы понять). Я также попытался предоставить блок DSL, как Lazyrow/Column, создав пользовательскую область.
typealias LazyStackLayoutComposable = @Composable (LazyStackItemScope.(Int) -> Unit)
interface LazyStackItemScope {
fun items(
count: Int,
itemContent: LazyStackLayoutComposable
)
fun item(content: LazyStackLayoutComposable)
fun items(
items: List,
itemContent: @Composable (LazyStackItemScope.(T) -> Unit)
)
}
class LazyStackItemScopeImpl() : LazyStackItemScope {
private val _items = mutableListOf Unit>()
val items: List Unit> get() = _items
override fun items(
count: Int,
itemContent: LazyStackLayoutComposable
) {
repeat(count) { index ->
_items.add { [email protected](index) }
}
}
override fun item(
content: LazyStackLayoutComposable
) {
_items.add { [email protected](0) }
}
override fun items(
items: List,
itemContent: @Composable (LazyStackItemScope.(T) -> Unit)
) {
items.forEach { item ->
_items.add { [email protected](item) }
}
}
}
@OptIn(ExperimentalFoundationApi::class)
class LazyStackLazyLayoutItemProvider(
private val composables: List Unit>
) : LazyLayoutItemProvider {
override val itemCount: Int
get() = composables.size
@Composable
override fun Item(index: Int, key: Any) {
composables[index].invoke()
}
override fun getKey(index: Int): Any = index
}
< /code>
Я знаю, что предоставил слишком много кода, но это наименьшее, что я мог бы дать. : (
Подробнее здесь: https://stackoverflow.com/questions/796 ... ontal-swip
Как создать нестандартный Lazylayout со сложенными видимыми предметами и горизонтальным жестом в JetPack Compose? ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Есть ли способ создать разрыв между сложенными вертикальными полосами в Chart.JS?
Anonymous » » в форуме Jquery - 0 Ответы
- 29 Просмотры
-
Последнее сообщение Anonymous
-