Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@ package com.paw.key.presentation.ui.onboard

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.paw.key.R
import com.paw.key.core.designsystem.component.PawkeyButton
import com.paw.key.core.designsystem.theme.PawKeyTheme
import com.paw.key.presentation.ui.onboard.component.OnboardPager
import com.paw.key.presentation.ui.onboard.component.OnboardingPosting

@Composable
fun OnboardingRoute(
Expand Down Expand Up @@ -66,48 +65,61 @@ fun OnboardingScreen(
snackBarHostState: SnackbarHostState,
modifier: Modifier = Modifier,
) {
Column(

val jobList = listOf(
OnboardingPosting(
title = "우리의 강아지를 위한 산책,\nPAWKEY와 함께해요!", // 원본 텍스트로 변경
subtitle = "",
backImg = R.drawable.onboard1
),
OnboardingPosting(
title = "새로운 산책의 시작",
subtitle = "최적화된 산책 환경에서 더 즐겁고 의미있는 산책을\n우리 강아지와 함께 시작해보세요.",
backImg = R.drawable.onboard2
),
OnboardingPosting(
title = "매일매일 새로운 루트로!\n우리 강아지와 나만의 산책.",
subtitle = "",
backImg = R.drawable.onboard3
),
OnboardingPosting(
title = "산책을 기록하고 공유하고\n수정해보세요.",
subtitle = "",
backImg = R.drawable.onboard4
)
)

Box(
modifier = modifier
.fillMaxSize()
.background(color = PawKeyTheme.colors.white1)
.background(color = PawKeyTheme.colors.green500)
) {
OnboardPager(
jobList = jobList
)

Column(
verticalArrangement = Arrangement.spacedBy(12.dp),
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp, vertical = 60.dp)
.align(Alignment.BottomCenter)
.padding(horizontal = 16.dp, vertical = 64.dp)
.fillMaxWidth()
) {

Text(
text = buildAnnotatedString {
append("안녕하세요\n우리 강아지를 위한 산책,\n")
withStyle(style = SpanStyle(color = PawKeyTheme.colors.green500)) {
append("PAWKEY")
}
append("와 함께해요! ")
},
color = PawKeyTheme.colors.black,
style = PawKeyTheme.typography.head22B
PawkeyButton(
text = "신규 계정으로 회원가입",
enabled = true,
onClick = { },
isBackGround = true,
isBorder = false
)

Spacer(modifier = Modifier.weight(1F))

Column(
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
PawkeyButton(
text = "신규 계정으로 회원가입",
enabled = true,
onClick = { },
)

PawkeyButton(
text = "기존 계정으로 로그인",
enabled = true,
isBackGround = true,
isBorder = false,
onClick = { navigateSignUp() },
)
}
PawkeyButton(
text = "기존 계정으로 로그인",
enabled = true,
isBorder = false,
onClick = { navigateSignUp() },
)
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package com.paw.key.presentation.ui.onboard.component

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
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.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.paw.key.R
import com.paw.key.core.designsystem.theme.PawKeyTheme

@Preview(showBackground = true)
@Composable
private fun PreviewOnboardPager() {
PawKeyTheme {
OnboardPager(
jobList = listOf(
OnboardingPosting(
title = "우리의 강아지를 위한 산책,\nPAWKEY와 함께해요!", // 원본 텍스트로 변경
subtitle = "",
backImg = R.drawable.onboard1
),
)

)
}
}

@Composable
fun OnboardPager(
jobList: List<OnboardingPosting>,
) {
val pageCount = jobList.size
val pagerState = rememberPagerState(pageCount = { pageCount })

Box(
modifier = Modifier
.fillMaxWidth()
.height(620.dp)
.background(
color = PawKeyTheme.colors.white1,
shape = RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp))
.clip(RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp))
) {
HorizontalPager(
state = pagerState,
modifier = Modifier
.fillMaxSize()
) { page ->
val job = jobList[page]
OnboardingListItem(
title = job.title,
subtitle = job.subtitle,
backImg = job.backImg
)
}

AnimatedPagerIndicator(
pagerState = pagerState,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 20.dp),
activeColor = PawKeyTheme.colors.green500,
inactiveColor = PawKeyTheme.colors.green200
)
}
}

@Composable
fun OnboardingListItem(
title: String,
subtitle: String,
backImg: Int,
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(
color = PawKeyTheme.colors.white1,
shape = RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
)
.clip(
shape = RoundedCornerShape(bottomStart = 24.dp, bottomEnd = 24.dp)
)
) {

Image(
painter = painterResource(id = backImg),
contentDescription = "sibal",
modifier = Modifier
.fillMaxSize()
.height(596.dp)
.align(Alignment.Center),
contentScale = ContentScale.FillBounds
)
Column(
modifier = Modifier
.padding(top = 80.dp, start = 24.dp, end = 24.dp)
.zIndex(2F)
) {
val annotatedTitle = if (title.contains("PAWKEY")) {
buildAnnotatedString {
val pawkeyStart = title.indexOf("PAWKEY")
val pawkeyEnd = pawkeyStart + "PAWKEY".length

withStyle(style = SpanStyle(color = PawKeyTheme.colors.black)) {
append(title.substring(0, pawkeyStart))
}

withStyle(style = SpanStyle(color = PawKeyTheme.colors.green500)) {
append("PAWKEY")
}

withStyle(style = SpanStyle(color = PawKeyTheme.colors.black)) {
append(title.substring(pawkeyEnd))
}
}
} else {
buildAnnotatedString {
withStyle(style = SpanStyle(color = PawKeyTheme.colors.green500)) {
append(title)
}
}
}
Text(
text = annotatedTitle,
style = PawKeyTheme.typography.head24B.copy(lineHeight = 36.sp),
color = PawKeyTheme.colors.green500,
modifier = Modifier
)

if (subtitle.isNotEmpty()) {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = subtitle,
style = PawKeyTheme.typography.body16M,
color = PawKeyTheme.colors.gray400,
)
}
}

}
}

