【问题标题】:How to scroll a list horizontally in SwiftUI?如何在 SwiftUI 中水平滚动列表?
【发布时间】:2021-07-06 09:55:13
【问题描述】:

在 iOS 14 中,您可以使用 ScrollViewReader 在滚动视图中的内容发生变化时自动向上或向下滚动视图。

我处于必须支持 iOS 13 的情况。有没有办法,甚至是一种 hacky 方式,以编程方式在 iOS 13 中滚动滚动视图?

为此,我编写了以下代码,它适用于垂直滚动,但我需要水平滚动并且它需要移动选定的索引。

    struct ListScrollingHelper: UIViewRepresentable {
        let proxy: ListScrollingProxy // reference type
    
        func makeUIView(context: Context) -> UIView {
            return UIView() // managed by SwiftUI, no overloads
        }
    
        func updateUIView(_ uiView: UIView, context: Context) {
            proxy.catchScrollView(for: uiView) // here UIView is in view hierarchy
        }
    }

class ListScrollingProxy {
    enum Action {
        case end
        case top
        case point(point: CGPoint)     // << bonus !!
    }

    private var scrollView: UIScrollView?

    func catchScrollView(for view: UIView) {
        if nil == scrollView {
            scrollView = view.enclosingScrollView()
        }
    }

    func scrollTo(_ action: Action) {
        if let scroller = scrollView {
            var rect = CGRect(origin: .zero, size: CGSize(width: 1, height: 1))
            switch action {
                case .end:
                    rect.origin.y = scroller.contentSize.height +
                        scroller.contentInset.bottom + scroller.contentInset.top - 1
                case .point(let point):
                    rect.origin.y = point.y
                default: {
                    // default goes to top
                }()
            }
            scroller.scrollRectToVisible(rect, animated: true)
        }
    }
}

extension UIView {
    func enclosingScrollView() -> UIScrollView? {
        var next: UIView? = self
        repeat {
            next = next?.superview
            if let scrollview = next as? UIScrollView {
                return scrollview
            }
        } while next != nil
        return nil
    }
}

我使用我的代码如下:

struct ContentView: View {
    private let scrollingProxy = ListScrollingProxy() // proxy helper

    var body: some View {
        VStack {
            HStack {
                Button(action: { self.scrollingProxy.scrollTo(.top) }) { // < here
                    Image(systemName: "arrow.up.to.line")
                      .padding(.horizontal)
                }
                Button(action: { self.scrollingProxy.scrollTo(.end) }) { // << here
                    Image(systemName: "arrow.down.to.line")
                      .padding(.horizontal)
                }
            }
            Divider()
            List {
                ForEach(0 ..< 200) { i in
                    Text("Item \(i)")
                        .background(
                           ListScrollingHelper(proxy: self.scrollingProxy) // injection
                        )
                }
            }
        }
    }
}

【问题讨论】:

    标签: swift swiftui scrollview


    【解决方案1】:

    使用以下方法:

    import SwiftUI
    
    struct ContentView: View {    
        
        var body: some View {            
            ScrollView(.horizontal, showsIndicators: false) {
                HStack(spacing: 10) {
                    ForEach(1..<11) {
                        Text("ITEM \($0)")
                            .frame(width: 70, height: 70)
                    }
                }
            }
        }
    }
    

    滚动整个表格如下所示:

    struct ContentView: View {
            
        var body: some View {
            List {
                ScrollView(.horizontal, showsIndicators: false) {       
                    Text("First List Item in a first cell")
                    Text("Second List Item in a second cell")
                    Text("Third List Item in a third cell")
                }
            }
        }
    }
    

    您可以结合使用这两种方法。

    【讨论】:

    • 这里我们可以使用滚动视图的滚动属性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 2021-05-27
    • 2020-09-23
    • 2021-02-08
    相关资源
    最近更新 更多