From 0ea610278bfc3c75abc438c9fa93707d95100a0b Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Thu, 21 Nov 2024 13:24:18 +0900 Subject: [PATCH 01/31] =?UTF-8?q?feat=20:=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=ED=8F=B4=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/demo/BottomSheetPreview.kt | 14 ++++++++++++++ .../com/yourssu/handy/compose/BottomSheet.kt | 7 +++++++ 2 files changed, 21 insertions(+) create mode 100644 app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt create mode 100644 compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt new file mode 100644 index 00000000..c82a59eb --- /dev/null +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -0,0 +1,14 @@ +package com.yourssu.handy.demo + +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import com.yourssu.handy.compose.BottomSheet +import com.yourssu.handy.compose.HandyTheme + +@Preview(showBackground = true) +@Composable +fun BottomSheetPreview() { + HandyTheme{ + BottomSheet() + } +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt new file mode 100644 index 00000000..bcd1509b --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -0,0 +1,7 @@ +package com.yourssu.handy.compose + +import androidx.compose.runtime.Composable + +@Composable +fun BottomSheet() { +} \ No newline at end of file From d943277cad44ba3117caa01eb0c6e1091f005907 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 14 Jan 2025 03:15:12 +0900 Subject: [PATCH 02/31] feat : bottom sheet UI --- .../com/yourssu/handy/compose/BottomSheet.kt | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index bcd1509b..d54b02d2 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,7 +1,82 @@ package com.yourssu.handy.compose +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape 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.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +enum class BottomSheetSize { + SMALL, MEDIUM, LARGE +} + +@Composable +fun BottomSheet( + modifier: Modifier = Modifier, + onDismiss: () -> Unit, + bottomSheetSize: BottomSheetSize = BottomSheetSize.SMALL, + handleBarVisibility: Boolean = true, + content: @Composable () -> Unit = {} +) { + // todo: Scrim 삭제 + Box( + modifier = modifier + .fillMaxSize() + .background(color = Color(0xFF25262C).copy(alpha = 0.65f)) + .clickable { onDismiss() }, + ) { + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(bottom = 34.dp) + .fillMaxWidth() + // todo: Handy Radius로 바꾸기 + .clip(RoundedCornerShape(24.dp)) + .background(HandyTheme.colors.bgBasicDefault) + .align(Alignment.BottomCenter) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (handleBarVisibility) { + // TODO: Divider 컴포넌트 머지되면 적용하기 + Divider( + modifier = Modifier + .width(32.dp) + .clip(CircleShape), + dividerSize = DividerSize.FOUR, + color = Color(0xFFB5B9C4) + ) + Spacer(modifier = Modifier.height(32.dp)) + } + content() + } + } +} + +@Preview @Composable -fun BottomSheet() { -} \ No newline at end of file +fun TempBottomSheetPreview() { + HandyTheme { + BottomSheet( + handleBarVisibility = true, + onDismiss = {}, + ) { + Text("hi") + } + } +} + From 67dc4259c189f43a1a4f6286fdc047c27f297919 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 18 Jan 2025 04:58:49 +0900 Subject: [PATCH 03/31] =?UTF-8?q?feat=20:=20handle=20bar=20optional?= =?UTF-8?q?=EC=9D=B8=20=EC=83=81=ED=83=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index d54b02d2..49f60e26 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -20,16 +20,15 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -enum class BottomSheetSize { - SMALL, MEDIUM, LARGE +enum class BottomSheetType { + NO_BUTTON, ONE_BUTTON, TWO_BUTTON } @Composable fun BottomSheet( modifier: Modifier = Modifier, onDismiss: () -> Unit, - bottomSheetSize: BottomSheetSize = BottomSheetSize.SMALL, - handleBarVisibility: Boolean = true, + buttonSheetType: BottomSheetType = BottomSheetType.ONE_BUTTON, content: @Composable () -> Unit = {} ) { // todo: Scrim 삭제 @@ -44,24 +43,21 @@ fun BottomSheet( .padding(horizontal = 16.dp) .padding(bottom = 34.dp) .fillMaxWidth() - // todo: Handy Radius로 바꾸기 - .clip(RoundedCornerShape(24.dp)) + .clip(RoundedCornerShape(24.dp)) // todo: Handy Radius로 바꾸기 .background(HandyTheme.colors.bgBasicDefault) .align(Alignment.BottomCenter) .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - if (handleBarVisibility) { - // TODO: Divider 컴포넌트 머지되면 적용하기 - Divider( - modifier = Modifier - .width(32.dp) - .clip(CircleShape), - dividerSize = DividerSize.FOUR, - color = Color(0xFFB5B9C4) - ) - Spacer(modifier = Modifier.height(32.dp)) - } + // TODO: Divider 컴포넌트 머지되면 적용하기 + Divider( + modifier = Modifier + .width(32.dp) + .clip(CircleShape), + dividerSize = DividerSize.FOUR, + color = Color(0xFFB5B9C4) + ) + Spacer(modifier = Modifier.height(32.dp)) content() } } @@ -72,7 +68,6 @@ fun BottomSheet( fun TempBottomSheetPreview() { HandyTheme { BottomSheet( - handleBarVisibility = true, onDismiss = {}, ) { Text("hi") From 9460ec397d371baf5a55d498cc84a4cc2d6601b1 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 18 Jan 2025 05:41:04 +0900 Subject: [PATCH 04/31] =?UTF-8?q?feat=20:=20bottomSheetType=20Sealed=20cla?= =?UTF-8?q?ss=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 66 +++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 49f60e26..0dfbf394 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -19,20 +19,32 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.button.BaseButton +import com.yourssu.handy.compose.button.ButtonColorState -enum class BottomSheetType { - NO_BUTTON, ONE_BUTTON, TWO_BUTTON +sealed class BottomSheetType { + data object NoButton : BottomSheetType() + + data class OneButton( + val buttonText: String + ) : BottomSheetType() + + data class TwoButton( + val primaryButtonText: String, + val secondaryButtonText: String + ) : BottomSheetType() } +// TODO: 주석 작성 @Composable fun BottomSheet( modifier: Modifier = Modifier, onDismiss: () -> Unit, - buttonSheetType: BottomSheetType = BottomSheetType.ONE_BUTTON, + bottomSheetType: BottomSheetType = BottomSheetType.NoButton, content: @Composable () -> Unit = {} ) { - // todo: Scrim 삭제 Box( + // todo: Scrim 삭제 modifier = modifier .fillMaxSize() .background(color = Color(0xFF25262C).copy(alpha = 0.65f)) @@ -59,16 +71,58 @@ fun BottomSheet( ) Spacer(modifier = Modifier.height(32.dp)) content() + + when (bottomSheetType) { + is BottomSheetType.NoButton -> {} + + is BottomSheetType.OneButton -> { + OneButtonBottomSheet(buttonText = bottomSheetType.buttonText) + } + + is BottomSheetType.TwoButton -> { + TwoButtonBottomSheet( + primaryButtonText = bottomSheetType.primaryButtonText, + secondaryButtonText = bottomSheetType.secondaryButtonText + ) + } + } + } } } -@Preview @Composable -fun TempBottomSheetPreview() { +private fun OneButtonBottomSheet( + modifier: Modifier = Modifier, + buttonText: String +) { + BaseButton( // TODO: 고민.. 버튼의 어디까지 열어둬야 하나? + onClick = {}, + colors = ButtonColorState( + bgColor = HandyTheme.colors.buttonBoxPrimaryEnabled + ), + modifier = modifier + ) { + Text(text = buttonText) + } +} + +@Composable +private fun TwoButtonBottomSheet( + primaryButtonText: String, + secondaryButtonText: String, + modifier: Modifier = Modifier +) { + +} + +@Preview // todo : delete preview +@Composable +private fun TempBottomSheetPreview() { HandyTheme { BottomSheet( onDismiss = {}, + bottomSheetType = BottomSheetType.OneButton(buttonText = "TEXT") ) { Text("hi") } From 167ed2a8ece6a20b34a1354495f6df17a385ef27 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 19 Jan 2025 16:07:00 +0900 Subject: [PATCH 05/31] =?UTF-8?q?feat=20:=20TwoButton=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 96 +++++++++++++++---- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 0dfbf394..98e1fec7 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -2,8 +2,10 @@ package com.yourssu.handy.compose 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.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -21,6 +23,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState +import com.yourssu.handy.compose.foundation.HandyTypography +import com.yourssu.handy.compose.foundation.Radius sealed class BottomSheetType { data object NoButton : BottomSheetType() @@ -30,7 +34,7 @@ sealed class BottomSheetType { ) : BottomSheetType() data class TwoButton( - val primaryButtonText: String, + val firstButtonText: String, val secondaryButtonText: String ) : BottomSheetType() } @@ -40,6 +44,9 @@ sealed class BottomSheetType { fun BottomSheet( modifier: Modifier = Modifier, onDismiss: () -> Unit, + onOneButtonClick: () -> Unit = {}, // todo: 한번에 관리하고싶다. + onFirstButtonClick: () -> Unit = {}, + onSecondButtonClick: () -> Unit = {}, bottomSheetType: BottomSheetType = BottomSheetType.NoButton, content: @Composable () -> Unit = {} ) { @@ -55,7 +62,7 @@ fun BottomSheet( .padding(horizontal = 16.dp) .padding(bottom = 34.dp) .fillMaxWidth() - .clip(RoundedCornerShape(24.dp)) // todo: Handy Radius로 바꾸기 + .clip(RoundedCornerShape(24.dp)) .background(HandyTheme.colors.bgBasicDefault) .align(Alignment.BottomCenter) .padding(16.dp), @@ -71,18 +78,24 @@ fun BottomSheet( ) Spacer(modifier = Modifier.height(32.dp)) content() + Spacer(modifier = Modifier.height(16.dp)) when (bottomSheetType) { is BottomSheetType.NoButton -> {} is BottomSheetType.OneButton -> { - OneButtonBottomSheet(buttonText = bottomSheetType.buttonText) + OneButtonBottomSheet( + buttonText = bottomSheetType.buttonText, + onClick = onOneButtonClick + ) } is BottomSheetType.TwoButton -> { TwoButtonBottomSheet( - primaryButtonText = bottomSheetType.primaryButtonText, - secondaryButtonText = bottomSheetType.secondaryButtonText + firstButtonText = bottomSheetType.firstButtonText, + secondaryButtonText = bottomSheetType.secondaryButtonText, + onFirstButtonClick = onFirstButtonClick, + onSecondButtonClick = onSecondButtonClick ) } } @@ -93,38 +106,85 @@ fun BottomSheet( @Composable private fun OneButtonBottomSheet( + buttonText: String, + onClick: () -> Unit, modifier: Modifier = Modifier, - buttonText: String ) { - BaseButton( // TODO: 고민.. 버튼의 어디까지 열어둬야 하나? - onClick = {}, + BaseButton( // todo: 고민.. 버튼의 어디까지 열어둬야 하나? + onClick = onClick, colors = ButtonColorState( bgColor = HandyTheme.colors.buttonBoxPrimaryEnabled ), - modifier = modifier + modifier = modifier.fillMaxWidth(), + rounding = Radius.XL.dp ) { - Text(text = buttonText) + Text( + text = buttonText, + style = HandyTypography.B1Sb16, + color = HandyTheme.colors.textBasicWhite + ) } } @Composable private fun TwoButtonBottomSheet( - primaryButtonText: String, + firstButtonText: String, secondaryButtonText: String, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, + onFirstButtonClick: () -> Unit, + onSecondButtonClick: () -> Unit ) { - + Row( + modifier = Modifier, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + BaseButton( + onClick = onFirstButtonClick, + colors = ButtonColorState(bgColor = HandyTheme.colors.buttonBoxSecondaryEnabled), + modifier = Modifier.weight(1f), + rounding = Radius.XL.dp + ) { + Text( + text = firstButtonText, + style = HandyTypography.B1Sb16, + color = HandyTheme.colors.textBrandSecondary + ) + } + BaseButton( + onClick = onSecondButtonClick, + colors = ButtonColorState(bgColor = HandyTheme.colors.buttonBoxPrimaryEnabled), + modifier = Modifier.weight(1f), + rounding = Radius.XL.dp + ) { + Text( + text = secondaryButtonText, + style = HandyTypography.B1Sb16, + color = HandyTheme.colors.textBasicWhite + ) + } + } } @Preview // todo : delete preview @Composable private fun TempBottomSheetPreview() { HandyTheme { - BottomSheet( - onDismiss = {}, - bottomSheetType = BottomSheetType.OneButton(buttonText = "TEXT") - ) { - Text("hi") + Column { +// BottomSheet( +// onDismiss = {}, +// bottomSheetType = BottomSheetType.OneButton(buttonText = "TEXT") +// ) { +// Text("hi") +// } + BottomSheet( + onDismiss = {}, + bottomSheetType = BottomSheetType.TwoButton( + firstButtonText = "LEFT", + secondaryButtonText = "RIGHT" + ) + ) { + Text("hi") + } } } } From 97b0a9b7311ab28d7cf96b69d2fa0b63dd16dff2 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 19 Jan 2025 16:32:18 +0900 Subject: [PATCH 06/31] =?UTF-8?q?feat=20:=20preview=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/handy/demo/BottomSheetPreview.kt | 43 +++++++++++++++++-- .../com/yourssu/handy/compose/BottomSheet.kt | 31 +------------ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index c82a59eb..fefb2f70 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -3,12 +3,49 @@ package com.yourssu.handy.demo import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview import com.yourssu.handy.compose.BottomSheet +import com.yourssu.handy.compose.BottomSheetType import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.Text @Preview(showBackground = true) @Composable -fun BottomSheetPreview() { - HandyTheme{ - BottomSheet() +fun NoBottomSheetPreview() { + HandyTheme { + BottomSheet( + onDismiss = {} + ) { + Text("no button") + } + } +} + +@Preview(showBackground = true) +@Composable +fun OneBottomSheetPreview() { + HandyTheme { + BottomSheet( + onDismiss = {}, + bottomSheetType = BottomSheetType.OneButton( + buttonText = "TEXT" + ) + ) { + Text("one button") + } + } +} + +@Preview(showBackground = true) +@Composable +fun TwoBottomSheetPreview() { + HandyTheme { + BottomSheet( + onDismiss = {}, + bottomSheetType = BottomSheetType.TwoButton( + firstButtonText = "LEFT", + secondaryButtonText = "RIGHT" + ) + ) { + Text("two button") + } } } \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 98e1fec7..c0aa7858 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -19,7 +19,6 @@ 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.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState @@ -68,8 +67,7 @@ fun BottomSheet( .padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - // TODO: Divider 컴포넌트 머지되면 적용하기 - Divider( + Divider( // TODO: Divider 컴포넌트 머지되면 적용하기 modifier = Modifier .width(32.dp) .clip(CircleShape), @@ -135,7 +133,7 @@ private fun TwoButtonBottomSheet( onSecondButtonClick: () -> Unit ) { Row( - modifier = Modifier, + modifier = modifier, horizontalArrangement = Arrangement.spacedBy(8.dp) ) { BaseButton( @@ -164,28 +162,3 @@ private fun TwoButtonBottomSheet( } } } - -@Preview // todo : delete preview -@Composable -private fun TempBottomSheetPreview() { - HandyTheme { - Column { -// BottomSheet( -// onDismiss = {}, -// bottomSheetType = BottomSheetType.OneButton(buttonText = "TEXT") -// ) { -// Text("hi") -// } - BottomSheet( - onDismiss = {}, - bottomSheetType = BottomSheetType.TwoButton( - firstButtonText = "LEFT", - secondaryButtonText = "RIGHT" - ) - ) { - Text("hi") - } - } - } -} - From e328e10bea1ed1b6462378c5b0d086af137a1261 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 19 Jan 2025 17:28:04 +0900 Subject: [PATCH 07/31] =?UTF-8?q?feat=20:=20BottomSheetDefaults=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/handy/demo/BottomSheetPreview.kt | 6 +- .../com/yourssu/handy/compose/BottomSheet.kt | 138 +++++++++++++----- .../yourssu/handy/compose/BottomSheetData.kt | 52 +++++++ 3 files changed, 154 insertions(+), 42 deletions(-) create mode 100644 compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index fefb2f70..807dc9e2 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -12,7 +12,7 @@ import com.yourssu.handy.compose.Text fun NoBottomSheetPreview() { HandyTheme { BottomSheet( - onDismiss = {} + onDismissRequest = {} ) { Text("no button") } @@ -24,7 +24,7 @@ fun NoBottomSheetPreview() { fun OneBottomSheetPreview() { HandyTheme { BottomSheet( - onDismiss = {}, + onDismissRequest = {}, bottomSheetType = BottomSheetType.OneButton( buttonText = "TEXT" ) @@ -39,7 +39,7 @@ fun OneBottomSheetPreview() { fun TwoBottomSheetPreview() { HandyTheme { BottomSheet( - onDismiss = {}, + onDismissRequest = {}, bottomSheetType = BottomSheetType.TwoButton( firstButtonText = "LEFT", secondaryButtonText = "RIGHT" diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index c0aa7858..58a3b29b 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,7 +1,17 @@ package com.yourssu.handy.compose +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.TweenSpec +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -11,15 +21,19 @@ 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.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember 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.graphics.isSpecified +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography @@ -41,63 +55,76 @@ sealed class BottomSheetType { // TODO: 주석 작성 @Composable fun BottomSheet( + onDismissRequest: () -> Unit, modifier: Modifier = Modifier, - onDismiss: () -> Unit, + dragHandle: @Composable (() -> Unit)? = { DragHandle() }, onOneButtonClick: () -> Unit = {}, // todo: 한번에 관리하고싶다. onFirstButtonClick: () -> Unit = {}, onSecondButtonClick: () -> Unit = {}, bottomSheetType: BottomSheetType = BottomSheetType.NoButton, content: @Composable () -> Unit = {} ) { + val transitionState = remember { MutableTransitionState(false) } + transitionState.targetState = true + + // Scrim() + Box( // todo: Scrim 삭제 modifier = modifier .fillMaxSize() .background(color = Color(0xFF25262C).copy(alpha = 0.65f)) - .clickable { onDismiss() }, + // .clickable { onDismissRequest() }, + .clickable { + transitionState.targetState = false // 애니메이션 종료 + onDismissRequest() + } ) { - Column( - modifier = Modifier - .padding(horizontal = 16.dp) - .padding(bottom = 34.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(24.dp)) - .background(HandyTheme.colors.bgBasicDefault) - .align(Alignment.BottomCenter) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally + AnimatedVisibility( + visibleState = transitionState, + enter = slideInVertically(initialOffsetY = { it }) + fadeIn(), + exit = slideOutVertically(targetOffsetY = { it }) + fadeOut(), + modifier = Modifier.align(Alignment.BottomCenter) ) { - Divider( // TODO: Divider 컴포넌트 머지되면 적용하기 + Column( modifier = Modifier - .width(32.dp) - .clip(CircleShape), - dividerSize = DividerSize.FOUR, - color = Color(0xFFB5B9C4) - ) - Spacer(modifier = Modifier.height(32.dp)) - content() - Spacer(modifier = Modifier.height(16.dp)) + .padding(horizontal = 16.dp) + .padding(bottom = 34.dp) + .fillMaxWidth() + .clip(RoundedCornerShape(24.dp)) + .background(HandyTheme.colors.bgBasicDefault) + // .align(Alignment.BottomCenter) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (dragHandle != null) { + DragHandle() + } + Spacer(modifier = Modifier.height(32.dp)) + content() + Spacer(modifier = Modifier.height(16.dp)) - when (bottomSheetType) { - is BottomSheetType.NoButton -> {} + when (bottomSheetType) { + is BottomSheetType.NoButton -> {} - is BottomSheetType.OneButton -> { - OneButtonBottomSheet( - buttonText = bottomSheetType.buttonText, - onClick = onOneButtonClick - ) - } + is BottomSheetType.OneButton -> { + OneButtonBottomSheet( + buttonText = bottomSheetType.buttonText, + onClick = onOneButtonClick + ) + } - is BottomSheetType.TwoButton -> { - TwoButtonBottomSheet( - firstButtonText = bottomSheetType.firstButtonText, - secondaryButtonText = bottomSheetType.secondaryButtonText, - onFirstButtonClick = onFirstButtonClick, - onSecondButtonClick = onSecondButtonClick - ) + is BottomSheetType.TwoButton -> { + TwoButtonBottomSheet( + firstButtonText = bottomSheetType.firstButtonText, + secondaryButtonText = bottomSheetType.secondaryButtonText, + onFirstButtonClick = onFirstButtonClick, + onSecondButtonClick = onSecondButtonClick + ) + } } - } + } } } } @@ -162,3 +189,36 @@ private fun TwoButtonBottomSheet( } } } + + +@Composable +private fun Scrim( + color: Color, + onDismissRequest: () -> Unit, + visible: Boolean +) { + if (color.isSpecified) { + val alpha by animateFloatAsState( + targetValue = if (visible) 1f else 0f, + animationSpec = TweenSpec() + ) + val dismissSheet = if (visible) { + Modifier + .pointerInput(onDismissRequest) { + detectTapGestures { + onDismissRequest() + } + } + .clearAndSetSemantics {} + } else { + Modifier + } + Canvas( + Modifier + .fillMaxSize() + .then(dismissSheet) + ) { + drawRect(color = color, alpha = alpha) + } + } +} \ No newline at end of file diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt new file mode 100644 index 00000000..69ed9f9d --- /dev/null +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -0,0 +1,52 @@ +package com.yourssu.handy.compose + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +internal object BottomSheetDefaults { + /** + * The default peek height used by [BottomSheetScaffold]. + */ + val SheetPeekHeight = 56.dp + + /** + * The default max width used by [ModalBottomSheet] and [BottomSheetScaffold] + */ + val SheetMaxWidth = 640.dp + + /** + * The optional visual marker placed on top of a bottom sheet to indicate it may be dragged. + */ + @Composable + fun DragHandle( + modifier: Modifier = Modifier, + width: Dp = DockedDragHandleWidth, + height: Dp = DockedDragHandleHeight, + shape: Shape = RoundedCornerShape(28.0.dp), + color: Color = Color(0xFFB5B9C4) + ) { + Surface( + modifier = modifier, + backgroundColor = color, + shape = shape + ) { + Box( + Modifier + .size( + width = width, + height = height + ) + ) + } + } +} + +private val DockedDragHandleWidth = 32.0.dp +private val DockedDragHandleHeight = 4.0.dp From ac17d9846f4d46a3d5e6e7e08bdedcebe540cd4b Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sun, 19 Jan 2025 17:30:22 +0900 Subject: [PATCH 08/31] =?UTF-8?q?feat=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 91 ++++++++----------- 1 file changed, 37 insertions(+), 54 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 58a3b29b..e38b083e 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,13 +1,7 @@ package com.yourssu.handy.compose -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.TweenSpec import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.slideInVertically -import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.Canvas import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -24,7 +18,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -64,9 +58,8 @@ fun BottomSheet( bottomSheetType: BottomSheetType = BottomSheetType.NoButton, content: @Composable () -> Unit = {} ) { - val transitionState = remember { MutableTransitionState(false) } - transitionState.targetState = true + val scope = rememberCoroutineScope() // Scrim() Box( @@ -74,57 +67,47 @@ fun BottomSheet( modifier = modifier .fillMaxSize() .background(color = Color(0xFF25262C).copy(alpha = 0.65f)) - // .clickable { onDismissRequest() }, - .clickable { - transitionState.targetState = false // 애니메이션 종료 - onDismissRequest() - } + .clickable { onDismissRequest() }, ) { - AnimatedVisibility( - visibleState = transitionState, - enter = slideInVertically(initialOffsetY = { it }) + fadeIn(), - exit = slideOutVertically(targetOffsetY = { it }) + fadeOut(), - modifier = Modifier.align(Alignment.BottomCenter) + Column( + modifier = Modifier + .padding(horizontal = 16.dp) + .padding(bottom = 34.dp) + .fillMaxWidth() + .clip(RoundedCornerShape(24.dp)) + .background(HandyTheme.colors.bgBasicDefault) + // .align(Alignment.BottomCenter) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally ) { - Column( - modifier = Modifier - .padding(horizontal = 16.dp) - .padding(bottom = 34.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(24.dp)) - .background(HandyTheme.colors.bgBasicDefault) - // .align(Alignment.BottomCenter) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (dragHandle != null) { - DragHandle() - } - Spacer(modifier = Modifier.height(32.dp)) - content() - Spacer(modifier = Modifier.height(16.dp)) - - when (bottomSheetType) { - is BottomSheetType.NoButton -> {} - - is BottomSheetType.OneButton -> { - OneButtonBottomSheet( - buttonText = bottomSheetType.buttonText, - onClick = onOneButtonClick - ) - } + if (dragHandle != null) { + DragHandle() + } - is BottomSheetType.TwoButton -> { - TwoButtonBottomSheet( - firstButtonText = bottomSheetType.firstButtonText, - secondaryButtonText = bottomSheetType.secondaryButtonText, - onFirstButtonClick = onFirstButtonClick, - onSecondButtonClick = onSecondButtonClick - ) - } + Spacer(modifier = Modifier.height(32.dp)) + content() + Spacer(modifier = Modifier.height(16.dp)) + + when (bottomSheetType) { + is BottomSheetType.NoButton -> {} + + is BottomSheetType.OneButton -> { + OneButtonBottomSheet( + buttonText = bottomSheetType.buttonText, + onClick = onOneButtonClick + ) } + is BottomSheetType.TwoButton -> { + TwoButtonBottomSheet( + firstButtonText = bottomSheetType.firstButtonText, + secondaryButtonText = bottomSheetType.secondaryButtonText, + onFirstButtonClick = onFirstButtonClick, + onSecondButtonClick = onSecondButtonClick + ) + } } + } } } From cf6e4124975c94cbeda83471e3a12ba88b0ca459 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 20 Jan 2025 03:16:45 +0900 Subject: [PATCH 09/31] =?UTF-8?q?feat=20:=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20data=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 197 ++++++++++-------- .../yourssu/handy/compose/BottomSheetData.kt | 152 +++++++++++++- 2 files changed, 257 insertions(+), 92 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index e38b083e..3ab18cb5 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,37 +1,43 @@ package com.yourssu.handy.compose -import androidx.compose.animation.core.TweenSpec -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.Canvas +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.detectTapGestures +import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.foundation.gestures.Orientation +import androidx.compose.foundation.gestures.anchoredDraggable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row 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.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue +import androidx.compose.runtime.SideEffect 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.graphics.isSpecified -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle +import com.yourssu.handy.compose.SheetValue.Expanded +import com.yourssu.handy.compose.SheetValue.Hidden import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography import com.yourssu.handy.compose.foundation.Radius +import kotlinx.coroutines.launch +import kotlin.math.max sealed class BottomSheetType { data object NoButton : BottomSheetType() @@ -47,67 +53,106 @@ sealed class BottomSheetType { } // TODO: 주석 작성 +@OptIn(ExperimentalFoundationApi::class) @Composable fun BottomSheet( onDismissRequest: () -> Unit, modifier: Modifier = Modifier, - dragHandle: @Composable (() -> Unit)? = { DragHandle() }, + sheetState: SheetState = rememberModalBottomSheetState(), onOneButtonClick: () -> Unit = {}, // todo: 한번에 관리하고싶다. onFirstButtonClick: () -> Unit = {}, onSecondButtonClick: () -> Unit = {}, bottomSheetType: BottomSheetType = BottomSheetType.NoButton, content: @Composable () -> Unit = {} ) { - + val density = LocalDensity.current + SideEffect { + sheetState.density = density + } val scope = rememberCoroutineScope() - // Scrim() - - Box( - // todo: Scrim 삭제 - modifier = modifier - .fillMaxSize() - .background(color = Color(0xFF25262C).copy(alpha = 0.65f)) - .clickable { onDismissRequest() }, - ) { - Column( - modifier = Modifier - .padding(horizontal = 16.dp) - .padding(bottom = 34.dp) - .fillMaxWidth() - .clip(RoundedCornerShape(24.dp)) - .background(HandyTheme.colors.bgBasicDefault) - // .align(Alignment.BottomCenter) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - if (dragHandle != null) { - DragHandle() + val animateToDismiss: () -> Unit = { + scope.launch { sheetState.hide() }.invokeOnCompletion { + if (!sheetState.isVisible) { + onDismissRequest() } + } + } - Spacer(modifier = Modifier.height(32.dp)) - content() - Spacer(modifier = Modifier.height(16.dp)) - - when (bottomSheetType) { - is BottomSheetType.NoButton -> {} - - is BottomSheetType.OneButton -> { - OneButtonBottomSheet( - buttonText = bottomSheetType.buttonText, - onClick = onOneButtonClick + Popup( + onDismissRequest = onDismissRequest + ) { + BoxWithConstraints(Modifier.fillMaxSize()) { + val fullHeight = constraints.maxHeight + Scrim( + color = Color(0xFF25262C).copy(alpha = 0.65f), + onDismissRequest = animateToDismiss, + visible = sheetState.currentValue == Expanded + ) + Surface( + modifier = modifier + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(horizontal = 16.dp) + .padding(bottom = 34.dp) + .clip(RoundedCornerShape(24.dp)) + .offset { + IntOffset( + x = 0, + y = sheetState + .requireOffset() + .toInt() + ) + } + .anchoredDraggable( + state = sheetState.anchoredDraggableState, + orientation = Orientation.Vertical, + enabled = true ) - } - - is BottomSheetType.TwoButton -> { - TwoButtonBottomSheet( - firstButtonText = bottomSheetType.firstButtonText, - secondaryButtonText = bottomSheetType.secondaryButtonText, - onFirstButtonClick = onFirstButtonClick, - onSecondButtonClick = onSecondButtonClick + .modalBottomSheetAnchors( + sheetState = sheetState, + fullHeight = fullHeight.toFloat() ) + ) { + Column( + modifier = Modifier + .background(HandyTheme.colors.bgBasicDefault) + .align(Alignment.BottomCenter) + .padding(horizontal = 16.dp) + .padding(bottom = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box( + modifier = Modifier + .align(Alignment.CenterHorizontally) + ) { + DragHandle() + } + Spacer(modifier = Modifier.height(16.dp)) + content() + Spacer(modifier = Modifier.height(16.dp)) + + when (bottomSheetType) { + is BottomSheetType.NoButton -> {} + + is BottomSheetType.OneButton -> { + OneButtonBottomSheet( + buttonText = bottomSheetType.buttonText, + onClick = onOneButtonClick + ) + } + + is BottomSheetType.TwoButton -> { + TwoButtonBottomSheet( + firstButtonText = bottomSheetType.firstButtonText, + secondaryButtonText = bottomSheetType.secondaryButtonText, + onFirstButtonClick = onFirstButtonClick, + onSecondButtonClick = onSecondButtonClick + ) + } + } + } } - } } } @@ -173,35 +218,21 @@ private fun TwoButtonBottomSheet( } } +@OptIn(ExperimentalFoundationApi::class) +private fun Modifier.modalBottomSheetAnchors( + sheetState: SheetState, + fullHeight: Float +) = onSizeChanged { sheetSize -> -@Composable -private fun Scrim( - color: Color, - onDismissRequest: () -> Unit, - visible: Boolean -) { - if (color.isSpecified) { - val alpha by animateFloatAsState( - targetValue = if (visible) 1f else 0f, - animationSpec = TweenSpec() - ) - val dismissSheet = if (visible) { - Modifier - .pointerInput(onDismissRequest) { - detectTapGestures { - onDismissRequest() - } - } - .clearAndSetSemantics {} - } else { - Modifier - } - Canvas( - Modifier - .fillMaxSize() - .then(dismissSheet) - ) { - drawRect(color = color, alpha = alpha) - } + val newAnchors = DraggableAnchors { + Hidden at fullHeight + Expanded at max(0f, fullHeight - sheetSize.height) } -} \ No newline at end of file + + val newTarget = when (sheetState.anchoredDraggableState.targetValue) { + Hidden -> Hidden + Expanded -> Expanded + } + + sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) +} diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 69ed9f9d..7ba46004 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -1,28 +1,128 @@ package com.yourssu.handy.compose +import androidx.compose.animation.core.SpringSpec +import androidx.compose.animation.core.TweenSpec +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.animateTo +import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.saveable.Saver +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.isSpecified +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.semantics.clearAndSetSemantics +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -internal object BottomSheetDefaults { +enum class SheetValue { /** - * The default peek height used by [BottomSheetScaffold]. + * The sheet is not visible. */ - val SheetPeekHeight = 56.dp + Hidden, /** - * The default max width used by [ModalBottomSheet] and [BottomSheetScaffold] + * The sheet is visible at its current position. */ - val SheetMaxWidth = 640.dp + Expanded, +} + +@Composable +fun rememberModalBottomSheetState( + initialValue: SheetValue = SheetValue.Expanded +) = rememberSheetState(initialValue) + +@Composable +internal fun rememberSheetState( + initialValue: SheetValue = SheetValue.Expanded, +): SheetState { + val density = LocalDensity.current + return rememberSaveable( + saver = SheetState.Saver(density = density) + ) { + SheetState(density, initialValue) + } +} + +@Stable +@OptIn(ExperimentalFoundationApi::class) +class SheetState( + density: Density, + initialValue: SheetValue = SheetValue.Expanded, +) { + var currentValue: SheetValue = initialValue + private set + + val isVisible: Boolean // todo: 이거 필요가 없나? + get() = currentValue != SheetValue.Hidden + + fun requireOffset(): Float = anchoredDraggableState.requireOffset() + + suspend fun show() { + animateTo(SheetValue.Expanded) + } + + suspend fun hide() { + animateTo(SheetValue.Hidden) + } + + private suspend fun animateTo( + targetValue: SheetValue, + velocity: Float = anchoredDraggableState.lastVelocity + ) { + anchoredDraggableState.animateTo(targetValue, velocity) + } + + internal suspend fun settle(velocity: Float) { + anchoredDraggableState.settle(velocity) + } + + internal var anchoredDraggableState = AnchoredDraggableState( + initialValue = initialValue, + animationSpec = SpringSpec(), + positionalThreshold = { with(requireDensity()) { 56.dp.toPx() } }, + velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } } + ) + + internal var density: Density? = null + private fun requireDensity() = requireNotNull(density) { + "SheetState did not have a density attached. Are you using SheetState with " + + "BottomSheetScaffold or ModalBottomSheet component?" + } + + companion object { + /** + * The default [Saver] implementation for [SheetState]. + */ + fun Saver( + density: Density + ) = Saver( + save = { it.currentValue }, + restore = { savedValue -> + SheetState(density, savedValue) + } + ) + + } +} +internal object BottomSheetDefaults { /** - * The optional visual marker placed on top of a bottom sheet to indicate it may be dragged. + * The visual marker placed on top of a bottom sheet to indicate it may be dragged. */ @Composable fun DragHandle( @@ -33,7 +133,8 @@ internal object BottomSheetDefaults { color: Color = Color(0xFFB5B9C4) ) { Surface( - modifier = modifier, + modifier = modifier + .padding(vertical = DragHandleVerticalPadding), backgroundColor = color, shape = shape ) { @@ -46,7 +147,40 @@ internal object BottomSheetDefaults { ) } } + + private val DockedDragHandleWidth = 32.0.dp + private val DockedDragHandleHeight = 4.0.dp + private val DragHandleVerticalPadding = 16.dp } -private val DockedDragHandleWidth = 32.0.dp -private val DockedDragHandleHeight = 4.0.dp +@Composable +internal fun Scrim( + color: Color, + onDismissRequest: () -> Unit, + visible: Boolean +) { + if (color.isSpecified) { + val alpha by animateFloatAsState( + targetValue = if (visible) 1f else 0f, + animationSpec = TweenSpec(), label = "" + ) + val dismissSheet = if (visible) { + Modifier + .pointerInput(onDismissRequest) { + detectTapGestures { + onDismissRequest() + } + } + .clearAndSetSemantics {} + } else { + Modifier + } + Canvas( + Modifier + .fillMaxSize() + .then(dismissSheet) + ) { + drawRect(color = color, alpha = alpha) + } + } +} \ No newline at end of file From 0d6f84eb1b55219c97f72da1480a22110b266c3c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 20 Jan 2025 09:43:15 +0900 Subject: [PATCH 10/31] =?UTF-8?q?feat=20:=20=EB=93=9C=EB=9E=98=EA=B7=B8?= =?UTF-8?q?=EB=A1=9C=20=EC=82=AC=EB=9D=BC=EC=A7=80=EB=8A=94=20=EC=95=A0?= =?UTF-8?q?=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 30 ++---------- .../yourssu/handy/compose/BottomSheetData.kt | 47 +++++++++++++------ 2 files changed, 37 insertions(+), 40 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 3ab18cb5..35b55865 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -2,7 +2,6 @@ package com.yourssu.handy.compose import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.DraggableAnchors import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.anchoredDraggable import androidx.compose.foundation.layout.Arrangement @@ -24,20 +23,17 @@ 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.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle -import com.yourssu.handy.compose.SheetValue.Expanded import com.yourssu.handy.compose.SheetValue.Hidden import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography import com.yourssu.handy.compose.foundation.Radius import kotlinx.coroutines.launch -import kotlin.math.max sealed class BottomSheetType { data object NoButton : BottomSheetType() @@ -79,14 +75,16 @@ fun BottomSheet( } Popup( - onDismissRequest = onDismissRequest + onDismissRequest = { + scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() } + } ) { BoxWithConstraints(Modifier.fillMaxSize()) { val fullHeight = constraints.maxHeight Scrim( color = Color(0xFF25262C).copy(alpha = 0.65f), onDismissRequest = animateToDismiss, - visible = sheetState.currentValue == Expanded + visible = sheetState.currentValue != Hidden ) Surface( modifier = modifier @@ -106,7 +104,6 @@ fun BottomSheet( .anchoredDraggable( state = sheetState.anchoredDraggableState, orientation = Orientation.Vertical, - enabled = true ) .modalBottomSheetAnchors( sheetState = sheetState, @@ -217,22 +214,3 @@ private fun TwoButtonBottomSheet( } } } - -@OptIn(ExperimentalFoundationApi::class) -private fun Modifier.modalBottomSheetAnchors( - sheetState: SheetState, - fullHeight: Float -) = onSizeChanged { sheetSize -> - - val newAnchors = DraggableAnchors { - Hidden at fullHeight - Expanded at max(0f, fullHeight - sheetSize.height) - } - - val newTarget = when (sheetState.anchoredDraggableState.targetValue) { - Hidden -> Hidden - Expanded -> Expanded - } - - sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) -} diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 7ba46004..6786959e 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -6,6 +6,7 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.Canvas import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.AnchoredDraggableState +import androidx.compose.foundation.gestures.DraggableAnchors import androidx.compose.foundation.gestures.animateTo import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box @@ -23,11 +24,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.yourssu.handy.compose.SheetValue.Expanded +import com.yourssu.handy.compose.SheetValue.Hidden enum class SheetValue { /** @@ -43,12 +47,12 @@ enum class SheetValue { @Composable fun rememberModalBottomSheetState( - initialValue: SheetValue = SheetValue.Expanded + initialValue: SheetValue = Hidden ) = rememberSheetState(initialValue) @Composable internal fun rememberSheetState( - initialValue: SheetValue = SheetValue.Expanded, + initialValue: SheetValue = Hidden, ): SheetState { val density = LocalDensity.current return rememberSaveable( @@ -61,23 +65,23 @@ internal fun rememberSheetState( @Stable @OptIn(ExperimentalFoundationApi::class) class SheetState( - density: Density, - initialValue: SheetValue = SheetValue.Expanded, + internal var density: Density, + initialValue: SheetValue = Hidden, ) { var currentValue: SheetValue = initialValue private set val isVisible: Boolean // todo: 이거 필요가 없나? - get() = currentValue != SheetValue.Hidden + get() = currentValue != Hidden - fun requireOffset(): Float = anchoredDraggableState.requireOffset() + fun requireOffset() = anchoredDraggableState.requireOffset() suspend fun show() { - animateTo(SheetValue.Expanded) + animateTo(Expanded) } suspend fun hide() { - animateTo(SheetValue.Hidden) + animateTo(Hidden) } private suspend fun animateTo( @@ -95,14 +99,10 @@ class SheetState( initialValue = initialValue, animationSpec = SpringSpec(), positionalThreshold = { with(requireDensity()) { 56.dp.toPx() } }, - velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } } + velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } }, ) - internal var density: Density? = null - private fun requireDensity() = requireNotNull(density) { - "SheetState did not have a density attached. Are you using SheetState with " + - "BottomSheetScaffold or ModalBottomSheet component?" - } + private fun requireDensity() = density companion object { /** @@ -153,6 +153,25 @@ internal object BottomSheetDefaults { private val DragHandleVerticalPadding = 16.dp } +@OptIn(ExperimentalFoundationApi::class) +internal fun Modifier.modalBottomSheetAnchors( + sheetState: SheetState, + fullHeight: Float +) = onSizeChanged { sheetSize -> + + val newAnchors = DraggableAnchors { + Hidden at 0f + Expanded at fullHeight - sheetSize.height + } + + val newTarget = when (sheetState.anchoredDraggableState.targetValue) { + Hidden -> Hidden + Expanded -> Expanded + } + + sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) +} + @Composable internal fun Scrim( color: Color, From 40a9c28fcc615242e9f33ecd53a1e6807351120e Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 20 Jan 2025 11:43:10 +0900 Subject: [PATCH 11/31] =?UTF-8?q?feat=20:=20sheet.show=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/yourssu/handy/compose/BottomSheet.kt | 8 ++++++++ .../com/yourssu/handy/compose/BottomSheetData.kt | 11 +++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 35b55865..d6ee065c 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,5 +1,6 @@ package com.yourssu.handy.compose +import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation @@ -17,6 +18,7 @@ import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.SideEffect import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -152,6 +154,12 @@ fun BottomSheet( } } } + if (sheetState.hasExpandedState) { + LaunchedEffect(sheetState) { + sheetState.show() + } + } +// Log.d("LYB", "sheet = ${sheetState.currentValue}") } @Composable diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 6786959e..e2e410ad 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -35,12 +35,12 @@ import com.yourssu.handy.compose.SheetValue.Hidden enum class SheetValue { /** - * The sheet is not visible. + * Sheet가 보이지 않는 상태 */ Hidden, /** - * The sheet is visible at its current position. + * Sheet가 현재 위치에서 보이는 상태 */ Expanded, } @@ -71,11 +71,14 @@ class SheetState( var currentValue: SheetValue = initialValue private set - val isVisible: Boolean // todo: 이거 필요가 없나? + val isVisible: Boolean get() = currentValue != Hidden fun requireOffset() = anchoredDraggableState.requireOffset() + val hasExpandedState: Boolean + get() = anchoredDraggableState.anchors.hasAnchorFor(Expanded) + suspend fun show() { animateTo(Expanded) } @@ -122,7 +125,7 @@ class SheetState( internal object BottomSheetDefaults { /** - * The visual marker placed on top of a bottom sheet to indicate it may be dragged. + * Sheet 위에 놓인 시각적 마커를 드래그하여 표시할 수 있다. */ @Composable fun DragHandle( From b625eb004847daceed7c7accea84b3d91ce99a15 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 20 Jan 2025 21:54:38 +0900 Subject: [PATCH 12/31] =?UTF-8?q?feat=20:=20conflict=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index d6ee065c..ab9952ce 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,6 +1,5 @@ package com.yourssu.handy.compose -import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation @@ -171,7 +170,7 @@ private fun OneButtonBottomSheet( BaseButton( // todo: 고민.. 버튼의 어디까지 열어둬야 하나? onClick = onClick, colors = ButtonColorState( - bgColor = HandyTheme.colors.buttonBoxPrimaryEnabled + bgColor = HandyTheme.colors.buttonFilledPrimaryEnabled ), modifier = modifier.fillMaxWidth(), rounding = Radius.XL.dp @@ -198,7 +197,7 @@ private fun TwoButtonBottomSheet( ) { BaseButton( onClick = onFirstButtonClick, - colors = ButtonColorState(bgColor = HandyTheme.colors.buttonBoxSecondaryEnabled), + colors = ButtonColorState(bgColor = HandyTheme.colors.buttonFilledSecondaryEnabled), modifier = Modifier.weight(1f), rounding = Radius.XL.dp ) { @@ -210,7 +209,7 @@ private fun TwoButtonBottomSheet( } BaseButton( onClick = onSecondButtonClick, - colors = ButtonColorState(bgColor = HandyTheme.colors.buttonBoxPrimaryEnabled), + colors = ButtonColorState(bgColor = HandyTheme.colors.buttonFilledPrimaryEnabled), modifier = Modifier.weight(1f), rounding = Radius.XL.dp ) { From 3212d94f14e15fcc19852a0315268352c5a44636 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Mon, 20 Jan 2025 22:32:57 +0900 Subject: [PATCH 13/31] =?UTF-8?q?feat=20:=20currentValue=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 1 - .../com/yourssu/handy/compose/BottomSheetData.kt | 14 ++++---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index ab9952ce..ab7f2a14 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -158,7 +158,6 @@ fun BottomSheet( sheetState.show() } } -// Log.d("LYB", "sheet = ${sheetState.currentValue}") } @Composable diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index e2e410ad..b4c070f7 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.Canvas import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.AnchoredDraggableState import androidx.compose.foundation.gestures.DraggableAnchors -import androidx.compose.foundation.gestures.animateTo import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -79,23 +78,18 @@ class SheetState( val hasExpandedState: Boolean get() = anchoredDraggableState.anchors.hasAnchorFor(Expanded) - suspend fun show() { + fun show() { animateTo(Expanded) } - suspend fun hide() { + fun hide() { animateTo(Hidden) } - private suspend fun animateTo( + private fun animateTo( targetValue: SheetValue, - velocity: Float = anchoredDraggableState.lastVelocity ) { - anchoredDraggableState.animateTo(targetValue, velocity) - } - - internal suspend fun settle(velocity: Float) { - anchoredDraggableState.settle(velocity) + currentValue = targetValue } internal var anchoredDraggableState = AnchoredDraggableState( From 364668f4e33c48f611c76103ebd658366ce6dd82 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 10:30:43 +0900 Subject: [PATCH 14/31] =?UTF-8?q?feat=20:=20show,=20hide=20=EC=95=A0?= =?UTF-8?q?=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 15 ++++++------ .../yourssu/handy/compose/BottomSheetData.kt | 23 +++++++++++-------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index ab7f2a14..9bbd1edc 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,11 +1,11 @@ package com.yourssu.handy.compose +import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.anchoredDraggable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -119,12 +119,7 @@ fun BottomSheet( .padding(bottom = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - Box( - modifier = Modifier - .align(Alignment.CenterHorizontally) - ) { - DragHandle() - } + DragHandle() // todo: box Spacer(modifier = Modifier.height(16.dp)) content() Spacer(modifier = Modifier.height(16.dp)) @@ -155,9 +150,12 @@ fun BottomSheet( } if (sheetState.hasExpandedState) { LaunchedEffect(sheetState) { - sheetState.show() + if (sheetState.currentValue != SheetValue.Expanded) { + sheetState.show() + } } } + Log.d("LYB", "sheet = ${sheetState.currentValue}") } @Composable @@ -220,3 +218,4 @@ private fun TwoButtonBottomSheet( } } } + diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index b4c070f7..c6e53aff 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.Canvas import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.gestures.AnchoredDraggableState import androidx.compose.foundation.gestures.DraggableAnchors +import androidx.compose.foundation.gestures.animateTo import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -78,20 +79,14 @@ class SheetState( val hasExpandedState: Boolean get() = anchoredDraggableState.anchors.hasAnchorFor(Expanded) - fun show() { + suspend fun show() { animateTo(Expanded) } - fun hide() { + suspend fun hide() { animateTo(Hidden) } - private fun animateTo( - targetValue: SheetValue, - ) { - currentValue = targetValue - } - internal var anchoredDraggableState = AnchoredDraggableState( initialValue = initialValue, animationSpec = SpringSpec(), @@ -99,6 +94,14 @@ class SheetState( velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } }, ) + private suspend fun animateTo( + targetValue: SheetValue, + velocity: Float = anchoredDraggableState.lastVelocity + ) { + currentValue = targetValue + anchoredDraggableState.animateTo(targetValue, velocity) + } + private fun requireDensity() = density companion object { @@ -157,8 +160,8 @@ internal fun Modifier.modalBottomSheetAnchors( ) = onSizeChanged { sheetSize -> val newAnchors = DraggableAnchors { - Hidden at 0f - Expanded at fullHeight - sheetSize.height + Hidden at fullHeight - sheetSize.height + Expanded at 0f } val newTarget = when (sheetState.anchoredDraggableState.targetValue) { From f802d48e2960ccf34dca335a8ee5ad2a174945d3 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 10:33:33 +0900 Subject: [PATCH 15/31] =?UTF-8?q?feat=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 9bbd1edc..9f35f162 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -29,7 +29,6 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle -import com.yourssu.handy.compose.SheetValue.Hidden import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography @@ -85,7 +84,7 @@ fun BottomSheet( Scrim( color = Color(0xFF25262C).copy(alpha = 0.65f), onDismissRequest = animateToDismiss, - visible = sheetState.currentValue != Hidden + visible = sheetState.isVisible ) Surface( modifier = modifier @@ -150,9 +149,7 @@ fun BottomSheet( } if (sheetState.hasExpandedState) { LaunchedEffect(sheetState) { - if (sheetState.currentValue != SheetValue.Expanded) { - sheetState.show() - } + sheetState.show() } } Log.d("LYB", "sheet = ${sheetState.currentValue}") From 4c2cef617571e56adc9893804f2b0519dcf2784f Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 14:02:30 +0900 Subject: [PATCH 16/31] =?UTF-8?q?feat=20:=20currentValue=20=EA=B0=92=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/yourssu/handy/compose/BottomSheet.kt | 2 +- .../com/yourssu/handy/compose/BottomSheetData.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 9f35f162..213ee2b2 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -110,6 +110,7 @@ fun BottomSheet( fullHeight = fullHeight.toFloat() ) ) { + Log.d("LYB", "sheet POPUP = ${sheetState.currentValue}") Column( modifier = Modifier .background(HandyTheme.colors.bgBasicDefault) @@ -152,7 +153,6 @@ fun BottomSheet( sheetState.show() } } - Log.d("LYB", "sheet = ${sheetState.currentValue}") } @Composable diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index c6e53aff..9358f1c6 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -1,5 +1,6 @@ package com.yourssu.handy.compose +import android.util.Log import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.TweenSpec import androidx.compose.animation.core.animateFloatAsState @@ -68,8 +69,7 @@ class SheetState( internal var density: Density, initialValue: SheetValue = Hidden, ) { - var currentValue: SheetValue = initialValue - private set + val currentValue: SheetValue get() = anchoredDraggableState.currentValue val isVisible: Boolean get() = currentValue != Hidden @@ -98,7 +98,7 @@ class SheetState( targetValue: SheetValue, velocity: Float = anchoredDraggableState.lastVelocity ) { - currentValue = targetValue + //anchoredDraggableState.currentValue = targetValue anchoredDraggableState.animateTo(targetValue, velocity) } @@ -122,7 +122,7 @@ class SheetState( internal object BottomSheetDefaults { /** - * Sheet 위에 놓인 시각적 마커를 드래그하여 표시할 수 있다. + * Sheet 상단에 놓인 시각적 마커를 나타내며 드래그할 수 있습니다. */ @Composable fun DragHandle( @@ -168,7 +168,7 @@ internal fun Modifier.modalBottomSheetAnchors( Hidden -> Hidden Expanded -> Expanded } - + Log.d("LYB", "newAnchors = ${newAnchors}, newTarget = $newTarget") sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) } From d1f347086e0e06ca1879fc82b4c1c1cac5a86c01 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 14:14:31 +0900 Subject: [PATCH 17/31] =?UTF-8?q?feat=20:=20targetValue=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EB=B0=B0=EA=B2=BD=20=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 3 ++- .../main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 213ee2b2..8b337b18 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -29,6 +29,7 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle +import com.yourssu.handy.compose.SheetValue.Hidden import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography @@ -84,7 +85,7 @@ fun BottomSheet( Scrim( color = Color(0xFF25262C).copy(alpha = 0.65f), onDismissRequest = animateToDismiss, - visible = sheetState.isVisible + visible = sheetState.targetValue != Hidden ) Surface( modifier = modifier diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 9358f1c6..0ba453e0 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -71,6 +71,8 @@ class SheetState( ) { val currentValue: SheetValue get() = anchoredDraggableState.currentValue + val targetValue: SheetValue get() = anchoredDraggableState.targetValue + val isVisible: Boolean get() = currentValue != Hidden @@ -98,7 +100,6 @@ class SheetState( targetValue: SheetValue, velocity: Float = anchoredDraggableState.lastVelocity ) { - //anchoredDraggableState.currentValue = targetValue anchoredDraggableState.animateTo(targetValue, velocity) } From f082ef8eba448fc18828cb6dd4e6bc4937842e03 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 14:38:06 +0900 Subject: [PATCH 18/31] =?UTF-8?q?feat=20:=20=EB=93=9C=EB=9E=98=EA=B7=B8=20?= =?UTF-8?q?=ED=9B=84=20onDismissRequest=20=EC=9A=94=EC=B2=AD=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 20 ++++++++++++++----- .../yourssu/handy/compose/BottomSheetData.kt | 3 +-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 8b337b18..24fb328f 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -1,6 +1,5 @@ package com.yourssu.handy.compose -import android.util.Log import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation @@ -20,6 +19,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.SideEffect import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -34,6 +34,9 @@ import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState import com.yourssu.handy.compose.foundation.HandyTypography import com.yourssu.handy.compose.foundation.Radius +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch sealed class BottomSheetType { @@ -69,12 +72,20 @@ fun BottomSheet( val scope = rememberCoroutineScope() val animateToDismiss: () -> Unit = { scope.launch { sheetState.hide() }.invokeOnCompletion { - if (!sheetState.isVisible) { - onDismissRequest() - } + if (!sheetState.isVisible) onDismissRequest() } } + LaunchedEffect(sheetState) { + snapshotFlow { sheetState.currentValue } + .drop(1) // 처음 바텀시트를 연 이후 동작을 감지하기 위한 첫 상태 방출 무시 + .distinctUntilChanged() + .filter { it == Hidden } + .collect { + scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() } + } + } + Popup( onDismissRequest = { scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() } @@ -111,7 +122,6 @@ fun BottomSheet( fullHeight = fullHeight.toFloat() ) ) { - Log.d("LYB", "sheet POPUP = ${sheetState.currentValue}") Column( modifier = Modifier .background(HandyTheme.colors.bgBasicDefault) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 0ba453e0..351a2761 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -1,6 +1,5 @@ package com.yourssu.handy.compose -import android.util.Log import androidx.compose.animation.core.SpringSpec import androidx.compose.animation.core.TweenSpec import androidx.compose.animation.core.animateFloatAsState @@ -169,7 +168,7 @@ internal fun Modifier.modalBottomSheetAnchors( Hidden -> Hidden Expanded -> Expanded } - Log.d("LYB", "newAnchors = ${newAnchors}, newTarget = $newTarget") + sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) } From b2f71ed257fece82b6fb229457655e3aaa170b26 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 14:53:22 +0900 Subject: [PATCH 19/31] =?UTF-8?q?feat=20:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 24fb328f..a39f8664 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -86,11 +86,7 @@ fun BottomSheet( } } - Popup( - onDismissRequest = { - scope.launch { sheetState.hide() }.invokeOnCompletion { onDismissRequest() } - } - ) { + Popup { BoxWithConstraints(Modifier.fillMaxSize()) { val fullHeight = constraints.maxHeight Scrim( From 6545c06a25b42363a7acc6248aa037b4102c9e02 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 15:07:00 +0900 Subject: [PATCH 20/31] =?UTF-8?q?feat=20:=20surface=EC=97=90=20shape=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index a39f8664..493d5aaa 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshotFlow 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.platform.LocalDensity import androidx.compose.ui.unit.IntOffset @@ -52,7 +51,6 @@ sealed class BottomSheetType { ) : BottomSheetType() } -// TODO: 주석 작성 @OptIn(ExperimentalFoundationApi::class) @Composable fun BottomSheet( @@ -100,7 +98,6 @@ fun BottomSheet( .align(Alignment.BottomCenter) .padding(horizontal = 16.dp) .padding(bottom = 34.dp) - .clip(RoundedCornerShape(24.dp)) .offset { IntOffset( x = 0, @@ -116,7 +113,8 @@ fun BottomSheet( .modalBottomSheetAnchors( sheetState = sheetState, fullHeight = fullHeight.toFloat() - ) + ), + shape = RoundedCornerShape(24.dp) ) { Column( modifier = Modifier From 19748acb5edbafdb190e13b680c444cc3eb365b9 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 17:49:29 +0900 Subject: [PATCH 21/31] =?UTF-8?q?feat=20:=20=EC=A3=BC=EC=84=9D=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20Color=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 82 +++++++++++++------ .../yourssu/handy/compose/BottomSheetData.kt | 51 ++++++++---- .../compose/foundation/PrimitiveColors.kt | 7 +- 3 files changed, 98 insertions(+), 42 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 493d5aaa..b225b079 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -22,15 +22,19 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle +import com.yourssu.handy.compose.BottomSheetDefaults.bottomSheetContentPadding +import com.yourssu.handy.compose.BottomSheetType.NoButton +import com.yourssu.handy.compose.BottomSheetType.OneButton +import com.yourssu.handy.compose.BottomSheetType.TwoButton import com.yourssu.handy.compose.SheetValue.Hidden import com.yourssu.handy.compose.button.BaseButton import com.yourssu.handy.compose.button.ButtonColorState +import com.yourssu.handy.compose.foundation.ColorGray080 import com.yourssu.handy.compose.foundation.HandyTypography import com.yourssu.handy.compose.foundation.Radius import kotlinx.coroutines.flow.distinctUntilChanged @@ -38,6 +42,13 @@ import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch +/** + * BottomSheet의 타입을 나타냈습니다. + * + * [NoButton] : 버튼 없이 내용만 표시 + * [OneButton] : 하단에 버튼 한 개를 표시 + * [TwoButton] : 하단에 버튼 두 개를 표시 + */ sealed class BottomSheetType { data object NoButton : BottomSheetType() @@ -47,20 +58,32 @@ sealed class BottomSheetType { data class TwoButton( val firstButtonText: String, - val secondaryButtonText: String + val secondButtonText: String ) : BottomSheetType() } +/** + * 바텀시트의 UI를 나타내는 함수입니다. + * + * @param onDismissRequest 바텀시트가 닫힐 때 호출되는 함수 + * @param modifier Modifier 수정자 + * @param sheetState 바텀시트의 상태를 나타내는 객체 + * @param onOneButtonClick [BottomSheetType.OneButton]의 버튼 클릭 시 호출되는 함수 + * @param onFirstButtonClick [BottomSheetType.TwoButton]의 첫 번째 버튼 클릭 시 호출되는 함수 + * @param onSecondButtonClick [BottomSheetType.TwoButton]의 두 번째 버튼 클릭 시 호출되는 함수 + * @param bottomSheetType 바텀시트의 레이아웃 타입을 결정 + * @param content 바텀시트 내부에 표시될 내용을 결정 + */ @OptIn(ExperimentalFoundationApi::class) @Composable fun BottomSheet( onDismissRequest: () -> Unit, modifier: Modifier = Modifier, sheetState: SheetState = rememberModalBottomSheetState(), - onOneButtonClick: () -> Unit = {}, // todo: 한번에 관리하고싶다. + onOneButtonClick: () -> Unit = {}, onFirstButtonClick: () -> Unit = {}, onSecondButtonClick: () -> Unit = {}, - bottomSheetType: BottomSheetType = BottomSheetType.NoButton, + bottomSheetType: BottomSheetType = NoButton, content: @Composable () -> Unit = {} ) { val density = LocalDensity.current @@ -76,7 +99,7 @@ fun BottomSheet( LaunchedEffect(sheetState) { snapshotFlow { sheetState.currentValue } - .drop(1) // 처음 바텀시트를 연 이후 동작을 감지하기 위한 첫 상태 방출 무시 + .drop(1) .distinctUntilChanged() .filter { it == Hidden } .collect { @@ -88,7 +111,7 @@ fun BottomSheet( BoxWithConstraints(Modifier.fillMaxSize()) { val fullHeight = constraints.maxHeight Scrim( - color = Color(0xFF25262C).copy(alpha = 0.65f), + color = ColorGray080, onDismissRequest = animateToDismiss, visible = sheetState.targetValue != Hidden ) @@ -120,29 +143,29 @@ fun BottomSheet( modifier = Modifier .background(HandyTheme.colors.bgBasicDefault) .align(Alignment.BottomCenter) - .padding(horizontal = 16.dp) - .padding(bottom = 16.dp), + .padding(horizontal = bottomSheetContentPadding) + .padding(bottom = bottomSheetContentPadding), horizontalAlignment = Alignment.CenterHorizontally ) { - DragHandle() // todo: box - Spacer(modifier = Modifier.height(16.dp)) + DragHandle() + Spacer(modifier = Modifier.height(bottomSheetContentPadding)) content() - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.height(bottomSheetContentPadding)) when (bottomSheetType) { - is BottomSheetType.NoButton -> {} + is NoButton -> {} - is BottomSheetType.OneButton -> { + is OneButton -> { OneButtonBottomSheet( buttonText = bottomSheetType.buttonText, onClick = onOneButtonClick ) } - is BottomSheetType.TwoButton -> { + is TwoButton -> { TwoButtonBottomSheet( firstButtonText = bottomSheetType.firstButtonText, - secondaryButtonText = bottomSheetType.secondaryButtonText, + secondButtonText = bottomSheetType.secondButtonText, onFirstButtonClick = onFirstButtonClick, onSecondButtonClick = onSecondButtonClick ) @@ -160,17 +183,22 @@ fun BottomSheet( } } +/** + * 하단에 버튼이 하나만 표시될 때 사용하는 함수입니다. + * + * @param buttonText 버튼에 표시될 텍스트 + * @param onClick 버튼 클릭 시 호출되는 함수 + * @param modifier Modifier + */ @Composable private fun OneButtonBottomSheet( buttonText: String, onClick: () -> Unit, modifier: Modifier = Modifier, ) { - BaseButton( // todo: 고민.. 버튼의 어디까지 열어둬야 하나? + BaseButton( onClick = onClick, - colors = ButtonColorState( - bgColor = HandyTheme.colors.buttonFilledPrimaryEnabled - ), + colors = ButtonColorState(bgColor = HandyTheme.colors.buttonFilledPrimaryEnabled), modifier = modifier.fillMaxWidth(), rounding = Radius.XL.dp ) { @@ -182,13 +210,21 @@ private fun OneButtonBottomSheet( } } +/** + * 하단에 버튼이 두 개일 때 표시될 때 사용하는 함수입니다. + * + * @param firstButtonText 첫 번째 버튼에 표시될 텍스트 + * @param secondButtonText 두 번째 버튼에 표시될 텍스트 + * @param onFirstButtonClick 첫 번째 버튼 클릭 시 호출되는 함수 + * @param onSecondButtonClick 두 번째 버튼 클릭 시 호출되는 함수 + */ @Composable private fun TwoButtonBottomSheet( firstButtonText: String, - secondaryButtonText: String, - modifier: Modifier = Modifier, + secondButtonText: String, onFirstButtonClick: () -> Unit, - onSecondButtonClick: () -> Unit + onSecondButtonClick: () -> Unit, + modifier: Modifier = Modifier, ) { Row( modifier = modifier, @@ -213,7 +249,7 @@ private fun TwoButtonBottomSheet( rounding = Radius.XL.dp ) { Text( - text = secondaryButtonText, + text = secondButtonText, style = HandyTypography.B1Sb16, color = HandyTheme.colors.textBasicWhite ) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 351a2761..41cd5d0a 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -33,15 +33,14 @@ import androidx.compose.ui.unit.dp import com.yourssu.handy.compose.SheetValue.Expanded import com.yourssu.handy.compose.SheetValue.Hidden +/** + * 바텀시트의 상태를 정의하는 Enum 클래스입니다. + * + * [Hidden]: 바텀시트가 보이지 않는 상태. + * [Expanded]: 바텀시트가 보이는 상태. + */ enum class SheetValue { - /** - * Sheet가 보이지 않는 상태 - */ Hidden, - - /** - * Sheet가 현재 위치에서 보이는 상태 - */ Expanded, } @@ -62,6 +61,12 @@ internal fun rememberSheetState( } } +/** + * 바텀시트 상태를 관리하는 클래스입니다. + * + * @property density 화면 밀도 + * @param initialValue 초기 바텀시트 상태 + */ @Stable @OptIn(ExperimentalFoundationApi::class) class SheetState( @@ -73,9 +78,9 @@ class SheetState( val targetValue: SheetValue get() = anchoredDraggableState.targetValue val isVisible: Boolean - get() = currentValue != Hidden + get() = anchoredDraggableState.currentValue != Hidden - fun requireOffset() = anchoredDraggableState.requireOffset() + fun requireOffset(): Float = anchoredDraggableState.requireOffset() val hasExpandedState: Boolean get() = anchoredDraggableState.anchors.hasAnchorFor(Expanded) @@ -88,13 +93,6 @@ class SheetState( animateTo(Hidden) } - internal var anchoredDraggableState = AnchoredDraggableState( - initialValue = initialValue, - animationSpec = SpringSpec(), - positionalThreshold = { with(requireDensity()) { 56.dp.toPx() } }, - velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } }, - ) - private suspend fun animateTo( targetValue: SheetValue, velocity: Float = anchoredDraggableState.lastVelocity @@ -102,6 +100,13 @@ class SheetState( anchoredDraggableState.animateTo(targetValue, velocity) } + internal var anchoredDraggableState = AnchoredDraggableState( + initialValue = initialValue, + animationSpec = SpringSpec(), + positionalThreshold = { with(requireDensity()) { 56.dp.toPx() } }, + velocityThreshold = { with(requireDensity()) { 125.dp.toPx() } }, + ) + private fun requireDensity() = density companion object { @@ -148,11 +153,18 @@ internal object BottomSheetDefaults { } } + val bottomSheetContentPadding = 16.dp private val DockedDragHandleWidth = 32.0.dp private val DockedDragHandleHeight = 4.0.dp private val DragHandleVerticalPadding = 16.dp } +/** + * 바텀시트의 드래그 앵커를 설정하는 Modifier 확장 함수입니다. + * + * @param sheetState 현재 바텀시트 상태를 관리하는 객체 + * @param fullHeight 화면의 전체 높이 + */ @OptIn(ExperimentalFoundationApi::class) internal fun Modifier.modalBottomSheetAnchors( sheetState: SheetState, @@ -172,6 +184,13 @@ internal fun Modifier.modalBottomSheetAnchors( sheetState.anchoredDraggableState.updateAnchors(newAnchors, newTarget) } +/** + * 바텀시트가 보일 때 스크림 효과를 추가하는 함수입니다. + * + * @param color 스크림의 색상 + * @param onDismissRequest 스크림을 눌렀을 때 호출되는 콜백 함수 + * @param visible 스크림이 보이는지 여부를 결정 + */ @Composable internal fun Scrim( color: Color, diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/PrimitiveColors.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/PrimitiveColors.kt index 5739e773..f8671a8f 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/PrimitiveColors.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/PrimitiveColors.kt @@ -39,7 +39,8 @@ internal val ColorNeutralTransparent = Color(0x00FFFFFF) internal val ColorStatusRedMain = Color(0xFFFF5C5C) internal val ColorStatusRedSub = Color(0xFFFFEBEB) - - internal val ColorFabPrimaryShadow = Color(0x6E768740).copy(alpha = 0.25f) -internal val ColorFabSecondaryShadow = Color(0xB5B9C440).copy(alpha = 0.25f) \ No newline at end of file +internal val ColorFabSecondaryShadow = Color(0xB5B9C440).copy(alpha = 0.25f) + +// Opacity/gray/080 +internal val ColorGray080 = Color(0xFF25262C).copy(alpha = 0.80f) \ No newline at end of file From f408080526e58b2767ee36c73141eee4ad66fc5c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 17:59:58 +0900 Subject: [PATCH 22/31] =?UTF-8?q?feat=20:=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20=EB=B0=8F=20Color=20=ED=86=A0=ED=81=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/demo/BottomSheetPreview.kt | 2 +- .../com/yourssu/handy/compose/BottomSheet.kt | 7 ++++--- .../com/yourssu/handy/compose/BottomSheetData.kt | 16 +++++++--------- .../handy/compose/foundation/SemanticColors.kt | 3 +++ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index 807dc9e2..f3cf3e17 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -42,7 +42,7 @@ fun TwoBottomSheetPreview() { onDismissRequest = {}, bottomSheetType = BottomSheetType.TwoButton( firstButtonText = "LEFT", - secondaryButtonText = "RIGHT" + secondButtonText = "RIGHT" ) ) { Text("two button") diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index b225b079..23d95a8e 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch /** - * BottomSheet의 타입을 나타냈습니다. + * BottomSheet의 타입을 나타냅니다. * * [NoButton] : 버튼 없이 내용만 표시 * [OneButton] : 하단에 버튼 한 개를 표시 @@ -71,7 +71,7 @@ sealed class BottomSheetType { * @param onOneButtonClick [BottomSheetType.OneButton]의 버튼 클릭 시 호출되는 함수 * @param onFirstButtonClick [BottomSheetType.TwoButton]의 첫 번째 버튼 클릭 시 호출되는 함수 * @param onSecondButtonClick [BottomSheetType.TwoButton]의 두 번째 버튼 클릭 시 호출되는 함수 - * @param bottomSheetType 바텀시트의 레이아웃 타입을 결정 + * @param bottomSheetType 바텀시트의 [BottomSheetType] 타입을 결정 * @param content 바텀시트 내부에 표시될 내용을 결정 */ @OptIn(ExperimentalFoundationApi::class) @@ -188,7 +188,7 @@ fun BottomSheet( * * @param buttonText 버튼에 표시될 텍스트 * @param onClick 버튼 클릭 시 호출되는 함수 - * @param modifier Modifier + * @param modifier Modifier 수정자 */ @Composable private fun OneButtonBottomSheet( @@ -217,6 +217,7 @@ private fun OneButtonBottomSheet( * @param secondButtonText 두 번째 버튼에 표시될 텍스트 * @param onFirstButtonClick 첫 번째 버튼 클릭 시 호출되는 함수 * @param onSecondButtonClick 두 번째 버튼 클릭 시 호출되는 함수 + * @param modifier Modifier 수정자 */ @Composable private fun TwoButtonBottomSheet( diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 41cd5d0a..06252fba 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable @@ -36,8 +37,8 @@ import com.yourssu.handy.compose.SheetValue.Hidden /** * 바텀시트의 상태를 정의하는 Enum 클래스입니다. * - * [Hidden]: 바텀시트가 보이지 않는 상태. - * [Expanded]: 바텀시트가 보이는 상태. + * [Hidden]: 바텀시트가 보이지 않는 상태 + * [Expanded]: 바텀시트가 보이는 상태 */ enum class SheetValue { Hidden, @@ -110,9 +111,6 @@ class SheetState( private fun requireDensity() = density companion object { - /** - * The default [Saver] implementation for [SheetState]. - */ fun Saver( density: Density ) = Saver( @@ -134,8 +132,8 @@ internal object BottomSheetDefaults { modifier: Modifier = Modifier, width: Dp = DockedDragHandleWidth, height: Dp = DockedDragHandleHeight, - shape: Shape = RoundedCornerShape(28.0.dp), - color: Color = Color(0xFFB5B9C4) + shape: Shape = CircleShape, + color: Color = HandyTheme.colors.bottomSheetHandle, ) { Surface( modifier = modifier @@ -188,8 +186,8 @@ internal fun Modifier.modalBottomSheetAnchors( * 바텀시트가 보일 때 스크림 효과를 추가하는 함수입니다. * * @param color 스크림의 색상 - * @param onDismissRequest 스크림을 눌렀을 때 호출되는 콜백 함수 - * @param visible 스크림이 보이는지 여부를 결정 + * @param onDismissRequest 스크림을 눌렀을 때 호출되는 함수 + * @param visible 스크림의 가시 여부 결정 */ @Composable internal fun Scrim( diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt index 5a50a8de..a4c702ab 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/foundation/SemanticColors.kt @@ -123,6 +123,9 @@ data class ColorScheme( val switchSelected: Color = ColorViolet500, val switchDisabled: Color = ColorGray200, val switchThumb: Color = ColorNeutralWhite, + + // BottomSheet + val bottomSheetHandle: Color = ColorGray300 ) val lightColorScheme = ColorScheme() From 09cb87bff7a977918f5024271ab48dbbf8961c22 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 18:04:51 +0900 Subject: [PATCH 23/31] =?UTF-8?q?feat=20:=20=ED=8C=A8=EB=94=A9=EA=B0=92=20?= =?UTF-8?q?=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 7 ++++--- .../kotlin/com/yourssu/handy/compose/BottomSheetData.kt | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 23d95a8e..184dc8b5 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -28,6 +28,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle import com.yourssu.handy.compose.BottomSheetDefaults.bottomSheetContentPadding +import com.yourssu.handy.compose.BottomSheetDefaults.surfaceBottomPadding +import com.yourssu.handy.compose.BottomSheetDefaults.surfaceHorizontalPadding import com.yourssu.handy.compose.BottomSheetType.NoButton import com.yourssu.handy.compose.BottomSheetType.OneButton import com.yourssu.handy.compose.BottomSheetType.TwoButton @@ -119,8 +121,8 @@ fun BottomSheet( modifier = modifier .fillMaxWidth() .align(Alignment.BottomCenter) - .padding(horizontal = 16.dp) - .padding(bottom = 34.dp) + .padding(horizontal = surfaceHorizontalPadding) + .padding(bottom = surfaceBottomPadding) .offset { IntOffset( x = 0, @@ -257,4 +259,3 @@ private fun TwoButtonBottomSheet( } } } - diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 06252fba..ec8a2870 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -152,6 +152,8 @@ internal object BottomSheetDefaults { } val bottomSheetContentPadding = 16.dp + val surfaceHorizontalPadding = 16.dp + val surfaceBottomPadding = 34.dp private val DockedDragHandleWidth = 32.0.dp private val DockedDragHandleHeight = 4.0.dp private val DragHandleVerticalPadding = 16.dp From d71a8c6a306aab1cb80d5aebf6e9ddfea52425c5 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 18:31:30 +0900 Subject: [PATCH 24/31] =?UTF-8?q?feat=20:=20=EC=B5=9C=EC=86=8C=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=EC=A6=88=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/compose/BottomSheet.kt | 59 +++++++++++-------- .../yourssu/handy/compose/BottomSheetData.kt | 9 +-- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index 184dc8b5..ada0040b 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -27,7 +28,9 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle -import com.yourssu.handy.compose.BottomSheetDefaults.bottomSheetContentPadding +import com.yourssu.handy.compose.BottomSheetDefaults.buttonHeight +import com.yourssu.handy.compose.BottomSheetDefaults.contentMinHeight +import com.yourssu.handy.compose.BottomSheetDefaults.contentPadding import com.yourssu.handy.compose.BottomSheetDefaults.surfaceBottomPadding import com.yourssu.handy.compose.BottomSheetDefaults.surfaceHorizontalPadding import com.yourssu.handy.compose.BottomSheetType.NoButton @@ -145,32 +148,42 @@ fun BottomSheet( modifier = Modifier .background(HandyTheme.colors.bgBasicDefault) .align(Alignment.BottomCenter) - .padding(horizontal = bottomSheetContentPadding) - .padding(bottom = bottomSheetContentPadding), + .padding(horizontal = contentPadding) + .padding(bottom = contentPadding), horizontalAlignment = Alignment.CenterHorizontally ) { - DragHandle() - Spacer(modifier = Modifier.height(bottomSheetContentPadding)) - content() - Spacer(modifier = Modifier.height(bottomSheetContentPadding)) - - when (bottomSheetType) { - is NoButton -> {} + Column( + modifier = Modifier + .defaultMinSize( + minHeight = if (bottomSheetType == NoButton) contentMinHeight + else contentMinHeight - buttonHeight + ), + horizontalAlignment = Alignment.CenterHorizontally + ) { + DragHandle() + Spacer(modifier = Modifier.height(contentPadding)) + content() + Spacer(modifier = Modifier.height(contentPadding)) + } + Column { + when (bottomSheetType) { + is NoButton -> {} - is OneButton -> { - OneButtonBottomSheet( - buttonText = bottomSheetType.buttonText, - onClick = onOneButtonClick - ) - } + is OneButton -> { + OneButtonBottomSheet( + buttonText = bottomSheetType.buttonText, + onClick = onOneButtonClick + ) + } - is TwoButton -> { - TwoButtonBottomSheet( - firstButtonText = bottomSheetType.firstButtonText, - secondButtonText = bottomSheetType.secondButtonText, - onFirstButtonClick = onFirstButtonClick, - onSecondButtonClick = onSecondButtonClick - ) + is TwoButton -> { + TwoButtonBottomSheet( + firstButtonText = bottomSheetType.firstButtonText, + secondButtonText = bottomSheetType.secondButtonText, + onFirstButtonClick = onFirstButtonClick, + onSecondButtonClick = onSecondButtonClick + ) + } } } diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index ec8a2870..401c92b8 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue @@ -151,11 +150,13 @@ internal object BottomSheetDefaults { } } - val bottomSheetContentPadding = 16.dp + val contentPadding = 16.dp + val contentMinHeight = 260.dp + val buttonHeight = 52.dp val surfaceHorizontalPadding = 16.dp val surfaceBottomPadding = 34.dp - private val DockedDragHandleWidth = 32.0.dp - private val DockedDragHandleHeight = 4.0.dp + private val DockedDragHandleWidth = 32.dp + private val DockedDragHandleHeight = 4.dp private val DragHandleVerticalPadding = 16.dp } From b0f753f1d12188e0cba155635d6440f498239a44 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 18:37:19 +0900 Subject: [PATCH 25/31] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/yourssu/handy/demo/BottomSheetPreview.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index f3cf3e17..7dda9fa8 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -5,14 +5,20 @@ import androidx.compose.ui.tooling.preview.Preview import com.yourssu.handy.compose.BottomSheet import com.yourssu.handy.compose.BottomSheetType import com.yourssu.handy.compose.HandyTheme +import com.yourssu.handy.compose.SheetValue import com.yourssu.handy.compose.Text +import com.yourssu.handy.compose.rememberModalBottomSheetState @Preview(showBackground = true) @Composable fun NoBottomSheetPreview() { HandyTheme { + val sheetState = rememberModalBottomSheetState( + initialValue = SheetValue.Expanded + ) BottomSheet( - onDismissRequest = {} + onDismissRequest = {}, + sheetState = sheetState ) { Text("no button") } @@ -23,8 +29,12 @@ fun NoBottomSheetPreview() { @Composable fun OneBottomSheetPreview() { HandyTheme { + val sheetState = rememberModalBottomSheetState( + initialValue = SheetValue.Expanded + ) BottomSheet( onDismissRequest = {}, + sheetState = sheetState, bottomSheetType = BottomSheetType.OneButton( buttonText = "TEXT" ) @@ -38,8 +48,12 @@ fun OneBottomSheetPreview() { @Composable fun TwoBottomSheetPreview() { HandyTheme { + val sheetState = rememberModalBottomSheetState( + initialValue = SheetValue.Expanded + ) BottomSheet( onDismissRequest = {}, + sheetState = sheetState, bottomSheetType = BottomSheetType.TwoButton( firstButtonText = "LEFT", secondButtonText = "RIGHT" From 3516c974ecf915d27fff2392fbad6155dceebac6 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 18:58:36 +0900 Subject: [PATCH 26/31] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=EC=9D=98=20=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index 7dda9fa8..7edc8419 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -39,7 +39,7 @@ fun OneBottomSheetPreview() { buttonText = "TEXT" ) ) { - Text("one button") + Text("one button\none button\none button") } } } @@ -59,7 +59,7 @@ fun TwoBottomSheetPreview() { secondButtonText = "RIGHT" ) ) { - Text("two button") + Text("two button\ntwo button\ntwo button\ntwo button\ntwo button\ntwo button\ntwo button\ntwo button") } } } \ No newline at end of file From 6d55a6eab5839573723a38ed3a17ab177683df35 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 19:19:25 +0900 Subject: [PATCH 27/31] =?UTF-8?q?feat=20:=20NoButton=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/handy/demo/BottomSheetPreview.kt | 18 +----------------- .../com/yourssu/handy/compose/BottomSheet.kt | 16 +++------------- .../yourssu/handy/compose/BottomSheetData.kt | 3 +-- 3 files changed, 5 insertions(+), 32 deletions(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index 7edc8419..68a8d9fd 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -9,22 +9,6 @@ import com.yourssu.handy.compose.SheetValue import com.yourssu.handy.compose.Text import com.yourssu.handy.compose.rememberModalBottomSheetState -@Preview(showBackground = true) -@Composable -fun NoBottomSheetPreview() { - HandyTheme { - val sheetState = rememberModalBottomSheetState( - initialValue = SheetValue.Expanded - ) - BottomSheet( - onDismissRequest = {}, - sheetState = sheetState - ) { - Text("no button") - } - } -} - @Preview(showBackground = true) @Composable fun OneBottomSheetPreview() { @@ -39,7 +23,7 @@ fun OneBottomSheetPreview() { buttonText = "TEXT" ) ) { - Text("one button\none button\none button") + Text("one button\none button") } } } diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index ada0040b..d1461986 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -28,12 +28,10 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import com.yourssu.handy.compose.BottomSheetDefaults.DragHandle -import com.yourssu.handy.compose.BottomSheetDefaults.buttonHeight import com.yourssu.handy.compose.BottomSheetDefaults.contentMinHeight import com.yourssu.handy.compose.BottomSheetDefaults.contentPadding import com.yourssu.handy.compose.BottomSheetDefaults.surfaceBottomPadding import com.yourssu.handy.compose.BottomSheetDefaults.surfaceHorizontalPadding -import com.yourssu.handy.compose.BottomSheetType.NoButton import com.yourssu.handy.compose.BottomSheetType.OneButton import com.yourssu.handy.compose.BottomSheetType.TwoButton import com.yourssu.handy.compose.SheetValue.Hidden @@ -50,13 +48,10 @@ import kotlinx.coroutines.launch /** * BottomSheet의 타입을 나타냅니다. * - * [NoButton] : 버튼 없이 내용만 표시 * [OneButton] : 하단에 버튼 한 개를 표시 * [TwoButton] : 하단에 버튼 두 개를 표시 */ sealed class BottomSheetType { - data object NoButton : BottomSheetType() - data class OneButton( val buttonText: String ) : BottomSheetType() @@ -71,24 +66,24 @@ sealed class BottomSheetType { * 바텀시트의 UI를 나타내는 함수입니다. * * @param onDismissRequest 바텀시트가 닫힐 때 호출되는 함수 + * @param bottomSheetType 바텀시트의 [BottomSheetType] 타입을 결정 * @param modifier Modifier 수정자 * @param sheetState 바텀시트의 상태를 나타내는 객체 * @param onOneButtonClick [BottomSheetType.OneButton]의 버튼 클릭 시 호출되는 함수 * @param onFirstButtonClick [BottomSheetType.TwoButton]의 첫 번째 버튼 클릭 시 호출되는 함수 * @param onSecondButtonClick [BottomSheetType.TwoButton]의 두 번째 버튼 클릭 시 호출되는 함수 - * @param bottomSheetType 바텀시트의 [BottomSheetType] 타입을 결정 * @param content 바텀시트 내부에 표시될 내용을 결정 */ @OptIn(ExperimentalFoundationApi::class) @Composable fun BottomSheet( onDismissRequest: () -> Unit, + bottomSheetType: BottomSheetType, modifier: Modifier = Modifier, sheetState: SheetState = rememberModalBottomSheetState(), onOneButtonClick: () -> Unit = {}, onFirstButtonClick: () -> Unit = {}, onSecondButtonClick: () -> Unit = {}, - bottomSheetType: BottomSheetType = NoButton, content: @Composable () -> Unit = {} ) { val density = LocalDensity.current @@ -154,10 +149,7 @@ fun BottomSheet( ) { Column( modifier = Modifier - .defaultMinSize( - minHeight = if (bottomSheetType == NoButton) contentMinHeight - else contentMinHeight - buttonHeight - ), + .defaultMinSize(minHeight = contentMinHeight), horizontalAlignment = Alignment.CenterHorizontally ) { DragHandle() @@ -167,8 +159,6 @@ fun BottomSheet( } Column { when (bottomSheetType) { - is NoButton -> {} - is OneButton -> { OneButtonBottomSheet( buttonText = bottomSheetType.buttonText, diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 401c92b8..2fc84be1 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -151,8 +151,7 @@ internal object BottomSheetDefaults { } val contentPadding = 16.dp - val contentMinHeight = 260.dp - val buttonHeight = 52.dp + val contentMinHeight = 208.dp val surfaceHorizontalPadding = 16.dp val surfaceBottomPadding = 34.dp private val DockedDragHandleWidth = 32.dp From 781e039acd1514a6185f8b3804ff3bfb019ebb11 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 19:31:30 +0900 Subject: [PATCH 28/31] =?UTF-8?q?feat=20:=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index d1461986..c57c947c 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -48,8 +48,8 @@ import kotlinx.coroutines.launch /** * BottomSheet의 타입을 나타냅니다. * - * [OneButton] : 하단에 버튼 한 개를 표시 - * [TwoButton] : 하단에 버튼 두 개를 표시 + * [OneButton] : 하단에 버튼 한 개 표시 + * [TwoButton] : 하단에 버튼 두 개 표시 */ sealed class BottomSheetType { data class OneButton( @@ -176,7 +176,6 @@ fun BottomSheet( } } } - } } } From 3a2542b478b72391da8e5c168a665f1f23071745 Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Tue, 21 Jan 2025 19:55:23 +0900 Subject: [PATCH 29/31] =?UTF-8?q?feat=20:=20=ED=94=84=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yourssu/handy/demo/BottomSheetPreview.kt | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt index 68a8d9fd..b72652bd 100644 --- a/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt +++ b/app/src/main/kotlin/com/yourssu/handy/demo/BottomSheetPreview.kt @@ -11,7 +11,7 @@ import com.yourssu.handy.compose.rememberModalBottomSheetState @Preview(showBackground = true) @Composable -fun OneBottomSheetPreview() { +private fun OneShortBottomSheetPreview() { HandyTheme { val sheetState = rememberModalBottomSheetState( initialValue = SheetValue.Expanded @@ -23,14 +23,53 @@ fun OneBottomSheetPreview() { buttonText = "TEXT" ) ) { - Text("one button\none button") + Text("one button") } } } @Preview(showBackground = true) @Composable -fun TwoBottomSheetPreview() { +private fun OneLongBottomSheetPreview() { + HandyTheme { + val sheetState = rememberModalBottomSheetState( + initialValue = SheetValue.Expanded + ) + BottomSheet( + onDismissRequest = {}, + sheetState = sheetState, + bottomSheetType = BottomSheetType.OneButton( + buttonText = "TEXT" + ) + ) { + Text("one button\none button\none button\none button\none button\none button\none button\none button") + } + } +} + +@Preview(showBackground = true) +@Composable +private fun TwoShortBottomSheetPreview() { + HandyTheme { + val sheetState = rememberModalBottomSheetState( + initialValue = SheetValue.Expanded + ) + BottomSheet( + onDismissRequest = {}, + sheetState = sheetState, + bottomSheetType = BottomSheetType.TwoButton( + firstButtonText = "LEFT", + secondButtonText = "RIGHT" + ) + ) { + Text("two button") + } + } +} + +@Preview(showBackground = true) +@Composable +private fun TwoLongBottomSheetPreview() { HandyTheme { val sheetState = rememberModalBottomSheetState( initialValue = SheetValue.Expanded From ca7ac13246b706997f2170cba82aab2565e01c6c Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Wed, 29 Jan 2025 20:50:48 +0900 Subject: [PATCH 30/31] =?UTF-8?q?feat=20:=20content=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt index c57c947c..cb3927c6 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheet.kt @@ -84,7 +84,7 @@ fun BottomSheet( onOneButtonClick: () -> Unit = {}, onFirstButtonClick: () -> Unit = {}, onSecondButtonClick: () -> Unit = {}, - content: @Composable () -> Unit = {} + content: @Composable () -> Unit ) { val density = LocalDensity.current SideEffect { From 4b1ec412eb0eb488958a3806ded5de8a6d46dd7e Mon Sep 17 00:00:00 2001 From: LEE YOU BIN Date: Sat, 1 Feb 2025 22:38:42 +0900 Subject: [PATCH 31/31] =?UTF-8?q?feat=20:=20=EC=A4=84=EB=B0=94=EA=BF=88=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt index 2fc84be1..40108c85 100644 --- a/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt +++ b/compose/src/main/kotlin/com/yourssu/handy/compose/BottomSheetData.kt @@ -118,7 +118,6 @@ class SheetState( SheetState(density, savedValue) } ) - } }