【SwiftUI模块】0032、SwiftUI搭建一个类似抖音评论模块的半页模式 - 底部抽屉

SwiftUI模块系列 - 已更新32篇
SwiftUI项目 - 已更新3个项目
往期Demo源码下载

技术:SwiftUI、SwiftUI4.0、抖音评论、半页模式、底部抽屉
运行环境:
SwiftUI4.0 + Xcode14 + MacOS12.6 + iPhone Simulator iPhone 14 Pro Max

概述

使用SwiftUI搭建一个类似抖音评论模块的半页模式 - 底部抽屉

详细

一、运行效果

请添加图片描述

二、项目结构图

在这里插入图片描述

三、程序实现 - 过程

思路:

  1. 基于View扩展一个模态视图
  2. 使用SwiftUI的ViewControllerRepresentable 使用实例在 SwiftUI 界面中创建和管理对象。能像UIKit那样管理对象,监听模态视图的代理
  3. 使用SwiftUI的UIHostingController - 管理 SwiftUI 视图层次结构的 UIKit 视图控制器。 能向UIKit那样管理视图的生命周期或结构

1.创建一个项目命名为 ScrollToHide

在这里插入图片描述
在这里插入图片描述

1.1.引入资源文件和颜色

Code

ContentView - 主窗口

主要是展示主窗口Home 设置半页模态弹框

  1. 基于View扩展一个模态视图
  2. 基于UIKit的UIViewControllerRepresentable 使用实例在 SwiftUI 界面中创建和管理对象。监听模态视图的代理
  3. 基于UIKit的UIHostingController - 管理 SwiftUI 视图层次结构的 UIKit 视图控制器。
//
//  ContentView.swift
//  ScrollToHide
//
//  Created by 李宇鸿 on 2022/9/26.
//

import SwiftUI

struct ContentView: View {
    
    
    var body: some View {
    
    
        Home()
    }
}

struct ContentView_Previews: PreviewProvider {
    
    
    static var previews: some View {
    
    
        ContentView()
    }
}


struct Home: View{
    
    
    @State var showSheet : Bool = false
    var body: some View {
    
    
        NavigationView{
    
    
            Button  {
    
    
                showSheet.toggle()
            } label: {
    
    
                Text("Present Sheet")
            }
            .navigationTitle("Half Modal Sheet")
            .halfSheet(showSheet: $showSheet) {
    
    
                
                // 你的半页视图…
                ZStack{
    
    
                    Color.red
                    VStack{
    
    
                        Text("Hello iJustine")
                            .font(.title.bold())
                            .foregroundColor(.white)
                        Button  {
    
    
                            showSheet.toggle()
                        } label: {
    
    
                            Text("Close From Sheet")
                                .foregroundColor(.white)
                        }
                        .padding()

                    }
                }
             
            } onEnd: {
    
    
                print("Dismiss")
            }

        }
        
    }
}


// 自定义半页修饰器....
extension View {
    
    
    // 绑定变量显示……
    func halfSheet<SheetView:View>(showSheet:Binding<Bool>,@ViewBuilder sheetView: @escaping ()->SheetView,onEnd: @escaping()->()) ->some View{
    
    
   
        //为什么我们使用overlay…
        // 因为它将自动使用swiftUI帧大小…
        return self
            .background(
                HalfSheetHelper(sheetView: sheetView(),showSheet: showSheet,onEnd: onEnd)
            )
    }
}

// UIKit 集成
struct HalfSheetHelper<SheetView: View>: UIViewControllerRepresentable {
    
    

    
    var sheetView : SheetView
    @Binding var showSheet: Bool
    var onEnd : ()->()
    
    let controller = UIViewController()
    
    func makeCoordinator() -> Coordinator {
    
    
        return Coordinator(parent: self)
    }
    
    func makeUIViewController(context: Context) -> some UIViewController {
    
    
        controller.view.backgroundColor = .clear
        return controller
    }
    
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
    
    
        
        if showSheet {
    
    
            // 弹出模态视图
            let sheetController = CustomHostingController(rootView: sheetView)
            sheetController.presentationController?.delegate = context.coordinator
            uiViewController.present(sheetController, animated: true)
        }
        else {
    
    
            // 当ShowSheet再次切换时…
            uiViewController.dismiss(animated: true)
        }
    }
    
    // 监听dismiss
    class Coordinator : NSObject,UISheetPresentationControllerDelegate {
    
    
        var parent : HalfSheetHelper
        init(parent: HalfSheetHelper) {
    
    
            self.parent = parent
        }
        func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
    
    
            parent.showSheet = false
            parent.onEnd()
        }
    }
    
}

// 自定义UIHostingController for halfSheet…
class CustomHostingController<Content: View> : UIHostingController<Content> {
    
    
    override func viewDidLoad() {
    
    
        
        view.backgroundColor = .clear
        // 设置表示控制器属性…
        if let presentationController = presentationController as? UISheetPresentationController {
    
    
            presentationController.detents = [
                .medium(),
                .large()
            ]
            
            // 为了显示抓取比例…
            presentationController.prefersGrabberVisible = true
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42816425/article/details/126843748