【Swift】UIAlertControllerのactionSheetにカスタムViewを埋め込む
UIAlertControllerからactionSheetスタイルで表示したアラートにカスタムViewを埋め込みたくなったので、埋め込み方法を調べました。
環境
- Xcode 14.1
- iOS 16.1
UIAlertController.Style.actionSheet
UIAlertController.Style
を.actionSheet
に選択することでiOSデバイスでは下から出てくるアクションシートを表現出来ます。
@IBAction private func showActionSheet(_ sender: UIButton) { let actionSheet = UIAlertController(title: "かわいいは作れる", message: nil, preferredStyle: .actionSheet) // iPadのクラッシュ対応 actionSheet.popoverPresentationController?.sourceView = sender.superview actionSheet.popoverPresentationController?.sourceRect = sender.frame let yesAction = UIAlertAction(title: "はい", style: .default) let noAction = UIAlertAction(title: "いいえ", style: .cancel) actionSheet.addAction(yesAction) actionSheet.addAction(noAction) present(actionSheet, animated: true) }
このアクションシートにカスタムViewを追加してかわいいを作っていこうと思います。
補足
iPadでUIAlertController.Style.actionSheet
を使用するには位置情報の設定が必要で、位置情報を設定しない場合にはクラッシュしてしまう為、sourceView
とsourceRect
を設定しています。
// iPadのクラッシュ対応 actionSheet.popoverPresentationController?.sourceView = sender.superview actionSheet.popoverPresentationController?.sourceRect = sender.frame
詳細については以前記事を書いたので今回は省かせていただきます。
UIAlertControllerにカスタムViewを追加する
埋め込むカスタムView
SwiftUIのViewでこのようなViewを作成しました。
UIAlertControllerにaddSubViewをする
作成したカスタムViewをUIAlertController.view
にaddSubView
を行います。
UIAlertController
のtitle
にカスタムViewが良い具合に収まるくらいの改行のテキストを渡します。すると、アラートのタイトル欄が縦に長くなるので、addSubView
をした時に中に収まっているように表現することが出来ます。
@IBAction private func showActionSheet(_ sender: UIButton) { // 縦方向にスペースを追加し、ActionSheetのタイトルの縦幅を広くする let verticalSpaceText = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n" let actionSheet = UIAlertController(title: verticalSpaceText, message: nil, preferredStyle: .actionSheet) // iPadのクラッシュ対応 actionSheet.popoverPresentationController?.sourceView = sender.superview actionSheet.popoverPresentationController?.sourceRect = sender.frame let hostingController = UIHostingController(rootView: CuteView()) actionSheet.addChild(hostingController) // actionSheetにカスタムViewを追加 actionSheet.view.addSubview(hostingController.view) hostingController.didMove(toParent: actionSheet) guard let actionSheetView = actionSheet.view else { return } // レイアウトの調整 hostingController.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ hostingController.view.topAnchor.constraint(equalTo: actionSheetView.topAnchor, constant: 40), hostingController.view.widthAnchor.constraint(equalTo: actionSheetView.widthAnchor), ]) let yesAction = UIAlertAction(title: "はい", style: .default) let noAction = UIAlertAction(title: "いいえ", style: .cancel) actionSheet.addAction(yesAction) actionSheet.addAction(noAction) present(actionSheet, animated: true) }
埋め込みたいViewによって、レイアウトの制約も調整してみてください。
出来たもの
無事にかわいいが作れました。
おわりに
SwiftUIのconfirmationDialog
ではViewをカスタムすることが出来ず困っていたのですが、UIAlertController
の.actionSheet
を使用してやや力技ですがカスタムすることが出来ました。
UIKit
様、この度はお力を借していただきありがとうございました。
是非、皆様のかわいいも作ってみてください。