iphone
在iphone下,因为不存在侧边栏,自定义返回按钮较为简单。
隐藏页面的返回按钮。使用toolbar修饰符或使用ZStack即可。
toolbar:
@Environment(\.presentationMode) private var presentationModevar body: some View {ZStack {VStack {Text("test")}}.navigationBarBackButtonHidden(true).toolbar(content: {ToolbarItemGroup(placement: .navigationBarLeading){BackButtonIcon()}}).edgesIgnoringSafeArea(.all)}func BackButtonIcon() -> some View {Image("icon.arrow.left").renderingMode(.template).resizable().frame(width: 24, height: 24).padding(.all, 6).background(Color.black.opacity(0.2).clipShape(Circle()).shadow(radius: 4)).foregroundColor(Color.white).cornerRadius(30).onTapGesture {presentationMode.wrappedValue.dismiss()}}
z-Index:
@Environment(\.presentationMode) private var presentationModevar body: some View {ZStack {VStack {Text("test")}ToolBar()}.navigationBarHidden(true).edgesIgnoringSafeArea(.all)}func ToolBar() -> some View {VStack {HStack {// 后退BackButtonIcon()Spacer()}.padding(.top, 4)Spacer()}.padding(.top, UIApplication.safeAreaInsetsTop == 0 ? 15: UIApplication.safeAreaInsetsTop).padding(.horizontal, 15)}func BackButtonIcon() -> some View {Image("icon.arrow.left").renderingMode(.template).resizable().frame(width: 24, height: 24).padding(.all, 6).background(Color.black.opacity(0.2).clipShape(Circle()).shadow(radius: 4)).foregroundColor(Color.white).cornerRadius(30).onTapGesture {presentationMode.wrappedValue.dismiss()}}
UIApplication 扩展:
import SwiftUIextension UIApplication{static let safeAreaInsetsTop = UIApplication.shared.windows.first?.safeAreaInsets.topstatic let safeAreaInsetsBottom = UIApplication.shared.windows.first?.safeAreaInsets.bottom}
因为禁用了系统的返回按钮,所以此方法下手势操作也需要自己实现。
iPad
iPad在竖屏下返回按钮将弹出sidebar。presentationMode.wrappedValue.dismiss()无法实现。
所以经过瞎折腾,想到了两种解决方案。
1.隐藏后退按钮
当然,这里的隐藏后退按钮不是设置navigationBarBackButtonHidden。使用属性设置后,将不能触发系统返回效果。
那么,要怎么办呢!我们可以把后退按钮设置成透明,在按钮的位置覆盖一个自己的样式,那么点击的时候是不是就可以触发系统的返回了呢。
extension UINavigationController {override open func viewDidLoad() {super.viewDidLoad()/// 将导航栏按钮设置为透明navigationBar.tintColor = UIColor.clear}}// 或者struct ContentView: View {init() {UINavigationBar.appearance().tintColor = .clear}...}
2.使用UISplitViewController
使用UIApplication可以获取UISplitViewController
let controller = UIApplication.shared.windows.first {$0.isKeyWindow }!.rootViewControllerguard let split = controller?.children[0] as? UISplitViewController else {return}
UISplitViewController中存在两个方法,@available(iOS 14.0, *) open func hide(_ column: UISplitViewController.Column)
和@available(iOS 14.0, *) open func show(_ column: UISplitViewController.Column)
用来隐藏和显示侧边栏。
import SwiftUIextension UISplitViewController {/// 用于控制侧边栏显示public static var isHide = false {didSet {let controller = UIApplication.shared.windows.first {$0.isKeyWindow }!.rootViewControllerguard let split = controller?.children[0] as? UISplitViewController else {print("not a split view")return}if isHide {split.dismiss(animated: true) {isHide = false}split.show(.primary)} else {split.hide(.primary)}}}open override func viewDidLoad() {super.viewDidLoad()/// 设置侧边栏宽度maximumPrimaryColumnWidth = 400preferredPrimaryColumnWidthFraction = 400}}
这样,扩展UISplitViewController后直接可以调用UISplitViewController.isHide.toggle()来显示和展开侧边栏了。
github地址,点击demo