AutoHeightEditor๋ Dynamic Height ๊ธฐ๋ฅ์ด ์๋ ์ปค์คํ
TextEditor ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ ๊ฐ ํ๋ก์ ํธ์ ํ์ํด์ ์ง์ ๊ตฌํํ๊ฒ ๋ ์ปค์คํ
TextEditor์
๋๋ค.
์ ๊ฐ ์งํํ๊ณ ์๋ ํ๋ก์ ํธ์์ ๋์ ์ผ๋ก ๋์ด๊ฐ ์กฐ์ ๋๋ ์
๋ ฅ ์ธํฐํ์ด์ค๊ฐ ์๊ตฌ์ฌํญ์ด์๋๋ฐ, iOS 16๋ถํฐ๋ TextField์ axis ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด Dynamic Height๋ก ๋์ํ๋ ์
๋ ฅ ์ธํฐํ์ด์ค๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํ์ง๋ง ํ๋ก์ ํธ ์ต์ ์ง์๋ฒ์ ์ด iOS 15.0+๋ก ๊ฒฐ์ ๋์๊ณ , ์ฌ๋ฌ ์ค์ ํ
์คํธ ์
๋ ฅ์ ๋ฐ๊ธฐ ์ํด์๋ TextEditor๋ฅผ ์ฌ์ฉํด์ผํ์ต๋๋ค.
๊ธฐ๋ณธ API๋ก ์ ๊ณต๋๋ TextEditor๋ฅผ ์ฌ์ฉํด๋ณด์ ๋ถ๋ค์ ๊ณต๊ฐํ์๊ฒ ์ง๋ง ์ง์ํ๋ ๊ธฐ๋ฅ์ด TextField์ ๋นํด ๋ถ์กฑํ๊ณ , ํนํ ๋ณ๋๋ก ๋์ด๋ฅผ ์ง์ ํด์ฃผ์ง ์์ผ๋ฉด ์ฐจ์งํ ์ ์๋ ์ต๋ ๋์ด๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ์ ์ ํ ๋์ด๋ฅผ ๋์ ์ผ๋ก ๊ณ์ฐํด์ฃผ๋ AutoHeightEditor๋ฅผ ์ปค์คํ
์ผ๋ก ์ ์ํ๊ฒ ๋์์ต๋๋ค.
์์ธํ ์ ์ ๋ฐฐ๊ฒฝ ๋ฐ ๊ตฌํ ๊ณผ์ ์ ๋ธ๋ก๊ทธ์์ ํ์ธํ ์ ์์ต๋๋ค.
AutoHeightEditor๋ ๊ธฐ๋ณธ์ ์ผ๋ก Dynamic Height์ด ๊ฐ์ฅ ํฐ ํน์ง์
๋๋ค.
์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ํฐํธ ๋์ด, ํ๊ฐ, ํ ์คํธ ๊ธธ์ด, ๊ฐํ๋ฌธ์๋ฅผ ํตํด์ ์ ์ ํ ๋์ด๋ก TextEditor์ ๋์ด๋ฅผ ์ค์๊ฐ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
- ํ
์คํธ์์
\n(๊ฐํ๋ฌธ์)์ ๊ฐฏ์๋ฅผ ๊ณ์ฐํฉ๋๋ค. TextEditor์ ๊ฐ๋ก ๊ธธ์ด์ ์ ๋ ฅ๋ ํ ์คํธ์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํด์ ์๋ ์ค๋ฐ๊ฟ์ด ๋ช ๋ฒ ์ผ์ด๋์ผํ๋์ง ๊ณ์ฐํฉ๋๋ค.- 1๋ฒ๊ณผ 2๋ฒ์ ํฉ์ณ์ ์ด ์ค๋ฐ๊ฟ ํ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
- ํฐํธ ํฌ๊ธฐ, ํ๊ฐ, ์ค๋ฐ๊ฟ ์๋ฅผ ๊ณ์ฐํ์ฌ
TextEditor์ ์ด ๋์ด๋ฅผ ๊ณ์ฐํฉ๋๋ค.
์ต์ 1์ค ~ maxLine๊น์ง ์ฌ์ฉ์์ ์ ๋ ฅ์ ๋ฐ๋ผ ๋์ด๊ฐ ๋ณ๊ฒฝ๋๊ณ ์ต๋ ๋ผ์ธ ์, ์ฌ์ฉ๋๋ ํฐํธ, ํ๊ฐ, ํ์ฑํ ์ฌ๋ถ์ ๊ฐ์ ์ ํ์ฌํญ์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ฐ์์ ๋ฐ์ํฉ๋๋ค.
๊ฐ์ธ์ ์ผ๋ก ์ฌ์ฉํ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ง์ถฐ์ ์์ ํ๋งํผ, ์ ๊ฐ ์๋ ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ์ฌ์ฉํ๋ ํ๊ฒฝ์ ๊ณ ๋ คํ์ฌ ์๋ ์ฌํญ๋ค์ ์ถ๊ฐํ์ต๋๋ค.
- isEnabled๋ฅผ ๋ฐ์ธ๋ฉ ๋ฐ์์ ์ธ๋ถ์์ ํ์ฑํ ์ฌ๋ถ ๊ด๋ฆฌ ๊ฐ๋ฅ
- ๊ณ ์ ์ผ๋ก ์กด์ฌํ๋ Border ์คํธ๋กํฌ ์ฌ์ฉ ์ฌ๋ถ ์ ํ ๊ฐ๋ฅ
- Disabled ์๋ด ๋ฌธ๊ตฌ ์ปค์คํ ๊ฐ๋ฅ
- ์ ๋ฌ๋ฐ์ ์ ๊ท์ ๋งค์น ์ฌ๋ถ๋ฅผ ๊ณ์ฐํด์ ๋ฐ์ธ๋ฉ ๋ Bool ๋ณ์์ ๋ฐ์
์ ์ ๋ฐฐ๊ฒฝ์์ ์ค๋ช
ํ ๊ฒ์ฒ๋ผ iOS 16์ ์์ง์ ์ค๋ฌด์ ์ ์ฉํ๊ธฐ ๋ถ๋ด์ค๋ฌ์ด ๋ฒ์ ์ด๊ธฐ ๋๋ฌธ์, ์ด๋ฅผ ๊ณ ๋ คํ์ฌ TextEditor๊ฐ ์ฒ์ ๋์จ iOS 14๋ถํฐ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ๊ตฌํํ์ต๋๋ค.
public init (
text: Binding<String>,
font: Font = .body,
lineSpace: CGFloat = 2,
maxLine: Int,
hasBorder: Bool,
isEnabled: Binding<Bool>,
disabledPlaceholder: String,
regExpUse: RegExpUse
)text: Binding<String>์๋ํฐ์ ๋ฐ์ธ๋ฉ๋๋ ์ ๋ ฅ ํ ์คํธ ๋ฌธ์์ด์ ๋๋ค. ์ธ๋ถ์์ ๋ฐ์ธ๋ฉ์ผ๋ก ์ฃผ์ ํด์ ์ฌ์ฉํฉ๋๋ค.
font: Fontํ
์คํธ์ ์ ์ฉํ ํฐํธ ํ์
์
๋๋ค. Default Value๋ก body๊ฐ ์ฃผ์
๋๊ณ , ์ํ๋ ๋ค๋ฅธ ํฐํธ๊ฐ ์๋ค๋ฉด ์ฃผ์
ํด์ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
lineSpace: CGFloatํ ์คํธ ๋ผ์ธ ์ฌ์ด์ ๋ค์ด๊ฐ๋ ํ ๊ฐ๊ฒฉ์ ๋๋ค. Default Value๋ก 2๊ฐ ์ฃผ์ ๋๊ณ , ์ํ๋ ๋ค๋ฅธ ๊ฐ์ด ์๋ค๋ฉด ์ฃผ์ ํด์ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
maxLine: Int์๋ํฐ์ ๋์ด๊ฐ ์ฆ๊ฐํ๋ ์ํ์ ๋ผ์ธ ์์
๋๋ค. ์
๋ ฅ ๋ผ์ธ์ด ๋์ด๋ ๋ maxLine๊น์ง ์๋ํฐ ๋์ด๊ฐ ์ฆ๊ฐํ๊ณ , ๊ทธ ์ดํ๋ก๋ ๋์ด๋์ง ์์ต๋๋ค.
hasBorder: Bool๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ Stroke์ ์ฌ์ฉ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ๊ธฐ๋ณธ Stroke๋ Gray ์ปฌ๋ฌ์ 20์ CornerRadius ๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
isEnabled: Binding<Bool>์๋ํฐ์ ํ์ฑํ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. ์ธ๋ถ์์ ๋ฐ์ธ๋ฉ์ผ๋ก ์ฃผ์ ํ๊ณ , ์กฐ์ ํด์ ์ฌ์ฉํฉ๋๋ค.
disabledPlaceholder: String์๋ํฐ๊ฐ ๋นํ์ฑํ ๋์ด์์ ๋, ์ฌ์ฉ์์๊ฒ ์๋ดํ๊ธฐ ์ํ ๋ฌธ๊ตฌ์ ๋๋ค.
public enum RegExpUse {
case use(pattern: String, isMatched: Binding<Bool>)
case none
}
regExpUse: RegExpUse์ ๊ท์ ๋งค์น ์ฌ๋ถ๋ฅผ ์ฌ์ฉํ๋์ง๋ฅผ ๊ฒฐ์ ํ๋ ํ์ ์ ๋๋ค.
์ฌ์ฉํ์ง ์์ผ๋ฉด none, ์ฌ์ฉํ๋ค๋ฉด use๋ฅผ ์ ๋ฌํฉ๋๋ค.
pattern์ ๋งค์นญ์ ์ฌ์ฉํ ์ ๊ท์ ํจํด, isMatched๋ ์ธ๋ถ์์ ์ฃผ์
ํ๊ณ ํ์ฉํ ๋ฐ์ธ๋ฉ ๊ฐ์
๋๋ค.
ํ
์คํธ๊ฐ ์
๋ฐ์ดํธ ๋ ๋๋ง๋ค ์ ๊ท์์ ๊ฒ์ฌํด์ isMatched์ ์ ๋ฌ๋ ๋ฐ์ธ๋ฉ ๋ณ์๋ฅผ ์๋์ผ๋ก ์
๋ฐ์ดํธํฉ๋๋ค.
์ฐ์ ๊ธฐ๋ณธ์ ์ธ ๋์์ ํ์ธํด๋ณด๊ธฐ ์ํด AutoHeightEditor๋ฅผ ์ด๊ธฐํ ํด๋ณด๊ฒ ์ต๋๋ค.
์ฒ์์๋ 1์ค ๋์ด๋ก ์์ํ๊ณ , ์ ๋ ฅ๋ ํ ์คํธ์ ๋ฐ๋ผ ์ต๋ 5์ค๊น์ง ๋์ด๊ฐ ๋์ ์ผ๋ก ๋์ด๋ฉ๋๋ค.
\n(๊ฐํ๋ฌธ์)๋ก ์ผ์ด๋๋ ์ค๋ฐ๊ฟ ๋ฟ๋ง ์๋๋ผ, ํ
์คํธ๊ฐ ๊ธธ์ด์ ธ์ ์๋์ผ๋ก ์ค๋ฐ๊ฟ์ด ๋ฐ์ํ๋ ์๊ฐ๋ ๊ฐ์งํด์ ๋์ด์ ๋ฐ์ํฉ๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: true,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
maxLine์ ์กฐ์ ํด์ ์ต๋ ๋์ด ๋ผ์ธ ์๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
์๋ ์์์์๋ 7์ ์ ๋ฌํด์ 7์ค ๋์ด๊น์ง ๋์ด๋๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 7,
hasBorder: true,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
ํ์ฌ ๋ฒ์ ์์๋ SwiftUI์ ๊ธฐ๋ณธ
Fontํ์ ์ ์๋ ๊ฐ์ ์ฌ์ฉ์ด ๋ถ๊ฐํฉ๋๋ค. ํฐํธ์ ์ฌ์ด์ฆ๋ฅผ ๊ตฌํ๊ธฐ ์ํด ๋ด๋ถ์์UIFont์ 1:1 ๋งคํ์ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
font์ lineSpace์๋ ๊ธฐ๋ณธ๊ฐ์ผ๋ก body์ 2๊ฐ ์ ๋ฌ๋๊ณ ์์ต๋๋ค.
์ํ๋ ๊ฐ์ด ์๋ค๋ฉด Default Value ๋์ ์ ์๋ก์ด ๊ฐ์ ์ ๋ฌํ ์ ์์ต๋๋ค.
์๋ ์์์์๋ title2์ 10์ ์ ๋ฌํด์ ํฐํธ ์ฌ์ด์ฆ๋ฅผ ํค์ฐ๊ณ ํ ๊ฐ๊ฒฉ๋ ๋ํ๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
font: .title2,
lineSpace: 10,
maxLine: 5,
hasBorder: true,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
hasBorder๋ฅผ ํตํด ๊ธฐ๋ณธ์ผ๋ก ์ ๊ณต๋๋ ํ
๋๋ฆฌ ์ฌ์ฉ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ Stroke๋ Gray ์ปฌ๋ฌ์ 20์ CornerRadius ๊ฐ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
์๋ ์์์์๋ hasBorder์ ๊ฐ์ false๋ก ์ ๋ฌํ์ฌ ํ
๋๋ฆฌ๋ฅผ ์ญ์ ํด๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: false,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
์ธ๋ถ์์ overlay๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ ๋์์ธ์ ์ปค์คํ
์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
์๋ ์์์์๋ ๊ธฐ๋ณธ ํ ๋๋ฆฌ๋ฅผ ์ญ์ ํ๊ณ , overlay๋ก ์ฌ๊ฐํ ์คํ์ผ์ ํ ๋๋ฆฌ๋ฅผ ๊ทธ๋ ค๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: false,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
.overlay {
Rectangle()
.stroke()
}
isEnabled๋ก ์๋ํฐ์ ํฐ์น ์ด๋ฒคํธ ์์ ์ฌ๋ถ๋ฅผ ์กฐ์ ํ ์ ์์ต๋๋ค.
์ธ๋ถ์์ ๊ด๋ฆฌํ๊ธฐ ์ํด ๋ฐ์ธ๋ฉ์ผ๋ก ์ ๋ฌ๋ฐ์ ์ฌ์ฉํฉ๋๋ค.
disabled๋๋ฉด disabledPlaceholder์ ์ ๋ฌ๋ ํ
์คํธ๋ฅผ ํ๋ ์ด์คํ๋๋ก ํ์ํฉ๋๋ค.
์๋ ์์์์๋ isEnabled์ ๋ณ์๋ฅผ ๋ฐ์ธ๋ฉํ๊ณ , Toggle๋ก ์ธ๋ถ์์ ๊ด๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: ๏ฟฝtrue,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
๋ง์ฝ์ ๋ฐ๋ก ๋นํ์ฑํ ํ๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ฉด .constant()๋ก ์ ๋ฌํ๊ณ , disabledPlaceholder์๋ ๋น ๋ฌธ์์ด์ ์ ๋ฌํ๋ฉด ๋ฉ๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: true,
isEnabled: .constant(true),
disabledPlaceholder: "",
regExpUse: .none)regExpUse ์ด๊ฑฐํ์ผ๋ก ์ ๊ท์ ์ฌ์ฉ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
์ฌ์ฉํ์ง ์๋๋ค๋ฉด none, ์ฌ์ฉํ๋ค๋ฉด use๋ฅผ ์ฃผ์
ํ๋ฉด ๋ฉ๋๋ค.
use์๋ ์ฐ๊ด๊ฐ์ผ๋ก pattern๊ณผ isMatched๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
pattern ํ
์คํธ์ ๋น๊ตํ ์ ๊ท์ ํจํด ๋ฌธ์์ด์
๋๋ค.
isMatched๋ ์ธ๋ถ์์ ๋ฐ์ธ๋ฉ ๋ฐ๋ ๋ณ์๋ก, ๋ด๋ถ์์ ์ ๊ท์ ์ผ์น ์ฌ๋ถ๋ฅผ ์
๋ฐ์ดํธ ๋ฐ์ต๋๋ค.
์๋ ์์์์๋ ์ด๋ฉ์ผ ํจํด์ ์ ๋ฌํด๋ณด๊ฒ ์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: true,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .use(
pattern: #"^[a-zA-Z0-9+-\_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]{2,3}+$"#,
isMatched: $isMatched))
@FocusState๋ฅผ ํจํค์ง ๋ด๋ถ์ ํฌํจ์ํค๋ฉด ์ต์ ์ง์๋ฒ์ ์ด iOS 15๋ก ์ฌ๋ผ๊ฐ๊ธฐ ๋๋ฌธ์ ํฌํจ์ํค์ง ์์์ต๋๋ค.
ํธ๋ ์ด๋ ์คํ๋ฅผ ์๊ฐํด๋ดค์ ๋, ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ฐ๋ ์ฌ์ฉ์ฑ๋ณด๋ค ์ง์ ๋ฒ์ ์ ๋ฎ์ถ๋๊ฒ ๋ ๋ฉ๋ฆฌํธ๊ฐ ์๋ค๊ณ ์๊ฐํ์ต๋๋ค.
ํ๋ก์ ํธ ์ง์ ๋ฒ์ ์ด 15.0+์ธ ์ฌ์ฉ์๋ถ๋ค์ ์ธ๋ถ์์ FocusState๋ฅผ ์ฌ์ฉํด์ ํฌ์ปค์ค๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
AutoHeightEditor(
text: $text,
maxLine: 5,
hasBorder: true,
isEnabled: $isEnabled,
disabledPlaceholder: "This editor has been disabled",
regExpUse: .none)
.focused($isFocus)
ํ์ฌ ๋ฒ์ ์์๋ ๋ด๋ถ foregroundColor์์ primary๋ฅผ ์ ๋ฌํด์ ๊ธฐ๋ณธ์ ์ธ ๋คํฌ๋ชจ๋ ๋์๋ง ์ง์ํ๊ณ ์์ต๋๋ค.
๊ธฐ๋ณธ ์ ๊ณต Stroke ์์์ ๋ผ์ดํธ / ๋คํฌ ๋ชจ๋ gray ๊ณ ์ ์
๋๋ค.
AutoHeightEditor๋ MIT ๋ผ์ด์ผ์ค์ ๋ฒ์ ๋ด์์ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
์์ธํ ์ ๋ณด๋ ๋ผ์ด์ผ์ค์์ ํ์ธํด์ฃผ์ธ์.
์์ฑ์: ์ํ์