-
Notifications
You must be signed in to change notification settings - Fork 3
[UI] 기록장 화면에 필요한 컴포넌트 #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4864ca6
29e9479
8460f7c
8290279
28d0215
49f4e92
8d6b3c2
ac5cffa
a97c3fd
d78bb8b
9f5f578
fed3c80
b4b0111
6f8cfb7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| package com.texthip.thip.ui.common.bottomsheet | ||
|
|
||
| import androidx.compose.animation.core.Animatable | ||
| import androidx.compose.animation.core.tween | ||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.clickable | ||
| import androidx.compose.foundation.gestures.detectVerticalDragGestures | ||
| import androidx.compose.foundation.interaction.MutableInteractionSource | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Box | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.Spacer | ||
| import androidx.compose.foundation.layout.fillMaxSize | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.height | ||
| import androidx.compose.foundation.layout.offset | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||
| import androidx.compose.material3.HorizontalDivider | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.LaunchedEffect | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableFloatStateOf | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.remember | ||
| import androidx.compose.runtime.rememberCoroutineScope | ||
| import androidx.compose.runtime.setValue | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Color | ||
| import androidx.compose.ui.input.pointer.pointerInput | ||
| import androidx.compose.ui.res.stringResource | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import androidx.compose.ui.zIndex | ||
| import com.texthip.thip.R | ||
| import com.texthip.thip.ui.theme.ThipTheme.colors | ||
| import com.texthip.thip.ui.theme.ThipTheme.typography | ||
| import kotlinx.coroutines.launch | ||
|
|
||
| data class MenuBottomSheetItem( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. data class는 분리 안하신 이유가 있을까용
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 이거 보기&수정하기 편하려고 같은 화면에 놓고 개발 하다가 옮겨야됐었는데 까먹었네요 .. ㅋㅎㅋㅎㅋㅎㅋ 옮기겠습니닷 |
||
| val text: String, | ||
| val color: Color = Color.White, | ||
| val onClick: () -> Unit, | ||
| ) | ||
|
|
||
| @Composable | ||
| fun MenuBottomSheet( | ||
| items: List<MenuBottomSheetItem>, | ||
| onDismiss: () -> Unit | ||
| ) { | ||
| val scope = rememberCoroutineScope() | ||
| val animatableOffset = remember { Animatable(300f) } // 시작 위치 아래 | ||
| var offsetY by remember { mutableFloatStateOf(0f) } | ||
| var isDismissing by remember { mutableStateOf(false) } | ||
|
|
||
| // 등장 애니메이션 | ||
| LaunchedEffect(Unit) { | ||
| animatableOffset.animateTo( | ||
| targetValue = 0f, | ||
| animationSpec = tween(durationMillis = 300) | ||
| ) | ||
| } | ||
|
|
||
| // 바깥 클릭 감지 | ||
| Box( | ||
| modifier = Modifier | ||
| .fillMaxSize() | ||
| .clickable( | ||
| indication = null, | ||
| interactionSource = remember { MutableInteractionSource() } | ||
| ) { | ||
| if (!isDismissing) { | ||
| isDismissing = true | ||
| scope.launch { | ||
| animatableOffset.animateTo(300f, tween(300)) | ||
| onDismiss() | ||
| } | ||
| } | ||
| } | ||
| .zIndex(1f) // 다른 컴포넌트 위에 뜨도록 | ||
| ) | ||
|
|
||
|
|
||
| // BottomSheet 본체 | ||
| Box( | ||
| modifier = Modifier | ||
| .fillMaxSize() | ||
| .zIndex(2f), // 시트가 배경보다 위에 뜨도록 | ||
| contentAlignment = Alignment.BottomCenter | ||
| ) { | ||
| Box( | ||
| modifier = Modifier | ||
| .fillMaxWidth() | ||
| .offset(y = (offsetY + animatableOffset.value).dp) | ||
| .background( | ||
| color = colors.DarkGrey, | ||
| shape = RoundedCornerShape(topEnd = 12.dp, topStart = 12.dp) | ||
| ) | ||
| .padding(20.dp) | ||
| .pointerInput(Unit) { | ||
| detectVerticalDragGestures( | ||
| onVerticalDrag = { _, dragAmount -> | ||
| if (dragAmount > 0) { | ||
| offsetY += dragAmount / 2 // 아래로 드래그할 때만 적용 | ||
| } | ||
| }, | ||
| onDragEnd = { | ||
| if (offsetY > 100f && !isDismissing) { | ||
| isDismissing = true | ||
| scope.launch { | ||
| animatableOffset.animateTo(300f, tween(300)) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런 튜닝값? 들도 위에 상수로 추출하는게 좋을 것 같아요! 나중에 UX적으로 숫자 수정할 일이 많을 것 같네용 |
||
| onDismiss() | ||
| } | ||
| } else { | ||
| offsetY = 0f | ||
| } | ||
| } | ||
| ) | ||
| } | ||
| .clickable(enabled = true) {} // 내부 클릭 무시되지 않도록 | ||
| ) { | ||
| Column(modifier = Modifier.fillMaxWidth()) { | ||
| items.forEachIndexed { index, item -> | ||
| if (index > 0) { | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| HorizontalDivider(modifier = Modifier.height(1.dp), color = colors.Grey03) | ||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| } | ||
|
|
||
| Column( | ||
| modifier = Modifier | ||
| .height(50.dp) | ||
| .padding(horizontal = 12.dp, vertical = 8.dp), | ||
| verticalArrangement = Arrangement.Center | ||
| ) { | ||
| Text( | ||
| text = item.text, | ||
| style = typography.menu_m500_s16_h24, | ||
| color = item.color, | ||
| modifier = Modifier | ||
| .fillMaxWidth() | ||
| .clickable { | ||
| item.onClick() | ||
| onDismiss() | ||
| } | ||
| ) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Preview | ||
| @Composable | ||
| private fun MenuBottomSheetPreview() { | ||
| MenuBottomSheet( | ||
| items = listOf( | ||
| MenuBottomSheetItem( | ||
| text = stringResource(R.string.leave_room), | ||
| color = colors.White, | ||
| onClick = { } | ||
| ), | ||
| MenuBottomSheetItem( | ||
| text = stringResource(R.string.report_room), | ||
| color = colors.Red, | ||
| onClick = { } | ||
| ), | ||
| MenuBottomSheetItem( | ||
| text = stringResource(R.string.delete_room), | ||
| color = colors.Red, | ||
| onClick = { } | ||
| ) | ||
| ), | ||
| onDismiss = {} | ||
| ) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| package com.texthip.thip.ui.common.buttons | ||
|
|
||
| import androidx.compose.foundation.clickable | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Row | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.material3.Icon | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.remember | ||
| import androidx.compose.runtime.setValue | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Color | ||
| import androidx.compose.ui.res.painterResource | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
| import androidx.compose.ui.unit.dp | ||
| import com.texthip.thip.R | ||
| import com.texthip.thip.ui.theme.ThipTheme.colors | ||
| import com.texthip.thip.ui.theme.ThipTheme.typography | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. slot api 느낌의 코드 같은데 이렇게 분리 하신 이유가 있을까요?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 안스 켜서 확인해보니 많이 쓰이는 화면이네요 확인했습니다... |
||
| @Composable | ||
| fun ActionBarButton( | ||
| modifier: Modifier = Modifier, | ||
| isLiked: Boolean, | ||
| likeCount: Int, | ||
| commentCount: Int, | ||
| isSaveVisible: Boolean = false, | ||
| isSaved: Boolean = false, | ||
| isPinVisible: Boolean = false, | ||
| onLikeClick: () -> Unit = {}, | ||
| onCommentClick: () -> Unit = {}, | ||
| onBookmarkClick: () -> Unit = {}, | ||
| onPinClick: () -> Unit = {} | ||
| ) { | ||
| Row( | ||
| modifier = modifier.fillMaxWidth(), | ||
| verticalAlignment = Alignment.CenterVertically, | ||
| horizontalArrangement = Arrangement.SpaceBetween | ||
| ) { | ||
| Row( | ||
| horizontalArrangement = Arrangement.spacedBy(12.dp), | ||
| ) { | ||
| Row( | ||
| modifier = Modifier.clickable { onLikeClick() }, | ||
| horizontalArrangement = Arrangement.spacedBy(2.dp), | ||
| verticalAlignment = Alignment.CenterVertically | ||
| ) { | ||
| Icon( | ||
| painter = painterResource(if (isLiked) R.drawable.ic_heart_filled else R.drawable.ic_heart), | ||
| contentDescription = null, | ||
| tint = Color.Unspecified | ||
| ) | ||
| Text( | ||
| text = likeCount.toString(), | ||
| style = typography.feedcopy_r400_s14_h20, | ||
| color = colors.White, | ||
| ) | ||
| } | ||
|
|
||
| Row( | ||
| modifier = Modifier.clickable { onCommentClick() }, | ||
| horizontalArrangement = Arrangement.spacedBy(2.dp), | ||
| verticalAlignment = Alignment.CenterVertically | ||
| ) { | ||
| Icon( | ||
| painter = painterResource(R.drawable.ic_comment), | ||
| contentDescription = null, | ||
| tint = colors.White | ||
| ) | ||
| Text( | ||
| text = commentCount.toString(), | ||
| style = typography.feedcopy_r400_s14_h20, | ||
| color = colors.White, | ||
| ) | ||
| } | ||
|
|
||
| if (isPinVisible) { | ||
| Icon( | ||
| modifier = Modifier.clickable { onPinClick() }, | ||
| painter = painterResource(R.drawable.ic_pin), | ||
| contentDescription = null, | ||
| tint = Color.White | ||
| ) | ||
|
Comment on lines
+80
to
+86
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요것은 원래 눌렀을때 색상변화가 없나유?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넹 디자이너님이 없다고 해쪄용 |
||
| } | ||
| } | ||
|
|
||
| if (isSaveVisible) { | ||
| Icon( | ||
| modifier = Modifier.clickable { onBookmarkClick() }, | ||
| painter = painterResource(if (isSaved) R.drawable.ic_save_filled else R.drawable.ic_save), | ||
| contentDescription = null, | ||
| tint = Color.Unspecified | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Preview | ||
| @Composable | ||
| private fun ActionBarButtonPreview() { | ||
| var isLiked by remember { mutableStateOf(false) } | ||
| var isSaved by remember { mutableStateOf(false) } | ||
|
|
||
| ActionBarButton( | ||
| isLiked = isLiked, | ||
| likeCount = 123, | ||
| commentCount = 45, | ||
| isSaveVisible = true, | ||
| isSaved = isSaved, | ||
| isPinVisible = true, | ||
| onLikeClick = { isLiked = !isLiked }, | ||
| onCommentClick = {}, | ||
| onBookmarkClick = { isSaved = !isSaved }, | ||
| onPinClick = {} | ||
| ) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 덕분에 편하게 개발했읍니다.,.