Как прокрутить список по горизонтали в SwiftUI?

#swift #swiftui #scrollview

Вопрос:

В iOS 14 вы можете использовать ScrollViewReader для автоматической прокрутки представления вверх или вниз по мере изменения содержимого в представлении прокрутки.

Я нахожусь в ситуации, когда мне нужно поддерживать iOS 13. Есть ли способ, даже банальный способ, программно прокручивать представление прокрутки в 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
                        )
                }
            }
        }
    }
}
 

Ответ №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")
            }
        }
    }
}
 

Вы можете комбинировать обе методологии.

Комментарии:

1. Здесь мы можем использовать свойство прокрутки вида прокрутки