我看到了position属性,但是我认为它只是用于设置x和y,但是我不知道如何识别当前位置。
还是完全使用onHover这样的事件收益属性?
答案 0 :(得分:3)
您可以通过@maxnatchanon使用TrackableScrollView
代码如下:
//
// TrackableScrollView.swift
// ToutiaoARDemo
//
// Created by Frad LEE on 2020/6/21.
// Copyright © 2020 Frad LEE. All rights reserved.
//
import SwiftUI
/// A trackable and scrollable view. Read [this link](https://medium.com/@maxnatchanon/swiftui-how-to-get-content-offset-from-scrollview-5ce1f84603ec) for more.
///
/// The trackable scroll view displays its content within the trackable scrollable content region.
///
/// # Usage
///
/// ``` swift
/// struct ContentView: View {
/// @State private var scrollViewContentOffset = CGFloat(0) // Content offset available to use
///
/// var body: some View {
/// TrackableScrollView(.vertical, showIndicators: false, contentOffset: $scrollViewContentOffset) {
/// ...
/// }
/// }
/// }
/// ```
struct TrackableScrollView<Content>: View where Content: View {
let axes: Axis.Set
let showIndicators: Bool
@Binding var contentOffset: CGFloat
let content: Content
/// Creates a new instance that’s scrollable in the direction of the given axis and can show indicators while scrolling.
/// - Parameters:
/// - axes: The scrollable axes of the scroll view.
/// - showIndicators: A value that indicates whether the scroll view displays the scrollable component of the content offset, in a way that’s suitable for the platform.
/// - contentOffset: A value that indicates offset of content.
/// - content: The scroll view’s content.
init(_ axes: Axis.Set = .vertical, showIndicators: Bool = true, contentOffset: Binding<CGFloat>, @ViewBuilder content: () -> Content) {
self.axes = axes
self.showIndicators = showIndicators
_contentOffset = contentOffset
self.content = content()
}
var body: some View {
GeometryReader { outsideProxy in
ScrollView(self.axes, showsIndicators: self.showIndicators) {
ZStack(alignment: self.axes == .vertical ? .top : .leading) {
GeometryReader { insideProxy in
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: [self.calculateContentOffset(fromOutsideProxy: outsideProxy, insideProxy: insideProxy)])
}
VStack {
self.content
}
}
}
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
self.contentOffset = value[0]
}
}
}
private func calculateContentOffset(fromOutsideProxy outsideProxy: GeometryProxy, insideProxy: GeometryProxy) -> CGFloat {
if axes == .vertical {
return outsideProxy.frame(in: .global).minY - insideProxy.frame(in: .global).minY
} else {
return outsideProxy.frame(in: .global).minX - insideProxy.frame(in: .global).minX
}
}
}
struct ScrollOffsetPreferenceKey: PreferenceKey {
typealias Value = [CGFloat]
static var defaultValue: [CGFloat] = [0]
static func reduce(value: inout [CGFloat], nextValue: () -> [CGFloat]) {
value.append(contentsOf: nextValue())
}
}
答案 1 :(得分:1)
请参见What is Geometry Reader in SwiftUI?,尤其是有关GeometryGetter
的讨论。如果将GeometryGetter
放在内容ScrollView
的顶部,它将使用传递给它的绑定来发出其框架。该帧的原点将是滚动视图的负内容偏移量。
答案 2 :(得分:0)
如果找不到任何选项。您仍然可以将标准UIScrollView
与它们的delegates
和UIViewRepresentable
配合使用,只要使一个单独的结构符合标准即可。
您可以在SwiftUI教程中找到的更多详细信息: https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit
答案 3 :(得分:0)
在下面的示例中,您将看到如何使用GeometryReader
来获取内容在滚动视图中的水平位置。但是,我尚未成功找到如何设置滚动位置的方法。 (Xcode 11.0 beta 6(11M392q))
struct TimelineView: View {
@State private var posX: CGFloat = 0
var body: some View {
GeometryReader { geo in
VStack {
Text("\(self.posX)")
ScrollView(.horizontal, showsIndicators: true) {
VStack {
GeometryReader { innerGeo -> Text in
self.posX = innerGeo.frame(in: .global).minX
return Text("")
}
TimelineGridView()
}
}
.position(x: geo.size.width / 2, y: geo.size.height / 2)
}
}
}
}
其中:
struct TimelineGridView: View {
var body: some View {
VStack {
ForEach(0...10, id: \.self) { rowIndex in
TimelineRowView()
}
}
}
}
struct TimelineRowView: View {
var body: some View {
HStack {
ForEach(0...100, id: \.self) { itemIndex in
TimelineCellView()
}
}
}
}
struct TimelineCellView: View {
var body: some View {
Rectangle()
.fill(Color.yellow)
.opacity(0.5)
.frame(width: 10, height: 10, alignment: .bottomLeading)
}
}
```
答案 4 :(得分:0)
我为此目的创建了SwiftPackage(纯SwiftUI?)
有了这个库,您可以获得ScrollView的位置。
https://github.com/kazuooooo/PositionScrollView
let maxNumberOfFrames = AVAudioFrameCount(1024)
let sampleRate = 44_100.0
guard let format = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: sampleRate, channels: 2, interleaved: false) else { return nil }
try engine.enableManualRenderingMode(.offline, format: format, maximumFrameCount: maxNumberOfFrames)
if delegate!.newRenderInstrument(connectedTo: engine.mainMixerNode) == nil { return nil }
engine.mainMixerNode.outputVolume = 2.0
sequencer = AVAudioSequencer(audioEngine: engine)
try sequencer!.load(from: data, options: AVMusicSequenceLoadOptions())
sequencer!.prepareToPlay()
let outputURL = folder.appendingPathComponent("\(name).m4a")
let fileSettings: [String: Any] = [
AVFormatIDKey: NSNumber(value: kAudioFormatMPEG4AAC),
AVSampleRateKey: NSNumber(value: sampleRate),
AVNumberOfChannelsKey: NSNumber(value: 2)
]
let outputFile = try AVAudioFile(forWriting: outputURL, settings: fileSettings)
guard let buffer = AVAudioPCMBuffer(pcmFormat: engine.manualRenderingFormat, frameCapacity: engine.manualRenderingMaximumFrameCount) else { return nil }
try engine.start()
try sequencer!.start()