Condider a new blank iOS project set to use Storyboard. Update the ViewController
to match the above and add in the other files.
Last active
August 5, 2021 17:58
-
-
Save vargero/7a018471856be3be06ef45910f6203df to your computer and use it in GitHub Desktop.
Custom Action Sheet View Controller (UIKit + SwiftUI)
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
import SwiftUI | |
struct CustomActionSheet: View { | |
@State private var offset: CGFloat = UIScreen.main.bounds.height | |
@Binding var isShowing: Bool | |
private var maxWidth: CGFloat { UIScreen.main.bounds.width } | |
private var maxHeight: CGFloat { UIScreen.main.bounds.height } | |
init(isShowing: Binding<Bool>) { | |
_isShowing = isShowing | |
} | |
private var actionSheet: some View { | |
VStack(spacing: 7) { | |
Color.gray | |
.frame(width: 45, height: 6) | |
.cornerRadius(3) | |
HStack { | |
Spacer() | |
VStack { | |
Text("1") | |
Text("2") | |
Text("3") | |
Text("4") | |
} | |
Spacer() | |
} | |
.padding(.bottom, (UIApplication.shared.windows.last?.safeAreaInsets.bottom ?? 0) + 40) | |
.padding(.top, 20) | |
.padding(.horizontal, 0) | |
.background(Color.white) | |
} | |
} | |
var body: some View { | |
VStack { | |
Spacer() | |
actionSheet | |
.offset(y: self.offset) | |
.gesture(DragGesture() | |
.onChanged({ (value) in | |
if value.translation.height > 0 { | |
self.offset = value.location.y | |
} | |
}).onEnded({ (value) in | |
showActionSheet(self.offset <= 100) | |
})) | |
} | |
.frame(width: maxWidth, height: maxHeight) | |
.edgesIgnoringSafeArea(.all) | |
.onChange(of: isShowing, perform: { value in | |
showActionSheet(value) | |
}) | |
.background((self.offset <= 100 ? Color.black.opacity(0.3) : Color.clear) | |
.edgesIgnoringSafeArea(.all) | |
.onTapGesture { | |
showActionSheet(false) | |
}) | |
} | |
func showActionSheet(_ show: Bool) { | |
withAnimation { | |
offset = show ? 0 : maxHeight | |
} | |
} | |
} |
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
import SwiftUI | |
import UIKit | |
class CustomActionSheetViewController: UIViewController { | |
private var internalVC: UIHostingController<CustomActionSheet>? | |
var show = true | |
lazy var isShowing: Binding<Bool> = .init { | |
self.show | |
} set: { show in | |
self.show = show | |
if !show { | |
self.dismiss(animated: false, completion: nil) | |
} | |
} | |
lazy var testView = CustomActionSheet(isShowing: isShowing) | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
let ivc = UIHostingController(rootView: testView) | |
internalVC = ivc | |
view.addSubview(ivc.view) | |
ivc.view.backgroundColor = .clear | |
ivc.view.translatesAutoresizingMaskIntoConstraints = false | |
ivc.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true | |
ivc.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true | |
ivc.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true | |
ivc.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true | |
} | |
override func viewDidAppear(_ animated: Bool) { | |
super.viewDidAppear(animated) | |
isShowing.wrappedValue = true | |
isShowing.update() | |
} | |
} |
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
import UIKit | |
class ViewController: UIViewController { | |
let button = UIButton(type: .system) | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Do any additional setup after loading the view. | |
view.backgroundColor = .white | |
button.setTitle("TAP THIS BUTTON", for: .normal) | |
view.addSubview(button) | |
button.translatesAutoresizingMaskIntoConstraints = false | |
button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true | |
button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true | |
button.addTarget(self, action: #selector(tapped), for: .touchUpInside) | |
} | |
@objc private func tapped() { | |
let vc = CustomActionSheetViewController() | |
vc.modalPresentationStyle = .overCurrentContext | |
present(vc, animated: false) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The view controller presenting this: