I'm building essentially a memorization app, where tapping a button on the keyboard takes the next word from a predetermined string, and adds it to the outputted text as shown below:
struct TypingGameView: View {
@State var text: String = "Some text that wraps at the incorrect spot and is quite annoying."
@State var outputText: String = ""
@State private var enteredText: String = ""
@State private var wordsTapped = 0
var body: some View {
ZStack {
TextField("", text: $enteredText)
.onChange(of: enteredText) { newValue in
addToOutputText(newValue)
}
Rectangle()
.foregroundColor(.white)
VStack {
Text(outputText)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
Spacer()
}
}
}
func addToOutputText(_ val: String) {
let words = text.components(separatedBy: " ")
for (index, word) in words.enumerated() {
if index == wordsTapped {
outputText += "\(word) "
wordsTapped += 1
return
}
}
}
}
The problem is, the last word of the first line jumps to the next line only if there is one other word after it, but then jumps back to the first line once there are more words after that. See below:
To the best of my knowledge, this is an automatic feature of the Text
view in SwiftUI to prevent there being any orphaned words. I want to disable this as it makes the words jump around in the view I've created. I've seen solutions with using a CATextLayer
in UIKit (see UILabel and UITextView line breaks don't match and Get each line of text in a UILabel), but I need something that works with SwiftUI @State
wrappers and would prefer a solution that uses all SwiftUI. End goal is to get same functionality as in above video, but with no automatic orphan fixing.
Edit: Just tried using Group
with individual Text
views inside for each word. Still does the same thing :/