Instantly share code, notes, and snippets.
Created
August 30, 2022 03:45
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save LePips/c37a83c8a09c229c641aed90f509bfba to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct NavBarDrawerButtonsModifier<Buttons: View>: ViewModifier { | |
let buttons: () -> Buttons | |
init(@ViewBuilder buttons: @escaping () -> Buttons) { | |
self.buttons = buttons | |
} | |
func body(content: Content) -> some View { | |
NavBarDrawerButtonsView { | |
ScrollView(.horizontal, showsIndicators: false) { | |
HStack { | |
buttons() | |
} | |
.padding(.horizontal) | |
} | |
.ignoresSafeArea() | |
} content: { | |
content | |
} | |
.ignoresSafeArea() | |
} | |
} | |
extension View { | |
func navBarDrawerButtons<Buttons: View>(@ViewBuilder _ buttons: @escaping () -> Buttons) -> some View { | |
self.modifier(NavBarDrawerButtonsModifier(buttons: buttons)) | |
} | |
} | |
struct NavBarDrawerButtonsView<Buttons: View, Content: View>: UIViewControllerRepresentable { | |
private let buttons: () -> Buttons | |
private let content: () -> Content | |
init( | |
@ViewBuilder buttons: @escaping () -> Buttons, | |
@ViewBuilder content: @escaping () -> Content | |
) { | |
self.buttons = buttons | |
self.content = content | |
} | |
func makeUIViewController(context: Context) -> UINavBarButtonsHostingController<Buttons, Content> { | |
UINavBarButtonsHostingController(buttons: buttons, content: content) | |
} | |
func updateUIViewController(_ uiViewController: UINavBarButtonsHostingController<Buttons, Content>, context: Context) {} | |
} | |
class UINavBarButtonsHostingController<Buttons: View, Content: View>: UIViewController { | |
private let buttons: () -> Buttons | |
private let content: () -> Content | |
private lazy var navBarBlurView: UIVisualEffectView = { | |
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .systemThinMaterial)) | |
blurView.translatesAutoresizingMaskIntoConstraints = false | |
return blurView | |
}() | |
private lazy var contentView: UIHostingController<Content> = { | |
let contentView = UIHostingController(rootView: content()) | |
contentView.view.translatesAutoresizingMaskIntoConstraints = false | |
contentView.view.backgroundColor = nil | |
return contentView | |
}() | |
private lazy var drawerButtonsView: UIHostingController<Buttons> = { | |
let drawerButtonsView = UIHostingController(rootView: buttons()) | |
drawerButtonsView.view.translatesAutoresizingMaskIntoConstraints = false | |
drawerButtonsView.view.backgroundColor = nil | |
return drawerButtonsView | |
}() | |
init( | |
buttons: @escaping () -> Buttons, | |
content: @escaping () -> Content | |
) { | |
self.buttons = buttons | |
self.content = content | |
super.init(nibName: nil, bundle: nil) | |
} | |
@available(*, unavailable) | |
required init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
view.backgroundColor = nil | |
addChild(contentView) | |
view.addSubview(contentView.view) | |
contentView.didMove(toParent: self) | |
view.addSubview(navBarBlurView) | |
addChild(drawerButtonsView) | |
view.addSubview(drawerButtonsView.view) | |
drawerButtonsView.didMove(toParent: self) | |
NSLayoutConstraint.activate([ | |
drawerButtonsView.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: -40), | |
drawerButtonsView.view.heightAnchor.constraint(equalToConstant: 40), | |
drawerButtonsView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
drawerButtonsView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
]) | |
NSLayoutConstraint.activate([ | |
navBarBlurView.topAnchor.constraint(equalTo: view.topAnchor), | |
navBarBlurView.bottomAnchor.constraint(equalTo: drawerButtonsView.view.bottomAnchor), | |
navBarBlurView.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
navBarBlurView.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
]) | |
NSLayoutConstraint.activate([ | |
contentView.view.topAnchor.constraint(equalTo: view.topAnchor), | |
contentView.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), | |
contentView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
contentView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
]) | |
} | |
override func viewWillAppear(_ animated: Bool) { | |
super.viewWillAppear(animated) | |
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default) | |
self.navigationController?.navigationBar.shadowImage = UIImage() | |
} | |
override func viewWillDisappear(_ animated: Bool) { | |
super.viewWillDisappear(animated) | |
self.navigationController?.navigationBar.setBackgroundImage(nil, for: .default) | |
self.navigationController?.navigationBar.shadowImage = nil | |
} | |
override var additionalSafeAreaInsets: UIEdgeInsets { | |
get { | |
.init(top: 40, left: 0, bottom: 0, right: 0) | |
} | |
set { | |
super.additionalSafeAreaInsets = .init(top: 40, left: 0, bottom: 0, right: 0) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment