获取 ScrollView 在 SwiftUI 中的当前位置? [英] Get the current position of ScrollView in SwiftUI?

查看:61
本文介绍了获取 ScrollView 在 SwiftUI 中的当前位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到了 position 属性,但我认为它只是用来设置 x 和 y,但我不知道如何识别当前位置.

I saw the position property but I think that is just used to set x and y, but I don't know what about recognizing current location.

或者完全如何使用像 onHover 这样的事件收入属性?

Or totally how to use events income properties like onHover?

推荐答案

您可以使用 TrackableScrollView by @maxnatchanon

代码如下:

//
//  TrackableScrollView.swift
//  TrackableScrollView
//
//  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())
    }
}

这篇关于获取 ScrollView 在 SwiftUI 中的当前位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