如何以编程方式在 SwiftUI 中滚动?
Posted
技术标签:
【中文标题】如何以编程方式在 SwiftUI 中滚动?【英文标题】:How can I programmatically scroll in SwiftUI? 【发布时间】:2021-03-30 15:33:48 【问题描述】:在 SwiftUI 中有一种滚动到视图的方法。像这个例子:
ScrollView
ScrollViewReader value in
Button("Jump to #8")
// we scroll on button press
value.scrollTo(8, anchor: .top)
.padding()
ForEach(0..<100) i in
Text("Example \(i)")
.font(.title)
.frame(width: 200, height: 200)
.background(colors[i % colors.count])
// We need to set ID for scrolling
.id(i)
但我的用户界面并不是那么简单。我有一个视图和视图模型。也有一些延迟生成的视图。
在加载所有视图后,我需要滚动到某个元素。
Do it after 不是问题,但是如何从 ViewModel 以编程方式滚动到需要的元素?
@ObservedObject var model: someViewModel
var body: some View
ScrollView
ScrollViewReader pageScroller in
ForEach(0..<100) i in
Text("Example \(i)")
.frame(width: 200, height: 200)
.background(colors[i % colors.count])
.id(i)
.frame(height: 350)
class someViewModel: ObservableObject
@Published var scrollToPageName = 4
var needToScroll = false
init()
如何在不刷新页面的情况下从我的model
执行pageScroller.scrollTo(pageIndex, anchor: .top)
?
或者如何通过一些事件从模型中执行一些视图函数?
我也不需要在滚动(!)之前刷新页面 - 就像第一个示例中的按钮单击一样。
【问题讨论】:
您想知道如何滚动和使用pageScroller吗? @swiftPunk 我需要知道如何从我的viewModel
拨打pageScroller.scrollTo(pageIndex, anchor: .top)
【参考方案1】:
滚动不是视图模型的责任,但您可以在视图模型中添加selectedIndex
属性,然后观察并响应更改。
var body: some View
ScrollView
ScrollViewReader pageScroller in
ForEach(0..<100) i in
Text("Example \(i)")
.frame(width: 200, height: 200)
.background(colors[i % colors.count])
.id(i)
.onChange(of: viewModel.selectedIndex) newIndex in
pageScroller.scrollTo(newIndex, anchor: .top)
.frame(height: 350)
由于您提到您的内容是异步加载的,因此您可以在加载所有内容后更新selectedIndex
属性。
【讨论】:
太棒了!非常感谢! isviewModel.selectedIndex
必须是 @Published 才能获得这样的代码?
一定是!当然。
@swiftPunk 这不是问题。这是 SwiftUI 的设计行为。请阅读以下文本:***.com/a/62919526/4423545 了解在 swiftUI 中使用 vievModels 的基础知识
@swiftPunk 我已经解决了问题并为我的所有问题找到了解决方案,你们都帮助了我,swiftPunk 和 EmilioPelaez。我将在几个小时内编写替代答案,无需刷新视图即可使用。【参考方案2】:
重要! 仅当不刷新视图很重要时,此答案才会对您有用。在另一种情况下,最好使用 EmilioPelaez
的解决方案这个答案展示了如何:
从模型发送事件到视图
并在事件触发时执行一些函数
不会触发全视图刷新!只有代码会像按下按钮一样被执行!
@ObservedObject var model: someViewModel
var body: some View
ScrollView
ScrollViewReader pageScroller in
ForEach(0..<100) i in
Text("Example \(i)")
.frame(width: 200, height: 200)
.background(colors[i % colors.count])
.id(i)
//Magic here
.onReceive(model.scroller.objectWillChange)
pageScroller.scrollTo(model.scroller.scrollToPageName, anchor: .top)
.frame(height: 350)
class someViewModel: ObservableObject
//Magic here
@ObservedObject var scroller: scrollerHelper
init()
someDelayedCall()
func someDelayedCall()
scroller.scrollToPageName = 8
//Magic here
class scrollerHelper: ObservableObject
@Published var scrollToPageName: Int = -1
【讨论】:
以上是关于如何以编程方式在 SwiftUI 中滚动?的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 13 上以编程方式滚动 SwiftUI ScrollView
如何以编程方式从 SwiftUI 列表中删除行并刷新列表视图?