如何让 SwiftUI 中的水平滚动视图在更新封闭文本时自动滚动到结束
How to get a horizontal ScrollView in SwiftUI to scroll automatically to end when the enclosed Text is updated
我正在编写一个 SwiftUI iOS 应用程序,我需要一个 Text
视图来在内容更新时自动滚动到其内容的末尾。更新发生在模型中。为了不让这个问题与我的应用程序的细节复杂化,我创建了一个简单的场景,其中我有两个文本字段和一个文本标签。在文本字段中输入的任何文本都会连接起来并显示在文本标签中。文本标签包含在水平 ScrollView
中,如果文本长于屏幕宽度,可以手动滚动。我想要实现的是每当标签更新时文本自动滚动到末尾。
这里是简单的模型代码:
class Model: ObservableObject {
var firstString = "" {
didSet { combinedString = "\(firstString). \(secondString)." }
}
var secondString = "" {
didSet { combinedString = "\(firstString). \(secondString)." }
}
@Published var combinedString = ""
}
这是内容视图:
struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack(alignment: .leading, spacing: 10) {
TextField("First string: ", text: $model.firstString)
TextField("Second string: ", text: $model.secondString)
Spacer().frame(height: 20)
Text("Combined string:")
ScrollView(.horizontal) {
Text(model.combinedString)
}
}
}
}
根据我所做的研究,我发现无需手动滚动到文本末尾的唯一方法是向视图添加一个按钮,这会导致标签中的文本滚动到末尾。
上面的 ScrollView
嵌入了一个 ScrollViewReader
,带有一个按钮来实现滚动操作。
ScrollViewReader { scrollView in
VStack {
ScrollView(.horizontal) {
Text(model.combinedString)
.id("combinedText")
}
Button("Scroll to end") {
withAnimation {
scrollView.scrollTo("combinedText", anchor: .trailing)
}
}
.padding()
.foregroundColor(.white)
.background(Color.black)
}
}
这可行,前提是要使用按钮来实现滚动操作。
我的问题是:是否可以在模型更新时触发上面的滚动动作,而不需要点击按钮。
任何帮助或指点将不胜感激。
谢谢。
ScrollViewReader 是您正在寻找的解决方案。您可能需要尝试一下这个值。此外,您还需要将 .id(0)
修饰符添加到您的文本视图中。
ScrollView {
ScrollViewReader { reader in
Button("Go to first then anchor trailing.") {
value.scrollTo(0, anchor: .trailing)
}
// The rest of your code .......
我假设你想要这个:
ScrollViewReader { scrollView in
VStack {
ScrollView(.horizontal) {
Text(model.combinedString)
.id("combinedText")
}
.onChange(of: model.combinedString) { // << here !!
withAnimation {
scrollView.scrollTo("combinedText", anchor: .trailing)
}
}
}
}
我正在编写一个 SwiftUI iOS 应用程序,我需要一个 Text
视图来在内容更新时自动滚动到其内容的末尾。更新发生在模型中。为了不让这个问题与我的应用程序的细节复杂化,我创建了一个简单的场景,其中我有两个文本字段和一个文本标签。在文本字段中输入的任何文本都会连接起来并显示在文本标签中。文本标签包含在水平 ScrollView
中,如果文本长于屏幕宽度,可以手动滚动。我想要实现的是每当标签更新时文本自动滚动到末尾。
这里是简单的模型代码:
class Model: ObservableObject {
var firstString = "" {
didSet { combinedString = "\(firstString). \(secondString)." }
}
var secondString = "" {
didSet { combinedString = "\(firstString). \(secondString)." }
}
@Published var combinedString = ""
}
这是内容视图:
struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
VStack(alignment: .leading, spacing: 10) {
TextField("First string: ", text: $model.firstString)
TextField("Second string: ", text: $model.secondString)
Spacer().frame(height: 20)
Text("Combined string:")
ScrollView(.horizontal) {
Text(model.combinedString)
}
}
}
}
根据我所做的研究,我发现无需手动滚动到文本末尾的唯一方法是向视图添加一个按钮,这会导致标签中的文本滚动到末尾。
上面的 ScrollView
嵌入了一个 ScrollViewReader
,带有一个按钮来实现滚动操作。
ScrollViewReader { scrollView in
VStack {
ScrollView(.horizontal) {
Text(model.combinedString)
.id("combinedText")
}
Button("Scroll to end") {
withAnimation {
scrollView.scrollTo("combinedText", anchor: .trailing)
}
}
.padding()
.foregroundColor(.white)
.background(Color.black)
}
}
这可行,前提是要使用按钮来实现滚动操作。
我的问题是:是否可以在模型更新时触发上面的滚动动作,而不需要点击按钮。
任何帮助或指点将不胜感激。
谢谢。
ScrollViewReader 是您正在寻找的解决方案。您可能需要尝试一下这个值。此外,您还需要将 .id(0)
修饰符添加到您的文本视图中。
ScrollView {
ScrollViewReader { reader in
Button("Go to first then anchor trailing.") {
value.scrollTo(0, anchor: .trailing)
}
// The rest of your code .......
我假设你想要这个:
ScrollViewReader { scrollView in
VStack {
ScrollView(.horizontal) {
Text(model.combinedString)
.id("combinedText")
}
.onChange(of: model.combinedString) { // << here !!
withAnimation {
scrollView.scrollTo("combinedText", anchor: .trailing)
}
}
}
}