Reputation: 1513
I have a List
row that, in some cases, shows a TextField
(depending on a switch
condition).
I managed to solve the focus problem with an excellent article from Peter Friese Link to article that suggests a very clever use of enums
Associated fields.
BUT I'm facing an inconsistent scrolling behavior 😥 that can be seen in this screen capture:
List($roundQuestions) { $question in
HStack {
Group {
Image(systemName: "\(question.index ).circle")
.foregroundColor(questionColor(question: question))
.scaleEffect(0.6)
Text("\(question.factorA)")
Text("x")
question.status == .unrevealed ? Text("?") : Text("\(question.factorB)")
Text("=")
switch question.status {
case .unrevealed:
if question.index == currentQuestionArrayIndex + 1 {
Spacer()
Button("Go!") {
question.status = .active
}
.buttonStyle(.borderedProminent)
.font(.none)
.lineLimit(1)
}
case .active:
ZStack (alignment: .trailing) {
TextField("??", text: $questionGuess )
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.focused($focusedQuestion, equals: .row(id: question.id))
.onAppear {
focusedQuestion = .row(id: question.id)
print("onAppear question.id = \(question.index)")
}
.onDisappear {
print("onDisappear question.id = \(question.index)")
}
}
Button("?") {
processUserGuess()
}
.buttonStyle(.borderedProminent)
.font(.none)
case .error:
Text("\(question.productGuess)").foregroundColor(.red)
case .right:
Text("\(question.productGuess)").foregroundColor(.green)
default:
Text("__")
}
}
.font(.custom("SF Compact", size: 40, relativeTo: .largeTitle))
.padding(.vertical)
}
}
https://github.com/gilsoncav/tabulenzo
I'm aware of solution paths like Move TextField up when the keyboard has appeared in SwiftUI but they seem "hacky" and the code doesn't "read well" in my opinion
I'm a Swift, native iOS and SwiftUI newbie. 🤗
Upvotes: 1
Views: 2399
Reputation: 12125
There is another option, but it uses ScrollView
instead of List
, and then facilitates ScrollViewReader
to scroll to the active question. It works, but you would have to do some custom formatting to get the same look as before (I already added some Spacers to get the overall look):
// Scrollview & reader instead of List
ScrollViewReader { scrollProxy in
ScrollView {
ForEach($roundQuestions) { $question in
HStack {
Group {
Image(systemName: "\(question.index ).circle")
.foregroundColor(questionColor(question: question))
.scaleEffect(0.6)
Text("\(question.factorA)")
Text("x")
question.status == .unrevealed ? Text("?") : Text("\(question.factorB)")
Text("=")
switch question.status {
case .unrevealed:
if question.index == currentQuestionArrayIndex + 1 {
Spacer()
Button("Go!") {
question.status = .active
}
.buttonStyle(.borderedProminent)
.font(.none)
.lineLimit(1)
} else {
Spacer()
}
case .active:
HStack {
TextField("??", text: $questionGuess )
.textFieldStyle(.roundedBorder)
.keyboardType(.numberPad)
.focused($focusedQuestion, equals: .row(id: question.id))
.onAppear {
focusedQuestion = .row(id: question.id)
// NEW: Scroll to active question
withAnimation {
scrollProxy.scrollTo(question.id, anchor: .bottom)
}
}
}
Button("?") {
processUserGuess()
}
.buttonStyle(.borderedProminent)
.font(.none)
case .error:
Text("\(question.productGuess)").foregroundColor(.red)
Spacer()
case .right:
Text("\(question.productGuess)").foregroundColor(.green)
Spacer()
default:
Text("__")
Spacer()
}
}
.font(.custom("SF Compact", size: 40, relativeTo: .largeTitle))
.padding(.vertical)
}
// new: id for scrollto
.id(question.id)
}
}
}
Upvotes: 2