swiftUI 自定义返回按钮

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SwiftUI提供了多种方法来实现自定义布局。其中,可以使用HStack、VStack、ZStack等布局容器来组合和排列视图元素,实现各种复杂界面。 另外,SwiftUI还提供了对齐指南来帮助文本对齐,如.leading、.trailing、.top等。但是当处理在不同视图之间分割的视图时,如果需要使完全不同的两个视图部分对齐,可以使用自定义的对齐辅助线。使用这些辅助线可以在整个界面中创建和使用辅助线,在视图之前或之后发生的变化并不重要,它们仍然会按照一条线排列。 例如,可以使用offset(x: CGFloat, y: CGFloat)方法为视图指定水平和垂直的偏移距离。这个方法可以将视图在水平和垂直方向上移动指定的距离。 综上所述,使用SwiftUI可以通过布局容器和对齐指南实现自定义布局,同时也可以使用偏移方法来调整视图的位置。这些功能可以帮助您创建个性化的布局。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SwiftUI 布局之自定义手动布局设置各种相对位置(教程含源码)](https://blog.csdn.net/iCloudEnd/article/details/107718464)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [SwiftUI之深入解析布局如何自定义AlignmentGuides](https://blog.csdn.net/Forever_wj/article/details/121958698)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值