Skip to content

Commit

Permalink
[Feature] OnBoardingScreen UI 로직 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
ajou4095 committed Jan 28, 2024
1 parent d3a45e5 commit 4d5cc84
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 110 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.common.view

import ac.dnd.bookkeeping.android.presentation.R
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
Expand All @@ -12,7 +11,6 @@ import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
Expand Down Expand Up @@ -81,7 +79,7 @@ fun ConfirmButtonPreview2() {
@Composable
fun ConfirmButtonPreview3() {
ConfirmButton(
text = stringResource(R.string.next_button_text),
text = "다음",
isMain = true,
modifier = Modifier
.padding(20.dp)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

sealed interface LoginOnBoardingEvent {
data object GoToNextStep : LoginOnBoardingEvent
}
sealed interface LoginOnBoardingEvent
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

sealed interface LoginOnBoardingIntent {
data object OnClickNextStep : LoginOnBoardingIntent
}
sealed interface LoginOnBoardingIntent
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

class LoginOnBoardingModel(
val loadingState: LoginOnBoardingState.Loading,
val buttonState: LoginOnBoardingState.Button
val state: LoginOnBoardingState
)
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ac.dnd.bookkeeping.android.presentation.common.util.LaunchedEffectWithLif
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.EventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.MutableEventFlow
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.eventObserve
import ac.dnd.bookkeeping.android.presentation.common.view.ConfirmButton
import ac.dnd.bookkeeping.android.presentation.ui.main.ApplicationState
import ac.dnd.bookkeeping.android.presentation.ui.main.home.HomeConstant
import ac.dnd.bookkeeping.android.presentation.ui.main.login.LoginConstant
Expand All @@ -27,25 +28,21 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus

@OptIn(ExperimentalFoundationApi::class)
@Composable
Expand All @@ -56,33 +53,18 @@ fun LoginOnBoardingScreen(
intent: (LoginOnBoardingIntent) -> Unit,
handler: CoroutineExceptionHandler
) {
var currentSelectedPage by rememberSaveable { mutableIntStateOf(0) }
val pagerState = rememberPagerState(pageCount = { 3 })
val buttonColorState = animateColorAsState(
targetValue = when (model.buttonState) {
is LoginOnBoardingState.Button.Default -> {
Color(0xFFDD55FF)
}

is LoginOnBoardingState.Button.Pressed -> {
Color(0xFFD401FE)
}
},
label = "pressed button color"
val scope = rememberCoroutineScope() + handler
val pagerState = rememberPagerState(
pageCount = { 3 }
)

LaunchedEffect(currentSelectedPage) {
pagerState.animateScrollToPage(currentSelectedPage)
}

fun navigateToHome() {
appState.navController.navigate(HomeConstant.ROUTE) {
popUpTo(LoginConstant.ROUTE) {
inclusive = true
}
}
}

Box(
modifier = Modifier
.fillMaxSize()
Expand All @@ -95,81 +77,64 @@ fun LoginOnBoardingScreen(
horizontalAlignment = Alignment.CenterHorizontally
) {
HorizontalPager(
state = pagerState
state = pagerState,
) { page ->
when (model.loadingState) {
is LoginOnBoardingState.Loading.Progress -> {
SampleImageComponent(page.toString())
}

is LoginOnBoardingState.Loading.Success -> {

}

is LoginOnBoardingState.Loading.Failure -> {

}
}
LoginOnBoardingPage(page.toString())
}

Spacer(Modifier.height(29.18.dp))

Row(
Modifier.wrapContentSize(),
horizontalArrangement = Arrangement.spacedBy(14.dp)
) {
repeat(pagerState.pageCount) { iterationIndex ->
repeat(pagerState.pageCount) { index ->
val isSelected = pagerState.currentPage == index

val color by animateColorAsState(
targetValue =
if (pagerState.currentPage == iterationIndex) Color.DarkGray
else Color.LightGray,
targetValue = if (isSelected) Color.DarkGray else Color.LightGray,
label = "iteration color"
)

Box(
modifier = Modifier
.padding(2.dp)
.clip(CircleShape)
.clickable { currentSelectedPage = iterationIndex }
.clickable {
scope.launch {
pagerState.animateScrollToPage(index)
}
}
.background(color)
.size(8.dp)
)
}
}
}

Surface(
ConfirmButton(
text = stringResource(R.string.next_button_text),
isMain = true,
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(
horizontal = 20.dp,
vertical = 12.dp
)
.fillMaxWidth()
.clickable {
intent(LoginOnBoardingIntent.OnClickNextStep)
},
shape = RoundedCornerShape(8.dp),
color = buttonColorState.value
.align(Alignment.BottomCenter)
.padding(25.dp),
) {
Text(
text = stringResource(R.string.next_button_text),
fontSize = 16.sp,
color = Color.White,
textAlign = TextAlign.Center,
modifier = Modifier.padding(14.dp)
)
navigateToHome()
}
}

LaunchedEffectWithLifecycle(event, handler) {
event.eventObserve { event ->
when (event) {
is LoginOnBoardingEvent.GoToNextStep -> navigateToHome()
}

}
}
}

@Composable
fun SampleImageComponent(contentIndex: String) {
private fun LoginOnBoardingPage(
text: String
) {
Box(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -179,7 +144,7 @@ fun SampleImageComponent(contentIndex: String) {
contentAlignment = Alignment.Center
) {
Text(
text = contentIndex,
text = text,
fontSize = 16.sp,
color = Color.Black,
)
Expand All @@ -192,8 +157,7 @@ fun LoginOnBoardingScreenPreview() {
LoginOnBoardingScreen(
appState = rememberApplicationState(),
model = LoginOnBoardingModel(
loadingState = LoginOnBoardingState.Loading.Progress,
buttonState = LoginOnBoardingState.Button.Default
state = LoginOnBoardingState.Init
),
event = MutableEventFlow(),
intent = {},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
package ac.dnd.bookkeeping.android.presentation.ui.main.login.onboarding

import ac.dnd.bookkeeping.android.domain.model.error.ServerException

sealed interface LoginOnBoardingState {
sealed interface Loading {
data object Progress : Loading
data object Success : Loading
data class Failure(val exception: ServerException) : Loading
}

sealed interface Button {
data object Default : Button
data object Pressed : Button
}
data object Init : LoginOnBoardingState
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.Mutab
import ac.dnd.bookkeeping.android.presentation.common.util.coroutine.event.asEventFlow
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand All @@ -17,28 +16,14 @@ class LoginOnBoardingViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : BaseViewModel() {

private val _loadingState: MutableStateFlow<LoginOnBoardingState.Loading> =
MutableStateFlow(LoginOnBoardingState.Loading.Progress)
val loadingState: StateFlow<LoginOnBoardingState.Loading> = _loadingState.asStateFlow()

private val _buttonState: MutableStateFlow<LoginOnBoardingState.Button> =
MutableStateFlow(LoginOnBoardingState.Button.Default)
val buttonState: StateFlow<LoginOnBoardingState.Button> = _buttonState.asStateFlow()
private val _state: MutableStateFlow<LoginOnBoardingState> =
MutableStateFlow(LoginOnBoardingState.Init)
val state: StateFlow<LoginOnBoardingState> = _state.asStateFlow()

private val _event: MutableEventFlow<LoginOnBoardingEvent> = MutableEventFlow()
val event: EventFlow<LoginOnBoardingEvent> = _event.asEventFlow()

fun onIntent(intent: LoginOnBoardingIntent) {
when (intent) {
LoginOnBoardingIntent.OnClickNextStep -> goToNextStep()
}
}

private fun goToNextStep() {
launch {
_buttonState.emit(LoginOnBoardingState.Button.Pressed)
delay(100L)
_event.emit(LoginOnBoardingEvent.GoToNextStep)
}
}
}

0 comments on commit 4d5cc84

Please sign in to comment.