Как создать пользовательский BottomNavigationAppBar в компоновке реактивного ранца?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как создать пользовательский BottomNavigationAppBar в компоновке реактивного ранца?

Сообщение Anonymous »

Я пытаюсь создать собственную нижнюю панель навигации (см. изображение). Я создал обычную нижнюю панель приложений, но столкнулся с двумя проблемами:
  • Кажется, я не могу получить правильную гауссовую кривую. симметрия, как видно на видео. По какой-то причине он также «обрезает» части слева и справа.
    Как создать анимацию для изменения логотипа/значка при переключении между значками?
Будем благодарны за любые отзывы!
Мой текущий пользовательский BottomAppBar:
Изображение

Моя цель:
Изображение

Пример использования:
< img alt="" src="https://i.sstatic.net/SXdfV.gif" />
Мой код:
Мой Основная анимированная нижняя панель — содержит «IndentedAnimation», которая управляет шириной и высотой кривой Безье!
@Composable
fun MyCustomAnimatedBottomNavBar() {
var selectedItem by remember { mutableStateOf(0) }
var prevSelectedIndex by remember { mutableStateOf(0) }

AnimatedNavigationBar(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 60.dp)
.height(85.dp),
selectedIndex = selectedItem,
ballColor = Color.White,
cornerRadius = shapeCornerRadius(25.dp),
ballAnimation = Straight(
spring(dampingRatio = 0.6f, stiffness = Spring.StiffnessVeryLow)
),
indentAnimation = StraightIndent(
indentWidth = 60.dp,
indentHeight = 25.dp,
animationSpec = tween(1000)
)
) {
colorButtons.forEachIndexed { index, it ->
ColorButton(
modifier = Modifier.fillMaxSize(),
prevSelectedIndex = prevSelectedIndex,
selectedIndex = selectedItem,
index = index,
onClick = {
prevSelectedIndex = selectedItem
selectedItem = index
},
icon = it.icon,
contentDescription = stringResource(id = it.description),
animationType = it.animationType,
background = it.animationType.background
)
}
}
}

IndentPatch — управляет кривой Безье:
class IndentPath(
private val rect: Rect,
) {
private val maxX = 110f
private val maxY = 34f

private fun translate(x: Float, y: Float): PointF {
return PointF(
((x / maxX) * rect.width) + rect.left,
((y / maxY) * rect.height) + rect.top
)
}

fun createPath(): Path {
val start = translate(x = -90f, y = 0f) // Left corner
val middle = translate(x = 45f, y = 90f) // , Y = Depth of curve
val end = translate(x = 180f, y = 0f) // Right corner

val control1 = translate(x = 1f, y = 1f) // X1 and Y1
val control2 = translate(x = 6.62f, y = 85f) // X2 and Y2, Left bottom axis (X)
val control3 = translate(x = 130f, y = 85f)
val control4 = translate(x = 87f, y = 0f)

val path = Path()
path.moveTo(start.x, start.y)
path.cubicTo(control1.x, control1.y, control2.x, control2.y, middle.x, middle.y)
path.cubicTo(control3.x, control3.y, control4.x, control4.y, end.x, end.y)

return path
}
}

Анимированная панель навигации:
/**
*A composable function that creates an animated navigation bar with a moving ball and indent
* to indicate the selected item.
*
*@param [modifier] Modifier to be applied to the navigation bar
*@param [selectedIndex] The index of the currently selected item
*@param [barColor] The color of the navigation bar
*@param [ballColor] The color of the moving ball
*@param [cornerRadius] The corner radius of the navigation bar
*@param [ballAnimation] The animation to be applied to the moving ball
*@param [indentAnimation] The animation to be applied to the navigation bar to indent selected item
*@param [content] The composable content of the navigation bar
*/

@Composable
fun AnimatedNavigationBar(
modifier: Modifier = Modifier,
selectedIndex: Int,
barColor: Color = Color.White,
ballColor: Color = Color.Black,
cornerRadius: ShapeCornerRadius = shapeCornerRadius(0f),
ballAnimation: BallAnimation = Parabolic(tween(300)),
indentAnimation: IndentAnimation = Height(tween(300)),
content: @Composable () -> Unit,
) {

var itemPositions by remember { mutableStateOf(listOf()) }
val measurePolicy = animatedNavBarMeasurePolicy {
itemPositions = it.map { xCord ->
Offset(xCord, 0f)
}
}

val selectedItemOffset by remember(selectedIndex, itemPositions) {
derivedStateOf {
if (itemPositions.isNotEmpty()) itemPositions[selectedIndex] else Offset.Unspecified
}
}

val indentShape = indentAnimation.animateIndentShapeAsState(
shapeCornerRadius = cornerRadius,
targetOffset = selectedItemOffset
)

val ballAnimInfoState = ballAnimation.animateAsState(
targetOffset = selectedItemOffset,
)

Box(
modifier = modifier
) {
Layout(
modifier = Modifier
.graphicsLayer {
clip = true
shape = indentShape.value
}
.background(barColor),
content = content,
measurePolicy = measurePolicy
)

if (ballAnimInfoState.value.offset.isSpecified) {
ColorBall(
ballAnimInfo = ballAnimInfoState.value,
ballColor = ballColor,
sizeDp = ballSize
)
}
}
}

val ballSize = 52.dp

@Composable
private fun ColorBall(
modifier: Modifier = Modifier,
ballColor: Color,
ballAnimInfo: BallAnimInfo,
sizeDp: Dp,
) {
Box(
modifier = modifier
.ballTransform(ballAnimInfo)
.size(sizeDp)
.clip(shape = CircleShape)
.background(ballColor)
)
}


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

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

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

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

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

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