微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ScrollViewProxy 如何通过 ScrollViewProxy.scroll(to:) 修改父内容偏移量?

如何解决ScrollViewProxy 如何通过 ScrollViewProxy.scroll(to:) 修改父内容偏移量?

借助 SwiftUI 2.0,我们可以:

ScrollView() {
   ScrollViewReader { proxy in
      DummyContent()
         .onTapGesture {
            proxy.scroll(to: item...)
         }
   }
}

滚动到 ScrollView 内的特定子项。

我正在使用 ScrollView 的“从头开始”实现而不使用 AppKit(为了学习和扩展认 ScrollView 的自定义实现)

我设法在我的 ScrollViewer 实现中实现了滚动和剪切内容,我想通过 ScrollViewerProxy 实现滚动(到 :)、缩放(到 :) 功能,就像 Apple 用 ScrollViewProxy 做的那样。 我不知道 Apple 的 ScrollViewProxy 是如何操纵父视图偏移的?

这是我的 ScrollViewerProxy 和 ScrollViewerReader 的示例实现:

struct ScrollViewerProxy {
   @State var offset: CGSize = .zero
   
   func scroll(to origin: CGPoint) {
      let newOrigin = CGPoint(x: origin.x,y: origin.y)
      offset = CGSize(width: newOrigin.x,height: newOrigin.y)
   }
}

struct ScrollViewerReader<Content: View>: View {
   let content: (ScrollViewerProxy) -> Content
   
   @State private var offset: CGSize = .zero
   private var scrollViewerProxy = ScrollViewerProxy()
   
   init(@viewbuilder _ content: @escaping (ScrollViewerProxy) -> Content) {
      self.content = content
   }
   
   var body: some View {
      content(scrollViewerProxy)
         .offset( ??? ) // Can't do scrollViewerProxy.offset since it won't trigger ScrollViewerReader update
   }
}

// Bellow 是自定义 ScrollView 实现的代码,不是很重要,为了完整起见,把它放在这里

struct ScrollViewer<Content: View>: View {
   let content: Content

   var body: some View {
      ZStack {
         GeometryReader { geometry
            content 
               .offset(offset)
               .onPreferenceChange(ContentPreferenceKey.self) { preferences in
                  guard let p = preferences.first else { fatalError() }
                  contentRect = p.frame
                  ....
               // I monitor content frame changes via PreferenceKey
            }
         }
      }
   }
}

// Usage:
ScrollViewer {
   ScrollViewerReader { proxy in
      DummyContent()
         .onTapGesture {
            let random = CGPoint(x: -Int.random(in: 0...400),y: 0)
            proxy.scroll(to: random)
         }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。