1

我正在编写一个 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嵌入的 a 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)
    }
}

如果意图是使用按钮来实现滚动操作,则此方法有效。

我的问题是:是否可以在模型更新时触发上面的滚动操作,而无需单击按钮。

任何帮助或指示将不胜感激。

谢谢。

4

2 回答 2

0

ScrollViewReader 是您正在寻找的解决方案。您可能需要玩弄价值。您还需要将.id(0)修饰符添加到您的文本视图。

ScrollView {
    ScrollViewReader { reader in 
        Button("Go to first then anchor trailing.") {
                    value.scrollTo(0, anchor: .trailing)
                }
      // The rest of your code .......
于 2021-11-13T14:42:51.057 回答
0

我假设你想要这个:

ScrollViewReader { scrollView in
    VStack {
        ScrollView(.horizontal) {
            Text(model.combinedString)
                .id("combinedText")
        }
        .onChange(of: model.combinedString) {     // << here !!
            withAnimation {
                scrollView.scrollTo("combinedText", anchor: .trailing)
            }
        }
    }
}
于 2021-11-13T15:27:28.927 回答