Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Dialog 구현 #21

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
152 changes: 152 additions & 0 deletions app/src/main/kotlin/com/yourssu/handy/demo/DialogPreview.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package com.yourssu.handy.demo

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
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.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.yourssu.handy.compose.HandyTheme
import com.yourssu.handy.compose.Icon
import com.yourssu.handy.compose.OneButtonDialog
import com.yourssu.handy.compose.TwoButtonDialog
import com.yourssu.handy.compose.button.BoxButton
import com.yourssu.handy.compose.icons.HandyIcons
import com.yourssu.handy.compose.icons.filled.Add

@Preview
@Composable
private fun OneButtonDialogPreview() {

var showDialog by remember { mutableStateOf(true) }

HandyTheme {
Column {
OneButtonDialog(
title = "제목이 들어갑니다",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼",
onPositiveClick = {},
onDismiss = { showDialog = false } // 다이얼로그 닫기
)

Spacer(modifier = Modifier.height(10.dp))

OneButtonDialog(
title = "보다 더 정확하게 분석하기 위해 다음 질문에 대해 대답해주세요.",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼",
onPositiveClick = {},
onDismiss = { showDialog = false } // 다이얼로그 닫기
)

Spacer(modifier = Modifier.height(10.dp))

OneButtonDialog(
title = "제목이 들어갑니다",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼",
onPositiveClick = {},
onDismiss = { showDialog = false }, // 다이얼로그 닫기
content = { Icon(HandyIcons.Filled.Add) }
)
}
}
}

@Preview
@Composable
private fun TwoButtonDialogPreview() {

var showDialog by remember { mutableStateOf(true) }

HandyTheme {
Column {
TwoButtonDialog(
title = "제목이 들어갑니다",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼2",
onPositiveClick = {},
onDismiss = { showDialog = false }, // 다이얼로그 닫기
negativeText = "버튼1",
onNegativeClick = {},
)

Spacer(modifier = Modifier.height(10.dp))

TwoButtonDialog(
title = "보다 더 정확하게 분석하기 위해 다음 질문에 대해 대답해주세요.",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼2",
onPositiveClick = {},
onDismiss = { showDialog = false }, // 다이얼로그 닫기
negativeText = "버튼1",
onNegativeClick = {},
)

Spacer(modifier = Modifier.height(10.dp))

TwoButtonDialog(
title = "제목이 들어갑니다",
description = "내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다 내용이 들어갑니다",
positiveText = "버튼2",
onPositiveClick = {},
onDismiss = { showDialog = false }, // 다이얼로그 닫기
negativeText = "버튼1",
onNegativeClick = {},
content = { Icon(HandyIcons.Filled.Add) }
)
}
}
}

@Preview
@Composable
private fun DialogOnScreenPreview() {

var showOneButtonDialog by remember { mutableStateOf(false) }
var showTwoButtonDialog by remember { mutableStateOf(false) }

HandyTheme {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
BoxButton(text = "원버튼 다이알로그", onClick = { showOneButtonDialog = true })
Spacer(modifier = Modifier.height(10.dp))
BoxButton(text = "투버튼 다이알로그", onClick = { showTwoButtonDialog = true })
}

if (showOneButtonDialog) {
OneButtonDialog(
title = "제목이 들어갑니다",
description = "내용",
positiveText = "버튼",
onPositiveClick = { showOneButtonDialog = false },
onDismiss = { showOneButtonDialog = false }
)
} else if (showTwoButtonDialog) {
TwoButtonDialog(
title = "제목이 들어갑니다",
description = "내용",
positiveText = "버튼",
onPositiveClick = { showTwoButtonDialog = false },
onDismiss = { showTwoButtonDialog = false },
negativeText = "버튼",
onNegativeClick = { showTwoButtonDialog = false }
)
}
}
}
237 changes: 237 additions & 0 deletions compose/src/main/kotlin/com/yourssu/handy/compose/Dialog.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package com.yourssu.handy.compose

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
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
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
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.unit.dp
import com.yourssu.handy.compose.DialogDefaults.dialogButtonSpacing
import com.yourssu.handy.compose.DialogDefaults.dialogInsidePadding
import com.yourssu.handy.compose.DialogDefaults.dialogPadding
import com.yourssu.handy.compose.DialogDefaults.dialogWidth
import com.yourssu.handy.compose.button.BoxButton
import com.yourssu.handy.compose.button.BoxButtonSize
import com.yourssu.handy.compose.button.BoxButtonType
import com.yourssu.handy.compose.foundation.ColorGray070
import com.yourssu.handy.compose.foundation.HandyTypography
import com.yourssu.handy.compose.icons.HandyIcons
import com.yourssu.handy.compose.icons.filled.Close


