[Jetpack Compose] Text and typography (1) — Text 그리기

이영영
13 min readJan 5, 2024

--

컴포즈를 처음 입문했습니다..

코드랩으로 무작정 따라하기는 했지만 각 컴포넌트의 사용법을 알아야할 것 같아 Text 를 사용하는 방법과 여러 속성들을 공식문서에 따라 정리해보겠습니다.

아래와같은 함수 형태에서 Row를 한줄씩 추가해가며 어떻게 노출되는지 Preview로 보았습니다. 파라미터로 넘겨지는 text 는 “Hello” 입니다.

@Preview(widthDp = 400, showBackground = true, backgroundColor = 0xFFEAEAEA)
@Composable
fun TextStylePreview() {
TextStyle(text = "Hello")
}

@Composable
fun TextStyle(text: String) {
Column {
Row {
...
}

Row {
...
}

...
}
}
preview

DisplayText

Text() 기본

Row {
Text("일반: ")
Text(text)
}

스트링 리소스 가져오기 | text = stringResource(R.string.id)

Row {
Text("stringResource: ")
Text(stringResource(R.string.hello))
}

Style text

텍스트 색상 | color = Color.___

Row {
Text("color: ")
Text(text, color = Color.Blue)
}

폰트 크기 | fontSize = __.sp __.em

  • dp는 타입에러가 발생한다.
Row {
Text("fontSize: ")
Text(text, fontSize = 30.sp)
}

폰트 스타일 | fontStyle = FontStyle.___

Row {
Text("fontStyle - Italic: ")
Text(text, fontStyle = FontStyle.Italic)
}

폰트 두께 | fontWeight = FontWeight.___

Row {
Text("fontWeight - Bold: ")
Text(text, fontWeight = FontWeight.Bold)
}

그림자 | TextStyle(shadow = Shadow(color, offset, blurRadius))

  • textStyle에서 fontSize를 지정할 수도 있다.
Row {
Text("shadow - TextStyle: ")
Text(
text = text,
style = TextStyle(
fontSize = 24.sp,
shadow = Shadow(
color = Color.Blue,
offset = Offset(50.0f, 10.0f),
blurRadius = 3f
)
)
)
}

한 개의 Text composable에 스타일 여러개 적용 | buildAnnotatedString, withStyle, append

  • 같은 Text composable에 다른 스타일들을 적용하려면 AnnotatedString 을 사용하면 된다.
  • buildAnnotatedString을 이용하여 AnnotatedString을 쉽게 만들 수 있다.
  • append를 이용하여 다른 스타일들을 차례로 이어붙인다.

withStyle(style = SpanStyle(…))

  • SpanStyle로 fontWeight, color 등 개별 스타일을 생성한다.
  • withStyle로 스타일을 적용한다.
  • append 내부의 문자열에 적용된다.
Row {
Text("buildAnnotatedString, withStyle - SpanStyle: ")
Text(
buildAnnotatedString {
withStyle(style = SpanStyle(color = Color.Blue)) {
append("H")
}

append("ELL")

withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
append("O")
}
}
)
}

Brush 사용하여 고급 스타일 표현하기 | TextStyle(brush = Brush.___)

  • 주의: Brush API는 현재 experimental. 변경될 수 있다.
  • TextStyle, SpanStyle 모두 brush를 사용할 수 있다.
val gradientColors = listOf(Cyan, Magenta, Yellow)

Row {
Text("brush - linearGradient: ")
Text(text, style = TextStyle(
brush = Brush.linearGradient(colors = gradientColors)
))
}
Cyan, Magenta, Yellow 선형 그라디언트 적용
val gradientColors = listOf(Cyan, Magenta, Yellow)

Row {
Text("brush - spanStyle: ")
Text(
buildAnnotatedString {
append("Do not allow people to dim your shine\n")

withStyle(style = SpanStyle(
brush = Brush.linearGradient(colors = gradientColors)
)) {
append("because the are blinded.\n")
}

append("Tell them to put some sunglasses on.")
}
)
}
SpanStyle로 두번째줄에만 그라디언트 스타일 적용

텍스트 투명도 | SpanStyle(alpha = __f)

val gradientColors = listOf(Cyan, Magenta, Yellow)

Row {
Text("alpha: ")
Text(
buildAnnotatedString {
withStyle(style = SpanStyle(
brush = Brush.linearGradient(colors = gradientColors),
alpha = .5f
)) {
append("Text in")
}

withStyle(style = SpanStyle(
brush = Brush.linearGradient(colors = gradientColors),
alpha = 1f
)) {
append("Compose ❤️")
}
}
)
}

Style paragraph

