JetpackCompose의 AlertDialog에서 시간을 녹였다.
18273 단어 안드로이드JetpackComposeKotlin
정리하면
무슨 실패?
텍스트 입력 대화 상자를 AlertDialog
를 사용하여 만들면 레이아웃이 무너질 수 있습니다.
@Composable
fun MyDialog4(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
AlertDialog(
onDismissRequest = onDismiss,
text = {
TextField(
value = text,
onValueChange = setText,
modifier = Modifier.padding(32.dp),
)
},
confirmButton = { ... },
)
}
환경
@Composable
fun MyDialog4(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
AlertDialog(
onDismissRequest = onDismiss,
text = {
TextField(
value = text,
onValueChange = setText,
modifier = Modifier.padding(32.dp),
)
},
confirmButton = { ... },
)
}
Arctic Fox 2020.3.1 RC 1
1.5.10
1.0.0-rc02
왜 일어났어?
이 레이아웃 붕괴가 발생한 원인을 탐구하기 위해 AlertDialog의 내용을 살펴 보겠습니다.
그러면 ColumnScope.AlertDialogBaselineLayout
에 도착합니다.
여기에서는 받은 제목과 텍스트를 배치합니다.
@Composable
internal fun ColumnScope.AlertDialogBaselineLayout(
title: @Composable (() -> Unit)?,
text: @Composable (() -> Unit)?
) {
Layout(
{
title?.let { title ->
Box(...) {
title()
}
}
text?.let { text ->
Box(...) {
text()
}
}
},
Modifier.weight(1f, false)
) { measurables, constraints ->
val titlePlaceable = measurables.firstOrNull { it.layoutId == "title" }?.measure(
constraints.copy(minHeight = 0)
)
val textPlaceable = measurables.firstOrNull { it.layoutId == "text" }?.measure(
constraints.copy(minHeight = 0)
)
// このあたりでタイトルとテキストの位置を計算
...
layout(layoutWidth, layoutHeight) {
titlePlaceable?.place(0, titlePositionY)
textPlaceable?.place(0, textPositionY)
}
}
}
보다 자세하게 살펴보면, 타이틀·텍스트 각각에 대해, 베이스 라인을 보면서 세로 방향의 위치 결정을 하고 있습니다(가로 방향은 단순하기 때문에 본고에서는 할애)
세세한 내용은 실제 코드를 읽을 수 있다고 생각하지만, 여기서 중요한 점은 기준선의 위치가 특정 위치에 오도록 배치하고 있다는 것입니다. (특정 위치는 sp 의존의 고정값)
// Place the title so that its first baseline is titleOffset from the top
val titlePositionY = titleOffset - firstTitleBaseline
이것을 모르면 몇 가지 문제가 발생할 수 있습니다.
top 방향의 padding이 효과가 없다
기준선의 위치를 특정 위치에 맞추려고하기 때문에 top에 padding을 지정해도 효과가 없습니다.
또한 큰 값을 넣으면 텍스트 자체가 무너집니다.
pad =
0
16
28
@Composable
fun MyDialog5(onDismiss: () -> Unit) {
val pad = // 表中の値
AlertDialog(
onDismissRequest = onDismiss,
title = null,
text = {
Text(text = "MyDialog5", modifier = Modifier.padding(top = pad.dp))
},
confirmButton = { CancelButton(onDismiss) },
)
}
Text와 TextField에서 차이가 발생합니다.
Text
와 TextField
에서는 상단에서 기준선까지의 거리가 다릅니다.
따라서 단순히 배치하는 것만으로도 어긋남이 발생합니다.
텍스트
TextField
@Composable
fun MyDialog2(onDismiss: () -> Unit) {
AlertDialog(
onDismissRequest = onDismiss,
title = null,
text = { Text(text = "MyDialog2") },
confirmButton = { CancelButton(onDismiss) },
)
}
@Composable
fun MyDialog3(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
AlertDialog(
onDismissRequest = onDismiss,
text = { TextField(value = text, onValueChange = setText) },
confirmButton = { CancelButton(onDismiss) },
)
}
해결안
해결책으로는 다음과 같은 예를 생각할 수 있습니다.
Dialog 사용
직접 Dialog에서 구현합니다.
방금 실제로 AlertDialog의 내용을 본 사람은 알 수 있다고 생각합니다.
제목 등을 배치하는 경우, AlertDialog 로 설정되어 있던 alpha 나 textStyle 에 대해서도 스스로 설정할 필요가 있는 것에 주의합니다
@Composable
fun MyDialog6(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
Dialog(onDismissRequest = onDismiss) {
Surface {
Column {
TextField(
value = text,
onValueChange = setText,
modifier = Modifier.padding(32.dp),
)
Box(
modifier = Modifier
.fillMaxWidth()
.padding(all = 8.dp),
) {
CancelButton(
onClick = onDismiss,
modifier = Modifier
.align(Alignment.BottomEnd),
)
}
}
}
}
}
대화상자 사용 안함
해결책이라고는 말할 수 없을지도 모르지만, 처음에는 대화가 필요합니까?
복잡한 UI가 필요하다면 대화의 생각에서 벗어나 일반 화면에 배치하는 것도 손 중 하나입니다.
또, 다이얼로그는 유저의 조작을 블록하는 UI 이며, 그 이용에는 신중하게 할 필요가 있습니다
참고 링크
공식 문서
머티리얼 디자인 가이드라인
이번에 작성한 샘플 프로젝트, 대화 상자는 여기
Reference
이 문제에 관하여(JetpackCompose의 AlertDialog에서 시간을 녹였다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/warahiko/items/d8d31b8eb0ee79ae6b4c
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
@Composable
internal fun ColumnScope.AlertDialogBaselineLayout(
title: @Composable (() -> Unit)?,
text: @Composable (() -> Unit)?
) {
Layout(
{
title?.let { title ->
Box(...) {
title()
}
}
text?.let { text ->
Box(...) {
text()
}
}
},
Modifier.weight(1f, false)
) { measurables, constraints ->
val titlePlaceable = measurables.firstOrNull { it.layoutId == "title" }?.measure(
constraints.copy(minHeight = 0)
)
val textPlaceable = measurables.firstOrNull { it.layoutId == "text" }?.measure(
constraints.copy(minHeight = 0)
)
// このあたりでタイトルとテキストの位置を計算
...
layout(layoutWidth, layoutHeight) {
titlePlaceable?.place(0, titlePositionY)
textPlaceable?.place(0, textPositionY)
}
}
}
// Place the title so that its first baseline is titleOffset from the top
val titlePositionY = titleOffset - firstTitleBaseline
@Composable
fun MyDialog5(onDismiss: () -> Unit) {
val pad = // 表中の値
AlertDialog(
onDismissRequest = onDismiss,
title = null,
text = {
Text(text = "MyDialog5", modifier = Modifier.padding(top = pad.dp))
},
confirmButton = { CancelButton(onDismiss) },
)
}
@Composable
fun MyDialog2(onDismiss: () -> Unit) {
AlertDialog(
onDismissRequest = onDismiss,
title = null,
text = { Text(text = "MyDialog2") },
confirmButton = { CancelButton(onDismiss) },
)
}
@Composable
fun MyDialog3(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
AlertDialog(
onDismissRequest = onDismiss,
text = { TextField(value = text, onValueChange = setText) },
confirmButton = { CancelButton(onDismiss) },
)
}
해결책으로는 다음과 같은 예를 생각할 수 있습니다.
Dialog 사용
직접 Dialog에서 구현합니다.
방금 실제로 AlertDialog의 내용을 본 사람은 알 수 있다고 생각합니다.
제목 등을 배치하는 경우, AlertDialog 로 설정되어 있던 alpha 나 textStyle 에 대해서도 스스로 설정할 필요가 있는 것에 주의합니다
@Composable
fun MyDialog6(onDismiss: () -> Unit) {
val (text, setText) = remember { mutableStateOf("") }
Dialog(onDismissRequest = onDismiss) {
Surface {
Column {
TextField(
value = text,
onValueChange = setText,
modifier = Modifier.padding(32.dp),
)
Box(
modifier = Modifier
.fillMaxWidth()
.padding(all = 8.dp),
) {
CancelButton(
onClick = onDismiss,
modifier = Modifier
.align(Alignment.BottomEnd),
)
}
}
}
}
}
대화상자 사용 안함
해결책이라고는 말할 수 없을지도 모르지만, 처음에는 대화가 필요합니까?
복잡한 UI가 필요하다면 대화의 생각에서 벗어나 일반 화면에 배치하는 것도 손 중 하나입니다.
또, 다이얼로그는 유저의 조작을 블록하는 UI 이며, 그 이용에는 신중하게 할 필요가 있습니다
참고 링크
공식 문서
머티리얼 디자인 가이드라인
이번에 작성한 샘플 프로젝트, 대화 상자는 여기
Reference
이 문제에 관하여(JetpackCompose의 AlertDialog에서 시간을 녹였다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/warahiko/items/d8d31b8eb0ee79ae6b4c
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(JetpackCompose의 AlertDialog에서 시간을 녹였다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/warahiko/items/d8d31b8eb0ee79ae6b4c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)