/**
* OneButtonDialog : 선택 버튼이 하나 있는 Dialog 입니다.
*
* @param title Dialog 제목 text
* @param positiveText 확인 버튼 text
* @param onPositiveClick 확인 버튼 클릭 시 실행되는 함수
* @param onDismiss 닫기(X) 버튼 클릭시 실행되는 함수
* @param description Dialog 안의 설명 text (optional)
* @param content Dialog 안의 content. 주로 이미지가 들어감(optional)
**/
@Composable
fun OneButtonDialog(
title: String,
positiveText: String,
onPositiveClick: () -> Unit,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
description: String = "",
content: @Composable (() -> Unit)? = null,
) {
// Scrim
Box(
modifier = Modifier
.fillMaxSize()
.background(color = ColorGray070)
.clickable(
onClick = onDismiss,
indication = null,
interactionSource = remember { MutableInteractionSource() }
), // 배경 클릭 시 닫기 처리
contentAlignment = Alignment.Center // 중앙 정렬
) {
Box(
modifier = modifier
.background(
color = HandyTheme.colors.bgBasicDefault,
shape = RoundedCornerShape(16.dp)
) //todo Radius.XL 어떻게 활용하는지 모르겠음
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

16.dp 대신 Radius.XL.dp 쓰시면 돼요

.width(dialogWidth)
.padding(dialogPadding),
) {
Column {
Row(
modifier = Modifier.fillMaxWidth(),
) {
Text(
text = title,
style = HandyTypography.T1Sb20,
color = HandyTheme.colors.textBasicPrimary,
maxLines = 3,
modifier = Modifier
.weight(1f)
.padding(end = dialogButtonSpacing)
)

Icon(
imageVector = HandyIcons.Filled.Close,
contentDescription = "Close",
modifier = Modifier.clickable { onDismiss() }
)
}

Spacer(modifier = Modifier.height(dialogInsidePadding))

Text(text = description)

Spacer(modifier = Modifier.height(dialogPadding))

if (content != null) {
Box(
modifier = Modifier
.align(Alignment.CenterHorizontally)
.padding(bottom = dialogPadding)
) {
content()
}
}

BoxButton(
modifier = Modifier.fillMaxWidth(),
text = positiveText,
onClick = { onPositiveClick() },
sizeType = BoxButtonSize.L,
)
}
}
}
}



/**
* TwoButtonDialog : 버튼이 두개 있는 다이알로그 입니다.
*
* @param title Dialog 제목 text
* @param positiveText 확인 버튼 text
* @param negativeText 취소 버튼 text
* @param onPositiveClick 확인 버튼 클릭 시 실행되는 함수
* @param onNegativeClick 취소 버튼 클릭 시 실행되는 함수
* @param onDismiss 닫기(X) 버튼 클릭시 실행되는 함수
* @param description Dialog 안의 설명 text (optional)
* @param content Dialog 안의 content. 주로 이미지가 들어감(optional)
**/
@Composable
fun TwoButtonDialog(
title: String,
positiveText: String,
negativeText: String,
onPositiveClick: () -> Unit,
onNegativeClick: () -> Unit,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
description: String = "",
content: @Composable (() -> Unit)? = null,
) {
// Scrim
Box(
modifier = Modifier
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modifier = Modifier
modifier = modifier

특별한 이유가 있지 않다면 파라미터로 들어오는 modifier는 최상위 컴포저블에만 적용하고 나머지는 파라미터와 독립적으로 적용하는 게 관례예요

.fillMaxSize()
.background(color = ColorGray070)
.clickable(
onClick = onDismiss,
indication = null,
interactionSource = remember { MutableInteractionSource() }
), // 배경 클릭 시 닫기 처리
contentAlignment = Alignment.Center // 중앙 정렬
) {
Box(
modifier = modifier
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modifier = modifier
modifier = Modifier

등등

.background(
color = HandyTheme.colors.bgBasicDefault,
shape = RoundedCornerShape(16.dp)
) //todo Radius.XL 어떻게 활용하는지 모르겠음
.width(dialogWidth)
.padding(dialogPadding),
) {
Column {
Row(
modifier = modifier.fillMaxWidth(),
) {
Text(
text = title,
style = HandyTypography.T1Sb20,
color = HandyTheme.colors.textBasicPrimary,
maxLines = 3,
modifier = Modifier
.weight(1f)
.padding(end = dialogButtonSpacing)
)

Icon(
imageVector = HandyIcons.Filled.Close,
contentDescription = "Close",
modifier = modifier.clickable { onDismiss() }
)
}

Spacer(modifier = modifier.height(dialogInsidePadding))

Text(text = description)

Spacer(modifier = modifier.height(dialogPadding))

if (content != null) {
Box(
modifier
.align(Alignment.CenterHorizontally)
.padding(bottom = dialogPadding)
) {
content()
}
}

Row(
modifier = modifier.align(Alignment.CenterHorizontally)
) {
BoxButton(
modifier = modifier.weight(1f),
text = negativeText,
onClick = { onNegativeClick() },
sizeType = BoxButtonSize.L,
buttonType = BoxButtonType.Secondary
)

Spacer(modifier = modifier.width(dialogButtonSpacing))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Spacer(modifier = modifier.width(dialogButtonSpacing))
Spacer(modifier = Modifier.width(dialogButtonSpacing))


BoxButton(
modifier = modifier.weight(1f),
text = positiveText,
onClick = { onPositiveClick() },
sizeType = BoxButtonSize.L,
)
}
}
}
}
}

object DialogDefaults {
val dialogWidth = 296.dp
val dialogPadding = 20.dp
val dialogInsidePadding = 16.dp
val dialogButtonSpacing = 8.dp
}
Loading