Skip to content

Commit 46edfce

Browse files
committed
Make textContainerInset easier to customize
1 parent ef9d357 commit 46edfce

4 files changed

Lines changed: 37 additions & 7 deletions

File tree

Example/Example (Shared)/ContentView.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct ContentView: View {
1313
@State var text2 = ""
1414
@State var text3 = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
1515
@State var text4 = ""
16+
@State var text5 = "I have greater horizontal padding than the others."
1617

1718
var body: some View {
1819
ScrollView {
@@ -73,6 +74,17 @@ struct ContentView: View {
7374
.autocapitalizationType(.none)
7475
}
7576
#endif
77+
ExampleSection("Customized textContentInset") {
78+
ResizingTextView(
79+
text: $text5,
80+
placeholder: ""
81+
)
82+
#if os(macOS)
83+
.textContainerInset(CGSize(width: 40, height: 10))
84+
#elseif os(iOS)
85+
.textContainerInset(UIEdgeInsets(top: 0, left: 40, bottom: 0, right: 40))
86+
#endif
87+
}
7688
}
7789
.scenePadding()
7890
}

Sources/ResizingTextView/ResizingTextView.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ public extension ResizingTextView {
207207
newSelf.font = font
208208
return newSelf
209209
}
210+
211+
func textContainerInset(_ inset: CGSize?) -> Self {
212+
var newSelf = self
213+
newSelf.textContainerInset = inset
214+
return newSelf
215+
}
210216

211217
#elseif os(iOS)
212218
func foregroundColor(_ color: UIColor) -> Self {
@@ -226,5 +232,11 @@ public extension ResizingTextView {
226232
newSelf.autocapitalizationType = autocapitalizationType
227233
return newSelf
228234
}
235+
236+
func textContainerInset(_ inset: UIEdgeInsets?) -> Self {
237+
var newSelf = self
238+
newSelf.textContainerInset = inset
239+
return newSelf
240+
}
229241
#endif
230242
}

Sources/ResizingTextView/TextView (AppKit).swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ struct TextView: NSViewRepresentable {
5252

5353
func makeNSView(context: Context) -> TextEnclosingScrollView {
5454
let textView = CustomTextView()
55-
textView.textContainerInset = textContainerInset
5655
textView.delegate = context.coordinator
5756
textView.isRichText = false
5857
textView.allowsUndo = true
@@ -130,6 +129,9 @@ struct TextView: NSViewRepresentable {
130129
if textView.isSelectable != isSelectable {
131130
textView.isSelectable = isSelectable
132131
}
132+
if textView.textContainerInset != textContainerInset {
133+
textView.textContainerInset = textContainerInset
134+
}
133135
if textView.textContainer?.maximumNumberOfLines != lineLimit {
134136
textView.textContainer?.maximumNumberOfLines = lineLimit
135137
}

Sources/ResizingTextView/TextView (UIKit).swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import UIKit
66

77
struct TextView: UIViewRepresentable {
88
static let defaultForegroundColor = Color(UIColor.label)
9+
10+
/// HACK: In iOS 17, the last sentence of a non-editable text may not be drawn if the textContainerInset is `.zero`. To avoid it, we add this default value to the insets.
11+
private static let defaultTextContainerInset = UIEdgeInsets(top: 0.00000001, left: 0.00000001, bottom: 0.00000001, right: 0.00000001)
912

1013
@Binding private var text: String
1114
private var isEditable: Bool
@@ -17,7 +20,7 @@ struct TextView: UIViewRepresentable {
1720
private var canHaveNewLineCharacters: Bool
1821
private var width: CGFloat?
1922
private var autocapitalizationType: UITextAutocapitalizationType
20-
private var textContainerInset: UIEdgeInsets
23+
private var textContainerInset: UIEdgeInsets?
2124

2225
init(
2326
_ text: Binding<String>,
@@ -31,7 +34,7 @@ struct TextView: UIViewRepresentable {
3134
autocapitalizationType: UITextAutocapitalizationType,
3235
textContainerInset: UIEdgeInsets?
3336
) {
34-
self._text = text
37+
_text = text
3538
self.isEditable = isEditable
3639
self.isScrollable = isScrollable
3740
self.isSelectable = isSelectable
@@ -40,10 +43,7 @@ struct TextView: UIViewRepresentable {
4043
self.font = font
4144
self.canHaveNewLineCharacters = canHaveNewLineCharacters
4245
self.autocapitalizationType = autocapitalizationType
43-
44-
// HACK: In iOS 17, the last sentence of a non-editable text may not be drawn if the textContainerInset is `.zero`. To avoid it, we add this default value to the insets.
45-
let defaultTextContainerInset = UIEdgeInsets(top: 0.00000001, left: 0.00000001, bottom: 0.00000001, right: 0.00000001)
46-
self.textContainerInset = textContainerInset ?? defaultTextContainerInset
46+
self.textContainerInset = textContainerInset
4747
}
4848

4949
func makeUIView(context: Context) -> CustomTextView {
@@ -84,6 +84,10 @@ struct TextView: UIViewRepresentable {
8484
if view.autocapitalizationType != autocapitalizationType {
8585
view.autocapitalizationType = autocapitalizationType
8686
}
87+
let textContainerInset = textContainerInset ?? Self.defaultTextContainerInset
88+
if view.textContainerInset != textContainerInset {
89+
view.textContainerInset = textContainerInset
90+
}
8791
if lineLimit > 0 {
8892
if view.textContainer.lineBreakMode != .byTruncatingTail {
8993
view.textContainer.lineBreakMode = .byTruncatingTail

0 commit comments

Comments
 (0)