@Composable
fun AnimatedPagerIndicator(
pagerState: PagerState,
modifier: Modifier = Modifier,
activeColor: Color = Color.Blue,
inactiveColor: Color = Color.Gray,
indicatorWidth: Dp = 12.dp,
indicatorHeight: Dp = 12.dp,
spacing: Dp = 12.dp,
) {
val density = LocalDensity.current
val activeIndicatorWidth = 24.dp

Canvas(
modifier = modifier
.height(indicatorHeight)
.width(
activeIndicatorWidth + (indicatorWidth * (pagerState.pageCount - 1)) +
spacing * (pagerState.pageCount - 1)
)
) {
val canvasWidth = size.width
val canvasHeight = size.height

val indicatorWidthPx = with(density) { indicatorWidth.toPx() }
val activeIndicatorWidthPx = with(density) { activeIndicatorWidth.toPx() }
val indicatorHeightPx = with(density) { indicatorHeight.toPx() }
val spacingPx = with(density) { spacing.toPx() }

var startX = 0f

for (i in 0 until pagerState.pageCount) {
val isActive = i == pagerState.currentPage
val currentWidth = if (isActive) activeIndicatorWidthPx else indicatorWidthPx

drawRoundRect(
color = if (isActive) activeColor else inactiveColor,
topLeft = Offset(startX, (canvasHeight - indicatorHeightPx) / 2),
size = Size(currentWidth, indicatorHeightPx),
cornerRadius = CornerRadius(indicatorHeightPx / 2)
)

startX += currentWidth + spacingPx
}
}
}

data class OnboardingPosting(
val title: String,
val subtitle: String,
val backImg: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,12 @@ fun SplashScreen(
.background(color = PawKeyTheme.colors.green500),
contentAlignment = Alignment.Center
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_logo_draft),
imageVector = ImageVector.vectorResource(id = R.drawable.ic_splash_logo),
contentDescription = stringResource(id = R.string.ic_logo),
tint = Color.Unspecified,
modifier = Modifier.size(154.dp)
)

Spacer(modifier = Modifier.height(16.dp))

Text(
text = stringResource(id = R.string.ic_logo),
color = PawKeyTheme.colors.white1,
style = PawKeyTheme.typography.head22B
)
}
}
}

Loading