
Я думал об использовании прокручиваемых вкладок, и это в некоторой степени работает, за исключением того, что я все еще выясняю, как уменьшить пространство между элементами обрезки, которые вы видите на рисунке выше.
Что я могу сделать? пробовали?
Код: Выделить всё
@Composable
fun CropBar(onCropClicked: (Int) -> Unit) {
var selectedIndex by remember { mutableStateOf(0) }
val pages = listOf("kotlin", "java", "c#", "php", "golang","A","B","C")
val colors = listOf(Color.Yellow, Color.Red, Color.White, Color.Blue, Color.Magenta)
val indicator = @Composable { tabPositions: List ->
val color = when (selectedIndex) {
0 -> colors[0]
1 -> colors[1]
2 -> colors[2]
3 -> colors[3]
else -> colors[4]
}
CustomIndicator(tabPositions = tabPositions, selectedIndex = selectedIndex, color)
}
ScrollableTabRow(
modifier = Modifier
.fillMaxWidth()
.height(58.dp),
selectedTabIndex = selectedIndex,
containerColor = Color(0xFF03753C),
indicator = indicator,
edgePadding = 0.dp,
divider = {
},
) {
pages.forEachIndexed { index, title ->
Tab(
modifier = Modifier
.height(58.dp)
.width(74.dp)
.zIndex(2f),
selected = selectedIndex == index,
onClick = {
selectedIndex = index
onCropClicked(index)
},
interactionSource = NoRippleInteractionSource()
) {
SampleImage(selectedIndex)
}
}
}
}
@Composable
private fun CustomIndicator(tabPositions: List, selectedIndex: Int, color: Color) {
val transition = updateTransition(selectedIndex, label = "transition")
val indicatorStart by transition.animateDp(
transitionSpec = {
tween(
durationMillis = 500,
easing = LinearOutSlowInEasing
)
},
label = ""
) {
tabPositions[it].left
}
val indicatorEnd by transition.animateDp(
transitionSpec = {
tween(
durationMillis = 500,
easing = LinearOutSlowInEasing
)
},
label = "",
) {
tabPositions[it].right
}
Box(
Modifier
.padding(top = 8.dp)
.offset(x = indicatorStart)
.wrapContentSize(align = Alignment.BottomStart)
.width(indicatorEnd - indicatorStart)
.paint(
// Replace with your image id
painterResource(id = R.drawable.ic_test), // some background vector drawable image
contentScale = ContentScale.FillWidth,
colorFilter = ColorFilter.tint(color) // for tinting
)
.zIndex(1f)
)
}
@Composable
fun SampleImage(selectedIndex: Int) {
BoxWithConstraints(
modifier = Modifier,
) {
Image(
modifier = Modifier
.padding(top = 8.dp)
.width(42.dp)
.height(42.dp)
.align(Alignment.BottomCenter),
painter = painterResource(id = R.drawable.ic_img_round),
contentDescription = "Image"
)
if(selectedIndex == 1) {
Text(
text = "180 Days",
fontSize = 8.sp,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(top = 18.dp)
.width(42.dp)
.clip(RoundedCornerShape(10.dp))
.background(Color.Gray)
.graphicsLayer {
translationX = 5f
}
)
}
}
}
class NoRippleInteractionSource : MutableInteractionSource {
override val interactions: Flow = emptyFlow()
override suspend fun emit(interaction: Interaction) {}
override fun tryEmit(interaction: Interaction) = true
}
[img]https://i .sstatic.net/fpNdk.gif[/img]
Желаемый результат: я должен иметь возможность контролировать расстояние между элементами вкладок. Я не ищу решение, используя только прокручиваемые вкладки. Фактически, любой прокручиваемый компонент с выбранным элементом, имеющим фон и переход фона к новому выбранному элементу, является допустимым. Я подумал об использовании чего-то вроде Row с drawBehind изображения со смещением, а затем получил позицию элемента, по которому щелкнули, и переместил фон к выбранным элементам. Любое другое решение или идеи?
На всякий случай: https://issuetracker.google.com/issues/234942462
Примечание: я проверьте с помощью uiautomaterviewer приложение Plantix. Они используют собственный горизонтальный вид прокрутки и макет фрейма. Кривые представляют собой пользовательский путь с использованием кубической кривой Безье. Я предполагаю, что вычисляется смещение выбранной обрезки или границ, а затем перемещается фоновый вид к определенному смещению и обратно.
Подробнее здесь: https://stackoverflow.com/questions/765 ... in-compose
Мобильная версия