diff --git a/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Color.kt b/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Color.kt
index 2d774b6d..6a54a15b 100644
--- a/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Color.kt
+++ b/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Color.kt
@@ -42,3 +42,4 @@ val Gray900 = Color(0xFF121212)
val SystemGreen = Color(0xFF4FCF6B)
val SystemRed = Color(0xFFFF584E)
+val Kakao = Color(0xFFFBD300)
diff --git a/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Theme.kt b/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Theme.kt
index 45c85494..55ff2475 100644
--- a/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Theme.kt
+++ b/core/designsystem/src/main/kotlin/com/nexters/ilab/android/core/designsystem/theme/Theme.kt
@@ -1,6 +1,5 @@
package com.nexters.ilab.android.core.designsystem.theme
-import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
@@ -9,12 +8,7 @@ import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.SideEffect
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.platform.LocalView
-import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
@@ -53,27 +47,6 @@ fun ILabTheme(
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
- val view = LocalView.current
-
- if (!view.isInEditMode) {
- SideEffect {
- val window = (view.context as Activity).window
-
- window.statusBarColor = if (darkTheme) Color.Black.toArgb() else Color.White.toArgb()
- window.navigationBarColor = if (darkTheme) Color.Black.toArgb() else Color.White.toArgb()
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- // remove unnecessary black screen from bars
- window.isNavigationBarContrastEnforced = false
- }
-
- val windowsInsetsController = WindowCompat.getInsetsController(window, view)
-
- // status bar's icon always visible
- windowsInsetsController.isAppearanceLightStatusBars = !darkTheme
- windowsInsetsController.isAppearanceLightNavigationBars = !darkTheme
- }
- }
MaterialTheme(
colorScheme = colorScheme,
diff --git a/core/designsystem/src/main/res/drawable/bg_login_screen.png b/core/designsystem/src/main/res/drawable/bg_login_screen.png
new file mode 100644
index 00000000..1f63d648
Binary files /dev/null and b/core/designsystem/src/main/res/drawable/bg_login_screen.png differ
diff --git a/core/designsystem/src/main/res/drawable/ic_ilab_logo_110.xml b/core/designsystem/src/main/res/drawable/ic_ilab_logo_110.xml
new file mode 100644
index 00000000..3ab37fde
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_ilab_logo_110.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_kakao.xml b/core/designsystem/src/main/res/drawable/ic_kakao.xml
new file mode 100644
index 00000000..8edda505
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_kakao.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml
index 34043295..0557195f 100644
--- a/core/designsystem/src/main/res/values/strings.xml
+++ b/core/designsystem/src/main/res/values/strings.xml
@@ -4,6 +4,7 @@
카카오 로그인
+ 반가워요! 아이랩에서 나만의\n프로필을 만들어보세요!
홈
diff --git a/core/ui/src/main/kotlin/com/nexters/ilab/core/ui/component/Image.kt b/core/ui/src/main/kotlin/com/nexters/ilab/core/ui/component/Image.kt
index 5be39470..686f3487 100644
--- a/core/ui/src/main/kotlin/com/nexters/ilab/core/ui/component/Image.kt
+++ b/core/ui/src/main/kotlin/com/nexters/ilab/core/ui/component/Image.kt
@@ -1,6 +1,8 @@
package com.nexters.ilab.core.ui.component
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
@@ -27,7 +29,7 @@ fun ExampleImage(
if (LocalInspectionMode.current) {
Icon(
imageVector = Icons.Outlined.Person,
- contentDescription = "Image Icon",
+ contentDescription = "Example Image Icon",
modifier = Modifier
.width(103.dp)
.height(139.dp),
@@ -56,7 +58,7 @@ fun NetworkImage(
if (LocalInspectionMode.current) {
Icon(
imageVector = Icons.Outlined.Person,
- contentDescription = "Image Icon",
+ contentDescription = "Network Image Icon",
modifier = Modifier
.width(186.dp)
.aspectRatio(1f),
@@ -74,12 +76,34 @@ fun NetworkImage(
}
}
+@Composable
+fun BackgroundImage(
+ resId: Int,
+ contentDescription: String,
+ modifier: Modifier = Modifier,
+) {
+ val context = LocalContext.current
+
+ if (LocalInspectionMode.current) {
+ Box(modifier = Modifier.fillMaxSize())
+ } else {
+ AsyncImage(
+ model = ImageRequest.Builder(context)
+ .data(resId)
+ .build(),
+ contentDescription = contentDescription,
+ contentScale = ContentScale.FillBounds,
+ modifier = modifier,
+ )
+ }
+}
+
@ComponentPreview
@Composable
fun ExampleImagePreview() {
ExampleImage(
resId = 0,
- contentDescription = "Image Icon",
+ contentDescription = "Example Image Icon",
)
}
@@ -88,6 +112,15 @@ fun ExampleImagePreview() {
fun NetworkImagePreview() {
NetworkImage(
imageUrl = "",
- contentDescription = "Image Icon",
+ contentDescription = "Network Image Icon",
+ )
+}
+
+@ComponentPreview
+@Composable
+fun BackgroundImagePreview() {
+ BackgroundImage(
+ resId = 0,
+ contentDescription = "Background Image Icon",
)
}
diff --git a/feature/intro/build.gradle.kts b/feature/intro/build.gradle.kts
index b5b9b956..a40185f0 100644
--- a/feature/intro/build.gradle.kts
+++ b/feature/intro/build.gradle.kts
@@ -12,5 +12,6 @@ dependencies {
implementations(
libs.androidx.core,
libs.timber,
+ libs.system.ui.controller,
)
}
diff --git a/feature/intro/src/main/kotlin/com/nexters/ilab/android/feature/intro/IntroActivity.kt b/feature/intro/src/main/kotlin/com/nexters/ilab/android/feature/intro/IntroActivity.kt
index e0890bb9..3408e922 100644
--- a/feature/intro/src/main/kotlin/com/nexters/ilab/android/feature/intro/IntroActivity.kt
+++ b/feature/intro/src/main/kotlin/com/nexters/ilab/android/feature/intro/IntroActivity.kt
@@ -4,10 +4,13 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.graphics.Color
import com.nexters.ilab.android.core.designsystem.theme.ILabTheme
import com.nexters.ilab.android.feature.navigator.LoginNavigator
import com.nexters.ilab.android.feature.navigator.MainNavigator
import dagger.hilt.android.AndroidEntryPoint
+import tech.thdev.compose.exteions.system.ui.controller.rememberExSystemUiController
import javax.inject.Inject
@AndroidEntryPoint
@@ -23,6 +26,18 @@ class IntroActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
+ val systemUiController = rememberExSystemUiController()
+
+ DisposableEffect(systemUiController) {
+ systemUiController.setSystemBarsColor(
+ color = Color.White,
+ darkIcons = true,
+ isNavigationBarContrastEnforced = false,
+ )
+
+ onDispose {}
+ }
+
ILabTheme {
IntroRoute(
navigateToLogin = {
diff --git a/feature/login/build.gradle.kts b/feature/login/build.gradle.kts
index aca99daa..42b979f5 100644
--- a/feature/login/build.gradle.kts
+++ b/feature/login/build.gradle.kts
@@ -11,7 +11,9 @@ android {
dependencies {
implementations(
libs.androidx.core,
+ libs.androidx.activity.compose,
libs.timber,
libs.kakao.auth,
+ libs.system.ui.controller,
)
}
diff --git a/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginActivity.kt b/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginActivity.kt
index 1ffcb75f..299020ff 100644
--- a/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginActivity.kt
+++ b/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginActivity.kt
@@ -3,10 +3,14 @@ package com.nexters.ilab.android.feature.login
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.graphics.Color
import com.nexters.ilab.android.core.designsystem.theme.ILabTheme
import com.nexters.ilab.android.feature.navigator.MainNavigator
import dagger.hilt.android.AndroidEntryPoint
+import tech.thdev.compose.exteions.system.ui.controller.rememberExSystemUiController
import javax.inject.Inject
@AndroidEntryPoint
@@ -17,8 +21,22 @@ class LoginActivity : ComponentActivity() {
lateinit var mainNavigator: MainNavigator
override fun onCreate(savedInstanceState: Bundle?) {
+ enableEdgeToEdge()
super.onCreate(savedInstanceState)
+
setContent {
+ val systemUiController = rememberExSystemUiController()
+
+ DisposableEffect(systemUiController) {
+ systemUiController.setSystemBarsColor(
+ color = Color.Transparent,
+ darkIcons = true,
+ isNavigationBarContrastEnforced = false,
+ )
+
+ onDispose {}
+ }
+
ILabTheme {
LoginRoute(
navigateToHome = {
diff --git a/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginScreen.kt b/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginScreen.kt
index 1eb728bb..81fca7d9 100644
--- a/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginScreen.kt
+++ b/feature/login/src/main/kotlin/com/nexters/ilab/android/feature/login/LoginScreen.kt
@@ -2,21 +2,29 @@ package com.nexters.ilab.android.feature.login
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
-import androidx.compose.material3.Button
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.padding
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.kakao.sdk.auth.model.OAuthToken
@@ -24,6 +32,13 @@ import com.kakao.sdk.common.model.AuthError
import com.kakao.sdk.user.UserApiClient
import com.nexters.ilab.android.core.common.UiText
import com.nexters.ilab.android.core.designsystem.R
+import com.nexters.ilab.android.core.designsystem.theme.Contents1
+import com.nexters.ilab.android.core.designsystem.theme.Gray900
+import com.nexters.ilab.android.core.designsystem.theme.Kakao
+import com.nexters.ilab.android.core.designsystem.theme.Subtitle1
+import com.nexters.ilab.core.ui.DevicePreview
+import com.nexters.ilab.core.ui.component.BackgroundImage
+import com.nexters.ilab.core.ui.component.ILabButton
import timber.log.Timber
@Composable
@@ -91,17 +106,75 @@ internal fun LoginScreen(
CircularProgressIndicator()
}
+ Box(modifier = Modifier.fillMaxSize()) {
+ BackgroundImage(
+ resId = R.drawable.bg_login_screen,
+ contentDescription = "Background Image for Login Screen",
+ modifier = Modifier.fillMaxSize(),
+ )
+ LoginContent(
+ onLoginClick = onLoginClick,
+ )
+ }
+}
+
+@Composable
+fun LoginContent(
+ onLoginClick: () -> Unit,
+) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
- horizontalAlignment = Alignment.CenterHorizontally,
+ horizontalAlignment = Alignment.Start,
) {
- Text(text = "LoginScreen")
- Spacer(modifier = Modifier.height(32.dp))
- Button(
- onClick = onLoginClick,
+ Spacer(modifier = Modifier.weight(1f))
+ Column(
+ modifier = Modifier.padding(horizontal = 21.dp),
) {
- Text(text = stringResource(id = R.string.kakao_login))
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_ilab_logo_110),
+ contentDescription = "iLab Logo",
+ tint = Color.Unspecified,
+ )
+ Spacer(modifier = Modifier.height(20.dp))
+ Text(
+ text = stringResource(id = R.string.intro_description),
+ style = Contents1,
+ )
}
+ Spacer(modifier = Modifier.weight(2f))
+ ILabButton(
+ onClick = onLoginClick,
+ modifier = Modifier
+ .fillMaxWidth()
+ .navigationBarsPadding()
+ .padding(start = 20.dp, end = 20.dp, bottom = 34.dp)
+ .height(60.dp),
+ containerColor = Kakao,
+ contentColor = Gray900,
+ text = {
+ Text(
+ text = stringResource(id = R.string.kakao_login),
+ fontSize = 18.sp,
+ style = Subtitle1,
+ )
+ },
+ leadingIcon = {
+ Icon(
+ imageVector = ImageVector.vectorResource(id = R.drawable.ic_kakao),
+ contentDescription = "Kakao Icon",
+ tint = Color.Unspecified,
+ )
+ },
+ )
}
}
+
+@DevicePreview
+@Composable
+fun LoginScreenPreview() {
+ LoginScreen(
+ uiState = LoginState(),
+ onLoginClick = {},
+ )
+}
diff --git a/feature/main/build.gradle.kts b/feature/main/build.gradle.kts
index 36d8b218..fef5d751 100644
--- a/feature/main/build.gradle.kts
+++ b/feature/main/build.gradle.kts
@@ -16,6 +16,8 @@ dependencies {
projects.feature.uploadphoto,
libs.androidx.core,
+ libs.androidx.activity.compose,
libs.kotlinx.collections.immutable,
+ libs.system.ui.controller,
)
}
diff --git a/feature/main/src/main/kotlin/com/nexters/ilab/android/feature/main/MainActivity.kt b/feature/main/src/main/kotlin/com/nexters/ilab/android/feature/main/MainActivity.kt
index 42a2a6ec..756a3e38 100644
--- a/feature/main/src/main/kotlin/com/nexters/ilab/android/feature/main/MainActivity.kt
+++ b/feature/main/src/main/kotlin/com/nexters/ilab/android/feature/main/MainActivity.kt
@@ -3,11 +3,14 @@ package com.nexters.ilab.android.feature.main
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
-import androidx.core.view.WindowCompat
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.graphics.Color
import com.nexters.ilab.android.core.designsystem.theme.ILabTheme
import com.nexters.ilab.android.feature.navigator.LoginNavigator
import dagger.hilt.android.AndroidEntryPoint
+import tech.thdev.compose.exteions.system.ui.controller.rememberExSystemUiController
import javax.inject.Inject
@AndroidEntryPoint
@@ -18,13 +21,24 @@ class MainActivity : ComponentActivity() {
lateinit var loginNavigator: LoginNavigator
override fun onCreate(savedInstanceState: Bundle?) {
+ enableEdgeToEdge()
super.onCreate(savedInstanceState)
setContent {
// TODO isDarkTheme 를 dataStore 에서 가져와서 구독하는 방식으로 수정
val isDarkTheme = false
val navigator: MainNavController = rememberMainNavController()
- WindowCompat.setDecorFitsSystemWindows(window, false)
+ val systemUiController = rememberExSystemUiController()
+
+ DisposableEffect(systemUiController) {
+ systemUiController.setSystemBarsColor(
+ color = Color.White,
+ darkIcons = true,
+ isNavigationBarContrastEnforced = false,
+ )
+
+ onDispose {}
+ }
ILabTheme(darkTheme = isDarkTheme) {
MainScreen(
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 736a51a3..c1e37908 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -44,6 +44,7 @@ ksp = "1.9.22-1.0.16"
orbit-core = "4.6.1"
kotest = "5.8.0"
kakao-core = "2.19.0"
+compose-extensions = "1.6.0-rc01"
[libraries]
@@ -78,6 +79,7 @@ androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-toolin
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidx-navigation" }
androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidx-hilt-navigation-compose" }
+system-ui-controller = { group = "tech.thdev", name = "extensions-compose-system-ui-controller", version.ref = "compose-extensions" }
retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" }
retrofit-kotlinx-serialization-converter = { group = "com.jakewharton.retrofit", name = "retrofit2-kotlinx-serialization-converter", version.ref = "kotlinx-serialization-converter" }
@@ -97,8 +99,8 @@ coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coi
compose-shimmer = { group = "com.valentinilk.shimmer", name = "compose-shimmer", version.ref = "compose-shimmer" }
kakao-auth = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakao-core" }
-kotest-runner = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
-kotest-assertion = { module = "io.kotest:kotest-assertions-core-jvm", version.ref = "kotest" }
+kotest-runner = { group = "io.kotest", name = "kotest-runner-junit5-jvm", version.ref = "kotest" }
+kotest-assertion = { group = "io.kotest", name = "kotest-assertions-core-jvm", version.ref = "kotest" }
[plugins]