텍스트정렬 | textAlign = TextAlign.___

  • 언어 특성에 따라 default 방향이 달라진다.
  • 왼쪽에서 오른쪽으로 읽는 언어는 왼쪽이 디폴트 (라틴어, 한글 등)
  • 오른쪽에서 왼쪽으로 읽는 언어는 오른쪽이 디폴트 (아랍어, 히브리어 등)
  • alignment를 변경하고싶다면, Left, Right 대신에 Start, End 를 사용하도록 한다. Left, Right는 언어 특성이 반영되지 않는 무조건 왼쪽/오른쪽 정렬이다.

언어 특성이라는 말에 대한 예시입니다. 아랍어는 오른쪽에서 왼쪽으로 읽는 언어이기 때문에 오른쪽정렬이 default입니다. 그래서 TextAlign.End 를 적용하면 반대인 왼쪽정렬이 됩니다.
만약 TextAlign.Right를 했다면 무조건 오른쪽정렬이 됩니다. 이는 일반적으로 쌍으로 생각하는 End-Right가 서로 다른방향으로 정렬된다는 것을 의미합니다.

  • Note: Text alignment는 layout alignment(Row, Column)과 다르다.
Row {
Text("textAlign - Center: ")
Text(text, textAlign = TextAlign.Center, modifier = Modifier.width(150.dp))
}

문단에 스타일 여러개 적용 | buildAnnotatedString, withStyle, ParagraphStyle

withStyle(style = ParagraphStyle(…))

  • 문단단위로 스타일을 적용한다.
  • 문단은 \n 줄바꿈이 기준이 된다.
  • text alignment, text direction, line height, text intent 스타일을 적용할 수 있다.
Row {
Text("buildAnnotatedString, withStyle - SpanStyle: ")
Text(
buildAnnotatedString {
withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
withStyle(style = SpanStyle(color = Color.Blue)) {
append("H\n")
}

append("ELL\n")

withStyle(
style = SpanStyle(
fontWeight = FontWeight.Bold,
color = Color.Red
)
) {
append("O")
}
}
}
)
}
ParagraphStyle에 선언한 lineHeight가 \n을 기준으로 문단마다 적용됨

텍스트 라인 높이와 패딩 조정 | TextStyle(lineHeight, platformStyle, lineHeightStyle)

  • includeFontPadding은 텍스트의 가장 첫번째줄의 top padding과 가장 마지막줄의 bottom padding을 추가하는 레거시 속성이다.
  • 컴포즈 1.2.0에서 기본값은 true이다. 하지만, PlatformTextStyle를 사용해서 eincludeFontPadding을 false로 세팅하는것을 추천한다. 미래의 컴포즈 릴리즈 버전에는 기본값을 false로 변경하는것이 목표라고 한다.
  • lineHeight는 Q부터 제공하던 기존옵션으로, 컴포즈에서도 LineHeightStyle API를 사용할 수 있다.
  • LineHeightStyle.Alignment로 lineHeight내에서 텍스트의 정렬 위치를 지정할 수 있다.
  • LineHeightStyle.Trim으로 공백을 제거할 수 있다.
  • Alignment, Trim 모두 includeFontPadding이 false로 설정되어있어야 적용된다.
  • 정밀도 향상을 원한다면 sp 대신에 em을 사용할 수 있다.
Row {
Text("lineHeightStyle: ")
Text(text, style = LocalTextStyle.current.merge(
TextStyle(
lineHeight = 4.0.em,
platformStyle = PlatformTextStyle(
includeFontPadding = false
),
lineHeightStyle = LineHeightStyle(
alignment = LineHeightStyle.Alignment.Center,
trim = LineHeightStyle.Trim.None
)
)
))
}
4.0.em lineHeight에 텍스트가 Center에 위치하며, 공백 제거는 하지 않음

LineHeightStyle.Alignment

  • Top, Bottom, Center, Proportional

LineHeightStyle.Trim

  • None: 공백 제거하지 않음
  • Both: 첫번째줄 Top, 마지막줄 Bottom 공백 제거
  • FirstLineTop: 첫번째줄 Top 공백 제거
  • LastLineBottom: 마지막줄 Bottom 공백 제거

Configure text layout

최대 라인수 제한 | maxLines

Row {
Text("maxLine: ")
Text(text.repeat(50), maxLines = 2)
}

마지막 라인 끝 말줄임표 | overflow = TextOverflow.___

Row {
Text("maxLine, overflow: ")
Text(text.repeat(50), maxLines = 2, overflow = TextOverflow.Ellipsis)
}

텍스트를 뷰에 그릴 때 사용되는 여러 속성들에 대한 정리는 여기까지입니다. 단순 Text 클래스 하나에도 정말 많은 속성이 있는 것 같습니다. 😲

--

--