diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index e78c245d..e045b811 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -46,10 +46,11 @@ dependencies {
implementation(libs.kakao.user)
implementation(projects.feature.auth)
- implementation(projects.feature.etc)
+ implementation(projects.feature.setting)
implementation(projects.feature.matching)
implementation(projects.feature.mypage)
implementation(projects.core.designsystem)
implementation(projects.core.navigation)
+ implementation(projects.core.commonUi)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/puzzle/piece/navigation/AppNavHost.kt b/app/src/main/java/com/puzzle/piece/navigation/AppNavHost.kt
index 4364d591..32b4ea71 100644
--- a/app/src/main/java/com/puzzle/piece/navigation/AppNavHost.kt
+++ b/app/src/main/java/com/puzzle/piece/navigation/AppNavHost.kt
@@ -5,7 +5,7 @@ import androidx.compose.ui.Modifier
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import com.puzzle.auth.navigation.authNavGraph
-import com.puzzle.etc.navigation.etcScreen
+import com.puzzle.setting.navigation.settingScreen
import com.puzzle.matching.navigation.matchingNavGraph
import com.puzzle.mypage.navigation.myPageScreen
import com.puzzle.navigation.AuthGraph
@@ -23,6 +23,6 @@ fun AppNavHost(
authNavGraph()
matchingNavGraph()
myPageScreen()
- etcScreen()
+ settingScreen()
}
}
diff --git a/app/src/main/java/com/puzzle/piece/navigation/TopLevelDestinvation.kt b/app/src/main/java/com/puzzle/piece/navigation/TopLevelDestinvation.kt
index ef734737..199a1ba3 100644
--- a/app/src/main/java/com/puzzle/piece/navigation/TopLevelDestinvation.kt
+++ b/app/src/main/java/com/puzzle/piece/navigation/TopLevelDestinvation.kt
@@ -1,41 +1,35 @@
package com.puzzle.piece.navigation
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Call
-import androidx.compose.material.icons.outlined.Call
-import androidx.compose.ui.graphics.vector.ImageVector
-import com.puzzle.navigation.EtcRoute
+import androidx.annotation.DrawableRes
+import com.puzzle.navigation.SettingRoute
import com.puzzle.navigation.MatchingGraphDest
import com.puzzle.navigation.MyPageRoute
+import com.puzzle.piece.R
import kotlin.reflect.KClass
enum class TopLevelDestination(
- val selectedIcon: ImageVector,
- val unselectedIcon: ImageVector,
- val iconText: String,
- val titleText: String,
+ @DrawableRes val iconDrawableId: Int,
+ val contentDescription: String,
+ val title: String,
val route: KClass<*>,
) {
- MATCHING(
- selectedIcon = Icons.Filled.Call,
- unselectedIcon = Icons.Outlined.Call,
- iconText = "매칭",
- titleText = "매칭",
- route = MatchingGraphDest.MatchingRoute::class,
- ),
MY_PAGE(
- selectedIcon = Icons.Filled.Call,
- unselectedIcon = Icons.Outlined.Call,
- iconText = "마이페이지",
- titleText = "마이페이지",
+ iconDrawableId = R.drawable.ic_profile,
+ contentDescription = "프로필",
+ title = "프로필",
route = MyPageRoute::class,
),
- ETC(
- selectedIcon = Icons.Filled.Call,
- unselectedIcon = Icons.Outlined.Call,
- iconText = "ETC",
- titleText = "ETC",
- route = EtcRoute::class,
+ MATCHING(
+ iconDrawableId = R.drawable.ic_profile,
+ contentDescription = "매칭",
+ title = "매칭",
+ route = MatchingGraphDest.MatchingRoute::class,
+ ),
+ SETTING(
+ iconDrawableId = R.drawable.ic_setting,
+ contentDescription = "설정",
+ title = "설정",
+ route = SettingRoute::class,
);
companion object {
diff --git a/app/src/main/java/com/puzzle/piece/ui/App.kt b/app/src/main/java/com/puzzle/piece/ui/App.kt
index 7174510e..f08eab2a 100644
--- a/app/src/main/java/com/puzzle/piece/ui/App.kt
+++ b/app/src/main/java/com/puzzle/piece/ui/App.kt
@@ -1,25 +1,45 @@
+@file:OptIn(ExperimentalMaterial3Api::class)
+
package com.puzzle.piece.ui
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
-import androidx.compose.material.BottomNavigation
-import androidx.compose.material.BottomNavigationItem
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.FabPosition
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.FloatingActionButtonDefaults.bottomAppBarFabElevation
import androidx.compose.material3.Icon
+import androidx.compose.material3.NavigationBar
+import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination
import androidx.navigation.NavDestination.Companion.hasRoute
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavHostController
import androidx.navigation.compose.currentBackStackEntryAsState
+import com.puzzle.common.ui.NoRippleInteractionSource
+import com.puzzle.designsystem.foundation.PieceTheme
import com.puzzle.navigation.AuthGraph
-import com.puzzle.navigation.EtcRoute
import com.puzzle.navigation.MatchingGraph
import com.puzzle.navigation.MatchingGraphDest.MatchingDetailRoute
import com.puzzle.navigation.MyPageRoute
import com.puzzle.navigation.Route
+import com.puzzle.navigation.SettingRoute
+import com.puzzle.piece.R
import com.puzzle.piece.navigation.AppNavHost
import com.puzzle.piece.navigation.TopLevelDestination
import kotlin.reflect.KClass
@@ -42,7 +62,25 @@ fun App(
navigateToTopLevelDestination = navigateToTopLevelDestination,
)
}
- }
+ },
+ floatingActionButton = {
+ if (currentDestination?.shouldHideBottomNavigation() == false) {
+ FloatingActionButton(
+ onClick = { navigateToTopLevelDestination(MatchingGraph) },
+ containerColor = PieceTheme.colors.white,
+ shape = CircleShape,
+ elevation = bottomAppBarFabElevation(),
+ modifier = Modifier.offset(y = 84.dp),
+ ) {
+ Image(
+ painter = painterResource(R.drawable.ic_matching),
+ contentDescription = null,
+ modifier = Modifier.size(80.dp),
+ )
+ }
+ }
+ },
+ floatingActionButtonPosition = FabPosition.Center,
) { innerPadding ->
val contentModifier = modifier.padding(innerPadding)
@@ -58,24 +96,51 @@ private fun AppBottomBar(
currentDestination: NavDestination?,
navigateToTopLevelDestination: (Route) -> Unit,
) {
- BottomNavigation(
- modifier = Modifier.navigationBarsPadding()
+ NavigationBar(
+ containerColor = PieceTheme.colors.white,
+ modifier = Modifier
+ .navigationBarsPadding()
+ .height(68.dp),
) {
TopLevelDestination.topLevelDestinations.forEach { topLevelRoute ->
- BottomNavigationItem(
+ NavigationBarItem(
icon = {
- Icon(
- imageVector = topLevelRoute.selectedIcon,
- contentDescription = topLevelRoute.name
- )
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.padding(top = 2.dp),
+ ) {
+ Icon(
+ painter = painterResource(topLevelRoute.iconDrawableId),
+ contentDescription = topLevelRoute.contentDescription,
+ modifier = Modifier.size(32.dp),
+ )
+
+ Text(
+ text = topLevelRoute.title,
+ style = PieceTheme.typography.captionM,
+ )
+ }
},
- label = { Text(topLevelRoute.name) },
+ alwaysShowLabel = false,
selected = currentDestination.isRouteInHierarchy(topLevelRoute.route),
+ colors = androidx.compose.material3.NavigationBarItemDefaults.colors(
+ selectedIconColor = PieceTheme.colors.primaryDefault,
+ unselectedIconColor = PieceTheme.colors.dark3,
+ selectedTextColor = PieceTheme.colors.primaryDefault,
+ unselectedTextColor = PieceTheme.colors.dark3,
+ indicatorColor = Color.Transparent,
+ ),
+ interactionSource = remember { NoRippleInteractionSource() },
onClick = {
when (topLevelRoute) {
- TopLevelDestination.MATCHING -> navigateToTopLevelDestination(MatchingGraph)
+ TopLevelDestination.MATCHING -> navigateToTopLevelDestination(
+ MatchingGraph
+ )
+
TopLevelDestination.MY_PAGE -> navigateToTopLevelDestination(MyPageRoute)
- TopLevelDestination.ETC -> navigateToTopLevelDestination(EtcRoute)
+ TopLevelDestination.SETTING -> navigateToTopLevelDestination(
+ SettingRoute
+ )
}
},
)
@@ -85,21 +150,11 @@ private fun AppBottomBar(
private val HIDDEN_BOTTOM_NAV_ROUTES = setOf(
AuthGraph::class.qualifiedName,
- MatchingDetailRoute::class.qualifiedName
+ MatchingDetailRoute::class.qualifiedName,
)
-/**
- * 현재 목적지가 바텀 네비게이션이 보여지지 않는 화면인지 확인하는 메서드
- */
private fun NavDestination?.shouldHideBottomNavigation(): Boolean =
- this?.hierarchy?.any { destination ->
- destination.route in HIDDEN_BOTTOM_NAV_ROUTES
- } ?: false
+ this?.hierarchy?.any { destination -> destination.route in HIDDEN_BOTTOM_NAV_ROUTES } ?: false
-/**
- * 현재 목적지가 TopLevelDestination 라우트에 속하는지 확인하는 메서드
- */
private fun NavDestination?.isRouteInHierarchy(route: KClass<*>): Boolean =
- this?.hierarchy?.any {
- it.hasRoute(route)
- } ?: false
\ No newline at end of file
+ this?.hierarchy?.any { it.hasRoute(route) } == true
diff --git a/app/src/main/res/drawable/ic_matching.xml b/app/src/main/res/drawable/ic_matching.xml
new file mode 100644
index 00000000..46acaef7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_matching.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_profile.xml b/app/src/main/res/drawable/ic_profile.xml
new file mode 100644
index 00000000..bc255864
--- /dev/null
+++ b/app/src/main/res/drawable/ic_profile.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_setting.xml b/app/src/main/res/drawable/ic_setting.xml
new file mode 100644
index 00000000..3371d1cd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_setting.xml
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/build-logic/src/main/java/com/puzzle/build/logic/configure/AndroidComposes.kt b/build-logic/src/main/java/com/puzzle/build/logic/configure/AndroidComposes.kt
index 51cba50f..722cd11a 100644
--- a/build-logic/src/main/java/com/puzzle/build/logic/configure/AndroidComposes.kt
+++ b/build-logic/src/main/java/com/puzzle/build/logic/configure/AndroidComposes.kt
@@ -14,7 +14,7 @@ internal fun Project.configureAndroidCompose() {
androidExtension.apply {
composeOptions {
- kotlinCompilerExtensionVersion = "1.3.0"
+ kotlinCompilerExtensionVersion = "1.5.15"
}
buildFeatures.apply {
diff --git a/core/common-ui/src/main/java/com/puzzle/common/ui/InteractionSource.kt b/core/common-ui/src/main/java/com/puzzle/common/ui/InteractionSource.kt
new file mode 100644
index 00000000..6d276386
--- /dev/null
+++ b/core/common-ui/src/main/java/com/puzzle/common/ui/InteractionSource.kt
@@ -0,0 +1,14 @@
+package com.puzzle.common.ui
+
+import androidx.compose.foundation.interaction.Interaction
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.runtime.Immutable
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.emptyFlow
+
+@Immutable
+class NoRippleInteractionSource : MutableInteractionSource {
+ override suspend fun emit(interaction: Interaction) {}
+ override val interactions: Flow = emptyFlow()
+ override fun tryEmit(interaction: Interaction): Boolean = true
+}
diff --git a/core/navigation/src/main/java/com/puzzle/navigation/Route.kt b/core/navigation/src/main/java/com/puzzle/navigation/Route.kt
index 20da3740..a2984cc5 100644
--- a/core/navigation/src/main/java/com/puzzle/navigation/Route.kt
+++ b/core/navigation/src/main/java/com/puzzle/navigation/Route.kt
@@ -13,7 +13,7 @@ sealed class AuthGraphDest : Route {
}
@Serializable
-data object EtcRoute : Route
+data object SettingRoute : Route
@Serializable
data object MatchingGraph : Route
diff --git a/feature/etc/src/main/java/com/puzzle/etc/navigation/EtcNavigation.kt b/feature/etc/src/main/java/com/puzzle/etc/navigation/EtcNavigation.kt
deleted file mode 100644
index 9dc4db8b..00000000
--- a/feature/etc/src/main/java/com/puzzle/etc/navigation/EtcNavigation.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.puzzle.etc.navigation
-
-import androidx.navigation.NavGraphBuilder
-import androidx.navigation.compose.composable
-import com.puzzle.etc.EtcRoute
-import com.puzzle.navigation.EtcRoute
-
-fun NavGraphBuilder.etcScreen() {
- composable {
- EtcRoute()
- }
-}
diff --git a/feature/matching/src/main/java/com/puzzle/matching/MatchingScreen.kt b/feature/matching/src/main/java/com/puzzle/matching/MatchingScreen.kt
index 5148a701..bc597062 100644
--- a/feature/matching/src/main/java/com/puzzle/matching/MatchingScreen.kt
+++ b/feature/matching/src/main/java/com/puzzle/matching/MatchingScreen.kt
@@ -275,4 +275,4 @@ private fun PreviewMatchingScreen() {
navigateToMatchingDetail = {},
)
}
-}
\ No newline at end of file
+}
diff --git a/feature/etc/.gitignore b/feature/setting/.gitignore
similarity index 100%
rename from feature/etc/.gitignore
rename to feature/setting/.gitignore
diff --git a/feature/etc/build.gradle.kts b/feature/setting/build.gradle.kts
similarity index 60%
rename from feature/etc/build.gradle.kts
rename to feature/setting/build.gradle.kts
index 4b387bc2..5d23cc98 100644
--- a/feature/etc/build.gradle.kts
+++ b/feature/setting/build.gradle.kts
@@ -3,5 +3,5 @@ plugins {
}
android {
- namespace = "com.puzzle.etc"
+ namespace = "com.puzzle.setting"
}
diff --git a/feature/etc/consumer-rules.pro b/feature/setting/consumer-rules.pro
similarity index 100%
rename from feature/etc/consumer-rules.pro
rename to feature/setting/consumer-rules.pro
diff --git a/feature/etc/proguard-rules.pro b/feature/setting/proguard-rules.pro
similarity index 100%
rename from feature/etc/proguard-rules.pro
rename to feature/setting/proguard-rules.pro
diff --git a/feature/etc/src/androidTest/java/com/puzzle/etc/ExampleInstrumentedTest.kt b/feature/setting/src/androidTest/java/com/puzzle/setting/ExampleInstrumentedTest.kt
similarity index 95%
rename from feature/etc/src/androidTest/java/com/puzzle/etc/ExampleInstrumentedTest.kt
rename to feature/setting/src/androidTest/java/com/puzzle/setting/ExampleInstrumentedTest.kt
index 8ba53323..8d6f6fc1 100644
--- a/feature/etc/src/androidTest/java/com/puzzle/etc/ExampleInstrumentedTest.kt
+++ b/feature/setting/src/androidTest/java/com/puzzle/setting/ExampleInstrumentedTest.kt
@@ -1,4 +1,4 @@
-package com.puzzle.etc
+package com.puzzle.setting
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
diff --git a/feature/etc/src/main/AndroidManifest.xml b/feature/setting/src/main/AndroidManifest.xml
similarity index 100%
rename from feature/etc/src/main/AndroidManifest.xml
rename to feature/setting/src/main/AndroidManifest.xml
diff --git a/feature/etc/src/main/java/com/puzzle/etc/EtcScreen.kt b/feature/setting/src/main/java/com/puzzle/setting/SettingScreen.kt
similarity index 77%
rename from feature/etc/src/main/java/com/puzzle/etc/EtcScreen.kt
rename to feature/setting/src/main/java/com/puzzle/setting/SettingScreen.kt
index b5ee9317..477492f1 100644
--- a/feature/etc/src/main/java/com/puzzle/etc/EtcScreen.kt
+++ b/feature/setting/src/main/java/com/puzzle/setting/SettingScreen.kt
@@ -1,4 +1,4 @@
-package com.puzzle.etc
+package com.puzzle.setting
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
@@ -9,14 +9,14 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp
@Composable
-fun EtcRoute(
+fun SettingRoute(
modifier: Modifier = Modifier,
) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
- Text(text = "EtcRoute", fontSize = 30.sp)
+ Text(text = "SettingRoute", fontSize = 30.sp)
}
}
@Composable
-internal fun EtcScreen() {
-}
\ No newline at end of file
+internal fun SettingScreen() {
+}
diff --git a/feature/setting/src/main/java/com/puzzle/setting/navigation/SettingNavigation.kt b/feature/setting/src/main/java/com/puzzle/setting/navigation/SettingNavigation.kt
new file mode 100644
index 00000000..6b047673
--- /dev/null
+++ b/feature/setting/src/main/java/com/puzzle/setting/navigation/SettingNavigation.kt
@@ -0,0 +1,12 @@
+package com.puzzle.setting.navigation
+
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.compose.composable
+import com.puzzle.setting.SettingRoute
+import com.puzzle.navigation.SettingRoute
+
+fun NavGraphBuilder.settingScreen() {
+ composable {
+ SettingRoute()
+ }
+}
diff --git a/feature/etc/src/test/java/com/puzzle/etc/ExampleUnitTest.kt b/feature/setting/src/test/java/com/puzzle/setting/ExampleUnitTest.kt
similarity index 92%
rename from feature/etc/src/test/java/com/puzzle/etc/ExampleUnitTest.kt
rename to feature/setting/src/test/java/com/puzzle/setting/ExampleUnitTest.kt
index 8bca67f4..da9fd3f5 100644
--- a/feature/etc/src/test/java/com/puzzle/etc/ExampleUnitTest.kt
+++ b/feature/setting/src/test/java/com/puzzle/setting/ExampleUnitTest.kt
@@ -1,4 +1,4 @@
-package com.puzzle.etc
+package com.puzzle.setting
import org.junit.Assert.assertEquals
import org.junit.Test
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 0e6e3bef..ac04860f 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,6 +1,6 @@
[versions]
## Android gradle plugin
-androidGradlePlugin = "8.6.1"
+androidGradlePlugin = "8.7.2"
## AndroidX
# https://developer.android.com/jetpack/androidx/releases/core
@@ -24,13 +24,9 @@ androidxSplashscreen = "1.0.1"
## Compose
# https://developer.android.com/develop/ui/compose/bom/bom-mapping
-androidxComposeBom = "2024.10.01"
+androidxComposeBom = "2024.12.01"
# https://developer.android.com/jetpack/androidx/releases/navigation
androidxComposeNavigation = "2.8.4"
-# https://developer.android.com/jetpack/androidx/releases/compose-material
-androidxComposeMaterial = "1.7.4"
-# https://developer.android.com/jetpack/androidx/releases/compose-material3
-androidxComposeMaterial3 = "1.3.0"
## Amplitude
# https://amplitude.com/docs/sdks/analytics/android
@@ -120,8 +116,8 @@ androidx-lifecycle-runtimeCompose = { group = "androidx.lifecycle", name = "life
androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidxLifecycle" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidxActivity" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "androidxComposeBom" }
-androidx-compose-material = { group = "androidx.compose.material", name = "material", version.ref = "androidxComposeMaterial" }
-androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "androidxComposeMaterial3" }
+androidx-compose-material = { group = "androidx.compose.material", name = "material" }
+androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 04bb79af..bed14419 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -27,7 +27,7 @@ include(":app")
include(":feature:auth")
include(":feature:mypage")
include(":feature:matching")
-include(":feature:etc")
+include(":feature:setting")
include(":core:domain")
include(":core:designsystem")
include(":core:data")