iphone
在iphone下,因为不存在侧边栏,自定义返回按钮较为简单。
隐藏页面的返回按钮。使用toolbar修饰符或使用ZStack即可。
toolbar:
@Environment(\.presentationMode) private var presentationMode
var 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 presentationMode
var 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 SwiftUI
extension UIApplication{
static let safeAreaInsetsTop = UIApplication.shared.windows.first?.safeAreaInsets.top
static 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 }!.rootViewController
guard 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 SwiftUI
extension UISplitViewController {
/// 用于控制侧边栏显示
public static var isHide = false {
didSet {
let controller = UIApplication.shared.windows.first { $0.isKeyWindow }!.rootViewController
guard 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 = 400
preferredPrimaryColumnWidthFraction = 400
}
}
这样,扩展UISplitViewController后直接可以调用UISplitViewController.isHide.toggle()来显示和展开侧边栏了。
github地址,点击demo