技术:SwiftUI、SwiftUI4.0、抖音评论、半页模式、底部抽屉
运行环境:
SwiftUI4.0 + Xcode14 + MacOS12.6 + iPhone Simulator iPhone 14 Pro Max
SwiftUI搭建一个类似抖音评论模块的半页模式 - 底部抽屉
概述
使用SwiftUI搭建一个类似抖音评论模块的半页模式 - 底部抽屉
详细
一、运行效果
二、项目结构图
三、程序实现 - 过程
思路:
- 基于View扩展一个模态视图
- 使用SwiftUI的ViewControllerRepresentable
使用实例在 SwiftUI 界面中创建和管理对象。
能像UIKit那样管理对象,监听模态视图的代理- 使用SwiftUI的UIHostingController -
管理 SwiftUI 视图层次结构的 UIKit 视图控制器。
能向UIKit那样管理视图的生命周期或结构
1.创建一个项目命名为 ScrollToHide
1.1.引入资源文件和颜色
无
Code
ContentView - 主窗口
主要是展示主窗口
Home
设置半页模态弹框
- 基于View扩展一个模态视图
- 基于UIKit的UIViewControllerRepresentable
使用实例在 SwiftUI 界面中创建和管理对象。
监听模态视图的代理- 基于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
}
}
}