はじめに
本記事では、wordJoinerを使って、SwiftUIのText()の文字を変な位置で改行させないようにする方法をご紹介します。
環境
- Xcode 15.2
- iOS 17.2
発生した課題
SwiftUIのTextを表示した時に、左詰めで文字が表示されず、変な位置で改行されていました。
現状: ボヘミア\nン・ラプソデ
しかし、理想とする改行の位置はこちら
理想: ボヘミアン\n・ラプソデ
(正式名称は、ボヘミアン・ラプソディですが、文字数の都合上、「ィ」は省略)
実装(before)
また、実装は下記の通りです。
ZStackでRoundedRectangleの上にTextを載せています。
frameを決めて、そのframe幅におさまるようにテキストを表示しています。
struct SampleView: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(Color.gray)
Text("ボヘミアン・ラプソデ")
}
.frame(width: 96, height: 96)
}
}
#Preview {
SampleView()
}
原因
あくまで予想ですが、「・」が行の先頭に配置されないように、内部で調整されていると考えました。
実際に、文字の改行パターンを調査しました。
「・」を消して「ラ」を追加した時のケース
「ラ」を追加すると、左詰めで表示される。
ひらがなのケース
ひらがなも同様に「・」が先頭に配置されないように改行されてしまいます。
解決策
前提
今回の要件は下記の通りです。
- 「・」の有無関係なく、文字が左詰めになっていること
- どんな文字が入っても問題なく表示できること
wordJoinerを使う
そこで今回は、wordJoinerというものを使います。
単語結合子は、Unicodeの制御文字の一つです。
単語の途中など改行してほしくない箇所に単語結合子を入れることで、その場所では改行されなくなります。
イメージ: let string = "ボ" + "\u{2060}" + "ヘ" + "\u{2060}" + "ミ" ...
実装(after)
今回は、stringの拡張として、メソッド化しました。
characters.joined(separator: wordJoiner)
で全ての文字の間にwordJoinerを追加しています。
private extension String {
// 全ての単語の間に Unicode WORD JOINER を挿入する
func insertWordJoiners() -> String {
let wordJoiner = "\u{2060}"
let characters = self.map { String($0) }
let modifiedString = characters.joined(separator: wordJoiner)
return modifiedString
}
}
struct WordJoinerSampleView: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundStyle(Color.gray)
Text("ボヘミアン・ラプソデ".insertWordJoiners())
}
.frame(width: 96, height: 96)
}
}
#Preview {
WordJoinerSampleView()
}
結果
無事に左詰めで改行されました。
おわりに
他により良い方法などがあればコメントいただけると幸いです。