SwiftUI如何在子视图中调用父ScrollViewReader的scrollTo方法
实现方案
有两种常用的无侵入实现方式,均可正常运行:
方案1:直接传递ScrollViewProxy到子视图
直接把父视图ScrollViewReader生成的proxy实例作为参数传给子视图,适合子视图滚动逻辑固定的场景。
子视图实现:
import SwiftUI struct ChildButton: View { // 声明接收ScrollViewProxy类型参数 let scrollProxy: ScrollViewProxy var body: some View { Button("go to bottom") { scrollProxy.scrollTo(19) } } }
父视图修改:
只需要在初始化子视图时传入proxy即可:
import SwiftUI struct ContentView: View { var body: some View { ScrollViewReader { value in ScrollView { // 传入当前ScrollView的proxy实例 ChildButton(scrollProxy: value) ForEach(0..<20) { i in Text("\(i)") .frame(width: 200, height: 200) .id(i) } } } } }
方案2:使用闭包回调实现
滚动逻辑完全放在父视图处理,子视图只负责触发点击事件,耦合度更低,适合子视图多场景复用的情况。
子视图实现:
import SwiftUI struct ChildButton: View { // 声明点击回调闭包 var onTap: () -> Void var body: some View { Button("go to bottom") { onTap() } } }
父视图修改:
初始化子视图时实现滚动逻辑的闭包即可:
import SwiftUI struct ContentView: View { var body: some View { ScrollViewReader { value in ScrollView { ChildButton { value.scrollTo(19) } ForEach(0..<20) { i in Text("\(i)") .frame(width: 200, height: 200) .id(i) } } } } }
选型建议
- 子视图仅用于当前ScrollView场景、滚动位置固定:选方案1,代码更简洁
- 子视图需要在多个ScrollView下复用、滚动位置需要父视图动态计算:选方案2,可维护性更高
内容的提问来源于stack exchange,提问作者Mathematical Lie
相关产品推荐
相关产品推荐

