Lea*_*par 20 foreach scroll scrollview swiftui swiftui-list
我的问题是我(在 SwiftUI 中)有一个 ScrollView,里面有一个 foreach。知道 foreach 何时加载我的所有条目,我希望最后一个条目得到关注。
我做了一些谷歌研究,但我没有找到任何答案。
ScrollView {
VStack {
ForEach (0..<self.entries.count) { index in
Group {
Text(self.entries[index].getName())
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ene*_*nso 42
根据Apple的文档ScrollViewReader,它应该包裹滚动视图,而不是嵌套在其中。
苹果文档中的示例:
@Namespace var topID
@Namespace var bottomID
var body: some View {
ScrollViewReader { proxy in
ScrollView {
Button("Scroll to Bottom") {
withAnimation {
proxy.scrollTo(bottomID)
}
}
.id(topID)
VStack(spacing: 0) {
ForEach(0..<100) { i in
color(fraction: Double(i) / 100)
.frame(height: 32)
}
}
Button("Top") {
withAnimation {
proxy.scrollTo(topID)
}
}
.id(bottomID)
}
}
}
func color(fraction: Double) -> Color {
Color(red: fraction, green: 1 - fraction, blue: 0.5)
}
Run Code Online (Sandbox Code Playgroud)
另一篇文章还展示了如何使用ScrollViewReader元素来包装List,这也很方便。文章中的代码示例:
ScrollViewReader { scrollView in
List {
ForEach(photos.indices) { index in
Image(photos[index])
.resizable()
.scaledToFill()
.cornerRadius(25)
.id(index)
}
}
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
对我来说,使用value.scrollTo(entries.count - 1)不起作用。此外,value.scrollTo(entries.last?.id)在我使用视图修饰符之前,使用也不起作用
.id(...)(可能是因为我的条目不符合Identifiable)。
使用ForEach,这是我正在处理的代码:
ScrollViewReader { value in
ScrollView {
ForEach(state.messages, id: \.messageId) { message in
MessageView(message: message)
.id(message.messageId)
}
}
.onAppear {
value.scrollTo(state.messages.last?.messageId)
}
.onChange(of: state.messages.count) { _ in
value.scrollTo(state.messages.last?.messageId)
}
}
Run Code Online (Sandbox Code Playgroud)
使用时的一个重要考虑onAppear因素是在ScrollView/List而不是在ForEach. 在 中这样做ForEach将导致它在手动滚动列表时出现列表中的元素时触发。
mul*_*des 18
ScrollViewReader在 iOS14 SwiftUI 获得了新的能力。为了能够在 ScrollView 中滚动到具有给定id. 有一个新的类型,称为ScrollViewReader该作品就像Geometry Reader。
下面的代码将滚动到您视图中的最后一项。
所以这是你的“条目”结构,我猜:
struct Entry {
let id = UUID()
func getName() -> String {
return "Entry with id \(id.uuidString)"
}
}
Run Code Online (Sandbox Code Playgroud)
和主要的内容视图:
struct ContentView: View {
var entries: [Entry] = Array(repeating: Entry(), count: 10)
var body: some View {
ScrollView {
ScrollViewReader { value in
ForEach(entries, id: \.id) { entry in
Text(entry.getName())
.frame(width: 300, height: 200)
.padding(.all, 20)
}
.onAppear {
value.scrollTo(entries.last?.id, anchor: .center)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
尝试在 WWDC20 宣布的新版 SwiftUI 中运行它。我认为这是一个很大的增强。
nor*_*kin 13
我还没有足够的声誉发表评论,所以你去@Dam 和@Evert
要在ForEach更改条目数时滚动到底部,您还可以使用与 a 相同的方法ScrollViewReader,如上面的答案中所述,通过添加视图修饰符,onChange如下所示:
struct ContentView: View {
let colors: [Color] = [.red, .blue, .green]
var entries: [Entry] = Array(repeating: Entry(), count: 10)
var body: some View {
ScrollView {
ScrollViewReader { value in
ForEach(0..<entries.count) { i in
Text(self.entries[i].getName())
.frame(width: 300, height: 200)
.background(colors[i % colors.count])
.padding(.all, 20)
}
.onChange(of: entries.count) { _ in
value.scrollTo(entries.count - 1)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里提供的所有解决方案都假设有多个子视图,每个子视图都有一个 id。但是,如果您只有一个子元素(例如,随着时间的推移而增长的多行文本),并且您希望将这种自动滚动功能添加到底部,该怎么办?
然后您只需添加一个标识符(在我的例子中为“1”):
VStack {
ScrollViewReader { proxy in
ScrollView {
Text(historyText)
.id(1) // this is where to add an id
.multilineTextAlignment(.leading)
.padding()
}
.onChange(of: historyText) { _ in
proxy.scrollTo(1, anchor: .bottom)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想我们都在这里制作聊天应用程序!
这就是我最终所做的,主要是受到这里答案的启发,并进行了组合扭曲(经过多次尝试)
struct ChatItemListView: View {
@StateObject var lesson: Lesson
var body: some View {
ScrollViewReader { scrollViewProxy in
List(lesson.safeChatItems) { chatItem in
ChatItemRowView(chatItem: chatItem).id(chatItem.id)
}
.onReceive(lesson.objectWillChange) { _ in
guard !lesson.chatItems.isEmpty else { return }
Task {
scrollViewProxy.scrollTo(
lesson.chatItems.last!.id,
anchor: .top
)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的两个重要细节是:
.id(chatItem.id)Task没有这些,即使我chatItem实现了Identifiable协议,它也无法工作。
| 归档时间: |
|
| 查看次数: |
10424 次 |
| 最近记录: |