Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#320 [Ui] rule guide 바텀시트 #321

Merged
merged 13 commits into from
Feb 10, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,9 @@ fabric.properties
.idea/kotlinc.xml

.idea/
/.tmp/
/caches/
/daemon/7.3.3/
/kotlin-profile/
/native/
/wrapper/dists/gradle-7.3.3-bin/6a41zxkdtcxs8rphpq6y0069z/
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ dependencies {
implementation(appCompatTheme)
implementation(lifecycle)
implementation(navigation)
implementation(foundation)
}

Deps.DI.run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ fun MainRuleContent(
searchQuery: String = "",
onSearch: (String) -> Unit = {},
onOpenDetailRule: (Int) -> Unit = {},
onOpenRuleGuide: () -> Unit = {},
onNavigateToAddRule: () -> Unit = {},
onNavigateToRepresentRule: () -> Unit = {},
onFinish: () -> Unit = {}
Expand All @@ -55,6 +56,7 @@ fun MainRuleContent(
) {
MainRuleToolbar(
onBack = onFinish,
onOpenRuleGuide = onOpenRuleGuide,
onNavigateToRepresentRule = onNavigateToRepresentRule
)
Spacer(modifier = Modifier.padding(top = 4.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,14 @@ fun MainRuleDropDownMenu(
onDismissRequest = onDismiss
) {
RuleDropDownMenuContent(
onNavigateToRepresentation = onNavigateToRepresentation,
onNavigateToGuide = onNavigateToGuide
onNavigateToRepresentation = {
onDismiss()
onNavigateToRepresentation()
},
onNavigateToGuide = {
onDismiss()
onNavigateToGuide()
}
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import hous.release.designsystem.theme.HousTheme
@Composable
fun MainRuleToolbar(
onNavigateToRepresentRule: () -> Unit = {},
onOpenRuleGuide: () -> Unit = {},
modifier: Modifier = Modifier,
title: String = "우리 집 Rules",
onBack: () -> Unit = { }
Expand Down Expand Up @@ -62,7 +63,7 @@ fun MainRuleToolbar(
)
}
)
MainRuleDropDownMenu(expanded, onDismiss, onNavigateToRepresentRule)
MainRuleDropDownMenu(expanded, onDismiss, onNavigateToRepresentRule, onOpenRuleGuide)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package hous.release.android.presentation.our_rules.component.main

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
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.text.style.TextAlign
import androidx.compose.ui.text.style.TextAlign.*
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import hous.release.designsystem.theme.HousBlack
import hous.release.designsystem.theme.HousBlue
import hous.release.designsystem.theme.HousG2
import hous.release.designsystem.theme.HousG6
import hous.release.designsystem.theme.HousTheme
import kotlinx.coroutines.launch

// https://github.com/android/snippets/blob/5ae1f7852164d98d055b3cc6b463705989cff231/compose/snippets/src/main/java/com/example/compose/snippets/layouts/PagerSnippets.kt#L93-L103

@OptIn(ExperimentalFoundationApi::class)
@Composable
fun RuleGuideBottomSheetContent() {
Column(
modifier = Modifier.fillMaxWidth().padding(top = 20.dp, bottom = 14.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
val pageCount = 3
val pagerState = rememberPagerState(pageCount = { pageCount })
val coroutineScope = rememberCoroutineScope()
HorizontalPager(
modifier = Modifier.fillMaxWidth(),
beyondBoundsPageCount = 2, // to place more pages before and after the visible pages
state = pagerState
) { page ->
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "룰스 고정하기",
color = HousBlack,
textAlign = TextAlign.Center,
style = HousTheme.typography.b1
)
Spacer(Modifier.height(13.dp))
Text(
text = "Page: $page",
textAlign = TextAlign.Center
)
RuleGuideLottie(idx = page)
Spacer(Modifier.height(20.dp))

Text(
text = "룰스 고정 어쩌구 저쩌구",
color = HousG6,
textAlign = TextAlign.Center,
style = HousTheme.typography.description
)
}
}
Spacer(Modifier.height(17.dp))
Row(
Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
PageIndicators(pageCount, pagerState.currentPage, onSelected = { targetPage ->
coroutineScope.launch {
pagerState.animateScrollToPage(targetPage)
}
})
}
}
}

@Composable
private fun PageIndicators(pageCount: Int, currentPage: Int, onSelected: (Int) -> Unit) {
repeat(pageCount) { idx ->
PageIndicator(currentPage == idx, onSelected = { onSelected(idx) })
if (idx != pageCount - 1) {
Spacer(Modifier.width(14.dp))
}
}
}

@Composable
private fun PageIndicator(isSelected: Boolean, onSelected: () -> Unit) {
Box(
modifier = Modifier.padding(8.dp).size(8.dp).clip(CircleShape).background(
color = if (isSelected) HousBlue else HousG2
).clickable(
onClick = onSelected
)
)
}

@Composable
@Preview(showBackground = true)
private fun RuleGuideBottomSheetContentPreview() {
HousTheme {
RuleGuideBottomSheetContent()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package hous.release.android.presentation.our_rules.component.main

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.rememberLottieComposition
import hous.release.android.R

@Composable
fun RuleGuideLottie(
idx: Int
) {
val composition by rememberLottieComposition(
LottieCompositionSpec.RawRes(
provideRuleGuideLottie(
0 // TODO : lottie json 파일 다시 받으면 idx로 바꾸기
)
)
)

Box(
modifier = Modifier
.size(122.dp),
contentAlignment = Alignment.TopCenter
) {
LottieAnimation(
composition = composition,
iterations = LottieConstants.IterateForever
)
}
}

@Throws(IllegalArgumentException::class)
private fun provideRuleGuideLottie(idx: Int): Int {
return when (idx) {
0 -> R.raw.rule_guide_1
1 -> R.raw.rule_guide_2
2 -> R.raw.rule_guide_3
else -> throw IllegalArgumentException("Invalid Index: $idx")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
Expand Down Expand Up @@ -61,7 +60,6 @@ fun RuleNavGraph(

// Screens

@OptIn(ExperimentalLifecycleComposeApi::class)
private fun NavGraphBuilder.mainRuleScreen(
navController: NavController
) {
Expand Down Expand Up @@ -113,7 +111,6 @@ private fun NavGraphBuilder.mainRuleScreen(
}
}

@OptIn(ExperimentalLifecycleComposeApi::class)
private fun NavGraphBuilder.updateRuleScreen(
navController: NavController
) {
Expand Down Expand Up @@ -214,7 +211,6 @@ private fun NavGraphBuilder.updateRuleScreen(
}
}

@OptIn(ExperimentalLifecycleComposeApi::class)
private fun NavGraphBuilder.addRuleScreen(onBack: () -> Unit) {
composable(RulesScreens.Add.route) {
val viewModel = hiltViewModel<AddRuleViewModel>()
Expand Down Expand Up @@ -308,7 +304,6 @@ private fun NavGraphBuilder.addRuleScreen(onBack: () -> Unit) {
}
}

@OptIn(ExperimentalLifecycleComposeApi::class)
private fun NavGraphBuilder.representativeRuleScreen(onBack: () -> Unit) {
composable(RulesScreens.Represent.route) {
val viewModel = hiltViewModel<RepresentRuleViewModel>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.lifecycle.LifecycleEventObserver
import hous.release.android.presentation.our_rules.component.dialog.DeleteRuleDialog
import hous.release.android.presentation.our_rules.component.main.DetailRuleBottomSheetContent
import hous.release.android.presentation.our_rules.component.main.MainRuleContent
import hous.release.android.presentation.our_rules.component.main.RuleGuideBottomSheetContent
import hous.release.android.presentation.our_rules.model.DetailRuleUiModel
import hous.release.designsystem.theme.HousTheme
import hous.release.designsystem.theme.HousWhite
Expand Down Expand Up @@ -48,6 +49,8 @@ fun MainRuleScreen(
skipHalfExpanded = true
)
var isShowDeleteRuleDialog by remember { mutableStateOf(false) }
var bottomSheetType: BottomSheetType by remember { mutableStateOf(BottomSheetType.DetailRule) }

val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
Expand Down Expand Up @@ -83,16 +86,21 @@ fun MainRuleScreen(
ModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
DetailRuleBottomSheetContent(
detailRule = detailRule,
onNavigateToUpdateRule = { detailRule ->
coroutineScope.launch {
bottomSheetState.hide()
onNavigateToUpdateRule(detailRule)
}
},
onDeleteRule = { isShowDeleteRuleDialog = true }
)
if (bottomSheetType is BottomSheetType.DetailRule) {
DetailRuleBottomSheetContent(
detailRule = detailRule,
onNavigateToUpdateRule = { detailRule ->
coroutineScope.launch {
bottomSheetState.hide()
onNavigateToUpdateRule(detailRule)
}
},
onDeleteRule = { isShowDeleteRuleDialog = true }
)
}
if (bottomSheetType is BottomSheetType.RuleGuide) {
RuleGuideBottomSheetContent()
}
},
sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp),
sheetElevation = 8.dp,
Expand All @@ -105,6 +113,13 @@ fun MainRuleScreen(
onOpenDetailRule = { id ->
coroutineScope.launch {
fetchDetailRuleById(id)
bottomSheetType = BottomSheetType.DetailRule
bottomSheetState.show()
}
},
onOpenRuleGuide = {
coroutineScope.launch {
bottomSheetType = BottomSheetType.RuleGuide
bottomSheetState.show()
}
},
Expand All @@ -129,3 +144,8 @@ private fun MainRuleScreenPreView2() {
)
}
}

sealed class BottomSheetType {
object DetailRule : BottomSheetType()
object RuleGuide : BottomSheetType()
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavController
import hous.release.android.presentation.practice.PhotoViewModel
import hous.release.designsystem.theme.HousTheme
import kotlinx.coroutines.launch

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
fun ImagePickerScreen(
navController: NavController,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.activity.addCallback
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint
import hous.release.android.R
Expand All @@ -25,7 +24,6 @@ import hous.release.designsystem.theme.HousTheme
class AddToDoActivity : AppCompatActivity() {
private val viewModel by viewModels<AddToDoVIewModel>()

@OptIn(ExperimentalLifecycleComposeApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import androidx.activity.addCallback
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dagger.hilt.android.AndroidEntryPoint
import hous.release.android.R
Expand All @@ -24,7 +23,6 @@ import hous.release.designsystem.theme.HousTheme
class EditToDoActivity : AppCompatActivity() {
private val viewModel by viewModels<EditToDoViewModel>()

@OptIn(ExperimentalLifecycleComposeApi::class)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Expand Down
Loading