Skip to content

Commit ff13908

Browse files
committed
[NDGL-71] design: BottomNavigationBar 디자인 수정
1 parent c377721 commit ff13908

File tree

2 files changed

+118
-17
lines changed

2 files changed

+118
-17
lines changed

app/src/main/java/com/yapp/ndgl/navigation/BottomNavTab.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,17 @@ enum class BottomNavTab(
99
val route: Route,
1010
) {
1111
TRAVEL_HELPER(
12-
icon = R.drawable.ic_nav_helper,
12+
icon = R.drawable.ic_24_tool,
1313
label = "여행 도구",
1414
route = Route.TravelHelper,
1515
),
1616
HOME(
17-
icon = R.drawable.ic_nav_home,
17+
icon = R.drawable.ic_24_home,
1818
label = "",
1919
route = Route.Home,
2020
),
2121
TRAVEL(
22-
icon = R.drawable.ic_nav_travel,
22+
icon = R.drawable.ic_24_bag,
2323
label = "여행",
2424
route = Route.Travel,
2525
),
Lines changed: 115 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,45 @@
11
package com.yapp.ndgl.ui
22

3+
import androidx.compose.animation.AnimatedVisibility
4+
import androidx.compose.animation.core.Spring
5+
import androidx.compose.animation.core.animateDpAsState
6+
import androidx.compose.animation.core.spring
7+
import androidx.compose.animation.expandHorizontally
8+
import androidx.compose.animation.fadeIn
9+
import androidx.compose.animation.fadeOut
10+
import androidx.compose.animation.shrinkHorizontally
11+
import androidx.compose.foundation.background
12+
import androidx.compose.foundation.clickable
13+
import androidx.compose.foundation.interaction.MutableInteractionSource
14+
import androidx.compose.foundation.layout.Arrangement
15+
import androidx.compose.foundation.layout.Box
16+
import androidx.compose.foundation.layout.BoxWithConstraints
17+
import androidx.compose.foundation.layout.Row
18+
import androidx.compose.foundation.layout.fillMaxHeight
19+
import androidx.compose.foundation.layout.fillMaxSize
20+
import androidx.compose.foundation.layout.fillMaxWidth
21+
import androidx.compose.foundation.layout.height
22+
import androidx.compose.foundation.layout.navigationBarsPadding
23+
import androidx.compose.foundation.layout.offset
24+
import androidx.compose.foundation.layout.padding
25+
import androidx.compose.foundation.layout.size
26+
import androidx.compose.foundation.layout.width
27+
import androidx.compose.foundation.shape.CircleShape
28+
import androidx.compose.foundation.shape.RoundedCornerShape
329
import androidx.compose.material3.Icon
4-
import androidx.compose.material3.NavigationBar
5-
import androidx.compose.material3.NavigationBarItem
630
import androidx.compose.material3.Text
731
import androidx.compose.runtime.Composable
32+
import androidx.compose.runtime.getValue
33+
import androidx.compose.runtime.remember
34+
import androidx.compose.ui.Alignment
35+
import androidx.compose.ui.Modifier
36+
import androidx.compose.ui.graphics.Color
837
import androidx.compose.ui.graphics.vector.ImageVector
938
import androidx.compose.ui.res.vectorResource
39+
import androidx.compose.ui.tooling.preview.Preview
40+
import androidx.compose.ui.unit.dp
41+
import com.yapp.ndgl.core.ui.theme.NDGLTheme
42+
import com.yapp.ndgl.core.ui.util.dropShadow
1043
import com.yapp.ndgl.navigation.BottomNavTab
1144
import com.yapp.ndgl.navigation.Route
1245

@@ -15,20 +48,88 @@ internal fun BottomNavigationBar(
1548
currentTab: Route,
1649
onTabSelected: (Route) -> Unit,
1750
) {
18-
// FIXME 네비게이션 바 디자인 수정 및 추상화
19-
NavigationBar {
20-
BottomNavTab.entries.forEach { topLevelRoute ->
21-
NavigationBarItem(
22-
selected = currentTab == topLevelRoute.route,
23-
onClick = { onTabSelected(topLevelRoute.route) },
24-
icon = {
51+
val tabs = BottomNavTab.entries
52+
val selectedIndex = tabs.indexOfFirst { it.route == currentTab }
53+
54+
BoxWithConstraints(
55+
modifier = Modifier
56+
.fillMaxWidth()
57+
.navigationBarsPadding()
58+
.padding(bottom = 20.dp)
59+
.padding(horizontal = 24.dp)
60+
.height(68.dp)
61+
.dropShadow(
62+
shape = RoundedCornerShape(34.dp),
63+
color = Color.Black.copy(alpha = 0.15f),
64+
offsetX = 1.dp,
65+
offsetY = 6.dp,
66+
blur = 12.dp,
67+
)
68+
.background(NDGLTheme.colors.white, RoundedCornerShape(34.dp))
69+
.padding(horizontal = 12.dp, vertical = 6.dp),
70+
) {
71+
val totalWidth = maxWidth
72+
val selectedWidth = maxWidth * 0.56f
73+
val unselectedWidth = (totalWidth - selectedWidth) / (tabs.size - 1)
74+
val indicatorOffset by animateDpAsState(
75+
targetValue = when (selectedIndex) {
76+
0 -> 0.dp
77+
1 -> unselectedWidth
78+
else -> totalWidth - selectedWidth
79+
},
80+
animationSpec = spring(dampingRatio = Spring.DampingRatioLowBouncy, stiffness = Spring.StiffnessLow),
81+
)
82+
83+
Box(
84+
modifier = Modifier
85+
.offset(x = indicatorOffset)
86+
.width(selectedWidth)
87+
.fillMaxHeight()
88+
.background(NDGLTheme.colors.black900, CircleShape),
89+
)
90+
91+
Row(modifier = Modifier.fillMaxSize()) {
92+
tabs.forEach { tab ->
93+
val isSelected = currentTab == tab.route
94+
95+
Row(
96+
modifier = Modifier
97+
.width(if (isSelected) selectedWidth else unselectedWidth)
98+
.fillMaxHeight()
99+
.clickable(
100+
interactionSource = remember { MutableInteractionSource() },
101+
indication = null,
102+
) { onTabSelected(tab.route) },
103+
verticalAlignment = Alignment.CenterVertically,
104+
horizontalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterHorizontally),
105+
) {
25106
Icon(
26-
imageVector = ImageVector.vectorResource(id = topLevelRoute.icon),
27-
contentDescription = topLevelRoute.label,
107+
modifier = Modifier.size(24.dp),
108+
imageVector = ImageVector.vectorResource(id = tab.icon),
109+
contentDescription = tab.label,
110+
tint = if (isSelected) NDGLTheme.colors.white else NDGLTheme.colors.black600,
28111
)
29-
},
30-
label = { Text(text = topLevelRoute.label) },
31-
)
112+
113+
AnimatedVisibility(
114+
visible = isSelected,
115+
enter = fadeIn() + expandHorizontally(),
116+
exit = fadeOut() + shrinkHorizontally(),
117+
) {
118+
Text(
119+
text = tab.label,
120+
color = NDGLTheme.colors.white,
121+
style = NDGLTheme.typography.bodyLgMedium,
122+
maxLines = 1,
123+
)
124+
}
125+
}
126+
}
32127
}
33128
}
34129
}
130+
131+
@Preview(showBackground = true)
132+
@Composable
133+
private fun BottomNavigationBarPreview() {
134+
BottomNavigationBar(currentTab = BottomNavTab.HOME.route, onTabSelected = {})
135+
}

0 commit comments

Comments
 (0)