この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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
様、この度はお力を借していただきありがとうございました。
是非、皆様のかわいいも作ってみてください。