-
Notifications
You must be signed in to change notification settings - Fork 0
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
SnackBar 구현 #14
Open
leeeyubin
wants to merge
27
commits into
main
Choose a base branch
from
feature/bona/snackbar
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
SnackBar 구현 #14
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
298f689
feat : make snackbar file
leeeyubin b5eb37c
feat : make snackbar preview file
leeeyubin 08b3dc3
feat : make InfoSnackBar
leeeyubin 435824b
feat : make ErrorSnackBar
leeeyubin 47e4c76
feat : make AutoInfoSnackBar
leeeyubin a8337d7
feat : make AutoErrorSnackBar
leeeyubin aa92578
feat : change snackbar function name
leeeyubin d1e51cd
chore : 코드 수정
leeeyubin dc8b143
feat : 정보성 스낵바 주석 추가
leeeyubin ccd35a8
feat : 에러 스낵바 주석 추가
leeeyubin a7c3700
feat : 에러 스낵바 아이콘 정렬
leeeyubin e65c063
feat : 스낵바 지속시간 상수화
leeeyubin 8f96b18
fix : 핸디 스낵바 컬러 추가
leeeyubin 3955b5d
fix : modify to Handy Icon
leeeyubin 7ab14c5
refactor : refactor snackBar code
leeeyubin e81f277
feat : git pull from main
leeeyubin 90f60c9
feat : add error SnackBar type
leeeyubin b342e26
feat : currentSnackBarData 변수 사용
leeeyubin 3b5b996
feat : 스와이프 기능 구현
leeeyubin 5334b9a
feat : 주석 추가
leeeyubin b26f978
feat : 에러 스낵바 UI 수정 및 LineBreak 속성 추가
leeeyubin ac45fb4
feat : 정보성 스낵바 단어 개행 구현
leeeyubin c55e525
feat : 정보성 스낵바 단어 개행 구현
leeeyubin fc05bf7
feat : Text lineBreak 속성 제거
leeeyubin 6af901d
feat : 에러 스낵바 단어 개행 구현
leeeyubin e2c7cb5
feat : 불필요한 Column 삭제
leeeyubin 1b197c4
feat : git pull from main
leeeyubin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
Empty file.
53 changes: 53 additions & 0 deletions
53
app/src/main/kotlin/com/yourssu/handy/demo/SnackBarPreview.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package com.yourssu.handy.demo | ||
|
||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.height | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import com.yourssu.handy.compose.ErrorSnackBar | ||
import com.yourssu.handy.compose.HandyTheme | ||
import com.yourssu.handy.compose.InfoSnackBar | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
fun InfoSnackBarPreview() { | ||
HandyTheme { | ||
Column( | ||
modifier = Modifier.padding(10.dp) | ||
) { | ||
InfoSnackBar( | ||
text = "한 줄짜리 정보성 메세지가 들어갑니다.", | ||
onDismiss = {} | ||
) | ||
Spacer(modifier = Modifier.height(10.dp)) | ||
InfoSnackBar( | ||
text = "줄 수가 두 줄 이상이 되는 스낵바 메시지입니다. 좌측 정렬을 해주세요.", | ||
onDismiss = {} | ||
) | ||
} | ||
} | ||
} | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
fun ErrorSnackBarPreview() { | ||
HandyTheme { | ||
Column( | ||
modifier = Modifier.padding(10.dp) | ||
) { | ||
ErrorSnackBar( | ||
text = "에러 메세지가 들어갑니다", | ||
onClick = {} | ||
) | ||
Spacer(modifier = Modifier.height(10.dp)) | ||
ErrorSnackBar( | ||
text = "두 줄 이상의 에러 메세지가 들어갈 경우 아이콘은 모두 위로 정렬해주세요.", | ||
onClick = {} | ||
) | ||
} | ||
} | ||
} |
190 changes: 190 additions & 0 deletions
190
compose/src/main/kotlin/com/yourssu/handy/compose/SnackBar.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
package com.yourssu.handy.compose | ||
|
||
import androidx.compose.animation.core.Animatable | ||
import androidx.compose.animation.core.tween | ||
import androidx.compose.foundation.ExperimentalFoundationApi | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.gestures.AnchoredDraggableState | ||
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.Column | ||
import androidx.compose.foundation.layout.ExperimentalLayoutApi | ||
import androidx.compose.foundation.layout.FlowRow | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.fillMaxWidth | ||
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.remember | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.draw.clip | ||
import androidx.compose.ui.platform.LocalDensity | ||
import androidx.compose.ui.unit.IntOffset | ||
import androidx.compose.ui.unit.dp | ||
import com.yourssu.handy.compose.foundation.HandyTypography | ||
import com.yourssu.handy.compose.icons.HandyIcons | ||
import com.yourssu.handy.compose.icons.filled.AlertTriangle | ||
import com.yourssu.handy.compose.icons.line.Close | ||
import kotlin.math.roundToInt | ||
|
||
/** | ||
* 드래그 위치를 나타냅니다. | ||
* Start는 초기 위치, End는 스낵바가 사라질 위치를 나타냅니다. | ||
*/ | ||
enum class DragValue { | ||
Start, End | ||
} | ||
|
||
/** | ||
* 정보성 스낵바의 UI를 그린 함수입니다. | ||
* | ||
* 유저의 행동에 대한 단순 결과를 나타낼 때 사용합니다. | ||
* | ||
* 특정 시간(기본 5초) 노출 후에 자동으로 사라집니다. | ||
* 아래로 스와이프 할 경우에도 사라집니다. | ||
* | ||
* @param text 스낵바의 문구를 나타내는 텍스트, 최대 두 줄까지 입력 가능 | ||
* @param modifier Modifier | ||
*/ | ||
@OptIn(ExperimentalFoundationApi::class, ExperimentalLayoutApi::class) | ||
@Composable | ||
fun InfoSnackBar( | ||
text: String, | ||
onDismiss: () -> Unit, | ||
leeeyubin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
modifier: Modifier = Modifier, | ||
) { | ||
val density = LocalDensity.current | ||
val state = remember { | ||
AnchoredDraggableState( | ||
initialValue = DragValue.Start, | ||
anchors = DraggableAnchors { | ||
with(density) { | ||
DragValue.Start at 0f | ||
DragValue.End at 20.dp.toPx() | ||
} | ||
}, | ||
positionalThreshold = { distance: Float -> distance * 0.5f }, | ||
velocityThreshold = { with(density) { 50.dp.toPx() } }, | ||
animationSpec = tween(), | ||
) | ||
} | ||
val offsetY = remember { Animatable(0f) } | ||
|
||
if (state.currentValue == DragValue.End) { | ||
onDismiss() | ||
} | ||
|
||
Column( | ||
modifier = modifier | ||
.offset { | ||
IntOffset( | ||
x = 0, | ||
y = offsetY.value.roundToInt() | ||
) | ||
} | ||
.padding(horizontal = 16.dp) | ||
.fillMaxWidth() | ||
.clip(RoundedCornerShape(12.dp)) | ||
.background(HandyTheme.colors.snackBarInfo) | ||
.padding(16.dp) | ||
.anchoredDraggable( | ||
state = state, | ||
orientation = Orientation.Vertical, | ||
) | ||
) { | ||
text.split("\n").forEach { line -> | ||
FlowRow { | ||
line.split(" ").forEachIndexed { index, word -> | ||
Text( | ||
text = word, | ||
color = HandyTheme.colors.textBasicWhite, | ||
maxLines = 2, | ||
style = HandyTypography.B3Sb14 | ||
) | ||
if (index != line.split(" ").lastIndex) { | ||
Text( | ||
text = " ", | ||
color = HandyTheme.colors.textBasicWhite, | ||
style = HandyTypography.B3Sb14 | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* 에러 스낵바의 UI를 그린 함수입니다. | ||
* | ||
* 사용자의 수행 과정에 부정적인 결과가 발생하거나 | ||
* 정보성 스낵바보다 강조해야 할 메시지를 담아야 할 때 사용합니다. | ||
* | ||
* X 버튼을 눌러야만 사라집니다. | ||
* | ||
* @param text 스낵바의 문구를 나타내는 텍스트, 최대 두 줄까지 입력 가능 | ||
* @param onClick 스낵바의 X 버튼을 눌렀을 때 호출되는 함수 | ||
* @param modifier Modifier | ||
*/ | ||
@OptIn(ExperimentalLayoutApi::class) | ||
@Composable | ||
fun ErrorSnackBar( | ||
text: String, | ||
onClick: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
) { | ||
Row( | ||
modifier = modifier | ||
.padding(horizontal = 16.dp) | ||
kangyuri1114 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.fillMaxWidth() | ||
.clip(RoundedCornerShape(12.dp)) | ||
.background(HandyTheme.colors.snackBarError) | ||
.padding(16.dp), | ||
horizontalArrangement = Arrangement.spacedBy(12.dp), | ||
verticalAlignment = Alignment.CenterVertically | ||
) { | ||
Icon( | ||
imageVector = HandyIcons.Filled.AlertTriangle, | ||
tint = HandyTheme.colors.bgStatusNegative, | ||
modifier = Modifier.align(Alignment.Top) | ||
) | ||
text.split("\n").forEach { line -> | ||
FlowRow(modifier = Modifier.weight(1f)) { | ||
line.split(" ").forEachIndexed { index, word -> | ||
Text( | ||
text = word, | ||
color = HandyTheme.colors.textStatusNegative, | ||
maxLines = 2, | ||
style = HandyTypography.B3Sb14 | ||
) | ||
if (index != line.split(" ").lastIndex) { | ||
Text( | ||
text = " ", | ||
color = HandyTheme.colors.textStatusNegative, | ||
style = HandyTypography.B3Sb14 | ||
) | ||
} | ||
} | ||
} | ||
} | ||
Icon( | ||
imageVector = HandyIcons.Line.Close, | ||
tint = HandyTheme.colors.textBasicTertiary, | ||
modifier = Modifier | ||
.clickable(onClick = onClick) | ||
.align(Alignment.Top) | ||
) | ||
} | ||
} | ||
|
||
object SnackBarDefaults { | ||
const val SNACK_BAR_DURATION = 5000L | ||
const val FADE_IN_DURATION = 500 | ||
const val FADE_OUT_DURATION = 300 | ||
const val TARGET_VALUE = -16f | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
X 버튼 클릭이라는게 좀더 잘 드러나면 어떨까요?
onCancel(Click)
이나onClose(Click)
등.. X 버튼 클릭의 부정적인 느낌이 좀 더 나면 좋을 것 같습니도