美文网首页SwiftUI
SwiftUI分页滑动PageView(转接UIScrollVi

SwiftUI分页滑动PageView(转接UIScrollVi

作者: zjam9333 | 来源:发表于2021-08-26 16:53 被阅读0次

    在SwiftUI的ScrollView中似乎找不到isPagingEnabled类似的属性,用于开启分页滑动。

    iOS14中用TabView{...}.tabViewStyle(PageTabViewStyle())也可以达到分页滑动的效果,但不知如何获得currentPage之类的属性,无法使用自定义的PageControl

    等官方的ScrollViewTabView更新page相关的功能,便无需考虑此转接方案

    那么考虑使用UIViewRepresentableUIHostingController等转接UIkit的方案。

    大概思路是定义一个PageView,其content传入UIScrollViewRepUIScrollViewRep内部的UIScrollView布局content,且有其Coordinator实例作为UIScrollViewDelegate代理监听滑动contentOffset,并且更改绑定的currentPage

    struct PageView<Content: View> : View {
        let pageCount: Int
        @Binding var currentPage: Int
        @ViewBuilder let content: () -> Content
        
        var body: some View {
            GeometryReader { geo in
                UIScrollViewRep(pageCount: pageCount, currentPage: $currentPage, size: geo.size) {
                    HStack(alignment: .center, spacing: 0) {
                        content()
                    }
                }
                .frame(width: geo.size.width, height: geo.size.height)
            }
        }
    }
    
      struct UIScrollViewRep<ScrollViewContent: View>: UIViewRepresentable {
            let pageCount: Int
            @Binding var currentPage: Int
            let size: CGSize
            var content: (() -> ScrollViewContent)?
            func makeUIView(context: Context) -> UIScrollView {
                let scrollView = UIScrollView()
                scrollView.contentInsetAdjustmentBehavior = .never
                scrollView.isPagingEnabled = true
                scrollView.delegate = context.coordinator
                scrollView.showsHorizontalScrollIndicator = false
                if let con = content?() {
                    let contro = UIHostingController(rootView: con)
                    if let view = contro.view {
                        view.backgroundColor = .clear
                        scrollView.addSubview(view)
                    }
                }
                return scrollView
            }
            
            func updateUIView(_ uiView: UIScrollView, context: Context) {
                var frame = CGRect(origin: .zero, size: size)
                frame.size.width *= CGFloat(pageCount)
                if let view = uiView.subviews.first {
                    view.frame = frame
                }
                uiView.contentSize = frame.size
            }
            
            typealias UIViewType = UIScrollView
            
            func makeCoordinator() -> Coor<ScrollViewContent> {
                let coo = Coor<ScrollViewContent>(self)
                return coo
            }
            
            class Coor<ScrollViewContent: View>: NSObject, UIScrollViewDelegate {
                var parent: UIScrollViewRep<ScrollViewContent>
                init(_ parent: UIScrollViewRep<ScrollViewContent>) {
                    self.parent = parent
                }
                
                func scrollViewDidScroll(_ scrollView: UIScrollView) {
                    let width = scrollView.frame.size.width
                    let offsetx = scrollView.contentOffset.x
                    let page = offsetx / width
                    self.parent.currentPage = Int(page)
                }
            }
    

    最终在页面声明使用

    PageView(pageCount: 4, currentPage: $currentPage) {
                                ForEach(0 ..< 4) { index in
                                    Color(.red).cornerRadius(10).padding(.horizontal, 10)
                                }
                            }
                            .frame(height: 360)
    

    自定义PageControl

    HStack(alignment: .center, spacing: 6) {
                                ForEach(0 ..< 4) { index in
                                    let isCurr = index == currentPage
                                    Color(isCurr ? .systemBlue : .gray).cornerRadius(2).frame(width: isCurr ? 10 : 4, height: 4)
                                }
                            }.frame(height: 20).offset(x: 0, y: -10)
    
    截屏2021-08-26 下午3.15.49.png

    缺点是需要传入pageCountcontent内只能传一个pages的组合。要做到TabView那样自动算出pageCount等,还需研究

    相关文章

      网友评论

        本文标题:SwiftUI分页滑动PageView(转接UIScrollVi

        本文链接:https://www.haomeiwen.com/subject/eogtvktx.html