質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1165閲覧

ハーフモーダル画面で、キーボードの高さが変わった際に、ハーフモーダル画面の高さも変えたい!!

masaboy

総合スコア61

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2022/05/06 19:52

実現したいこと

https://github.com/aivars/SlideOverTutorial
を参考にハーフモーダル遷移を実装しました。
このハーフモーダル画面にtextFieldを配置し、キーボードの高さに応じてキーボードの高さも高くすることによって、端末が変わっても、textFieldが隠れないように実装したいです。

発生している問題・エラーメッセージ

keyboardWillShow(notification: NSNotification)でキーボードの高さを取得してから、どうやってハーフモーダルの高さを取得すればいいのかが解りません。
現状のコードだと、viewが大きく上に持ち上がった状態になってしまいます。
なかなか前に進めなくなってしまい、質問させて頂きました。

該当のソースコード

以下コード全文です。

swift.ViewController

1import UIKit 2 3class ViewController: UIViewController { 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 // Do any additional setup after loading the view. 8 } 9 10 @objc func showMiracle() { 11 let slideVC = OverlayView() 12 slideVC.modalPresentationStyle = .custom 13 slideVC.transitioningDelegate = self 14 self.present(slideVC, animated: true, completion: nil) 15 } 16 17 @IBAction func onButton(_ sender: Any) { 18 showMiracle() 19 } 20 21} 22 23extension ViewController: UIViewControllerTransitioningDelegate { 24 func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { 25 PresentationController(presentedViewController: presented, presenting: presenting) 26 } 27}

swift.PresentationController

1import UIKit 2 3class PresentationController: UIPresentationController { 4 5 let blurEffectView: UIVisualEffectView! 6 var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer() 7 8 override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) { 9 let blurEffect = UIBlurEffect(style: .dark) 10 blurEffectView = UIVisualEffectView(effect: blurEffect) 11 super.init(presentedViewController: presentedViewController, presenting: presentingViewController) 12 tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController)) 13 blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 14 self.blurEffectView.isUserInteractionEnabled = true 15 self.blurEffectView.addGestureRecognizer(tapGestureRecognizer) 16 } 17 18 override var frameOfPresentedViewInContainerView: CGRect { 19 CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height * 0.37), 20 size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height * 21 0.63)) 22 } 23 24 override func presentationTransitionWillBegin() { 25 self.blurEffectView.alpha = 0 26 self.containerView?.addSubview(blurEffectView) 27 self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in 28 self.blurEffectView.alpha = 0.7 29 }, completion: { (UIViewControllerTransitionCoordinatorContext) in }) 30 } 31 32 override func dismissalTransitionWillBegin() { 33 self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in 34 self.blurEffectView.alpha = 0 35 }, completion: { (UIViewControllerTransitionCoordinatorContext) in 36 self.blurEffectView.removeFromSuperview() 37 }) 38 } 39 40 override func containerViewWillLayoutSubviews() { 41 super.containerViewWillLayoutSubviews() 42 presentedView!.roundCorners([.topLeft, .topRight], radius: 22) 43 } 44 45 override func containerViewDidLayoutSubviews() { 46 super.containerViewDidLayoutSubviews() 47 presentedView?.frame = frameOfPresentedViewInContainerView 48 blurEffectView.frame = containerView!.bounds 49 } 50 51 @objc func dismissController(){ 52 self.presentedViewController.dismiss(animated: true, completion: nil) 53 } 54} 55 56extension UIView { 57 func roundCorners(_ corners: UIRectCorner, radius: CGFloat) { 58 let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, 59 cornerRadii: CGSize(width: radius, height: radius)) 60 let mask = CAShapeLayer() 61 mask.path = path.cgPath 62 layer.mask = mask 63 } 64}

swift.OverlayView

1import UIKit 2 3class OverlayView: UIViewController { 4 5 @IBOutlet weak var textField: UITextField! 6 var hasSetPointOrigin = false 7 var pointOrigin: CGPoint? 8 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction)) 13 view.addGestureRecognizer(panGesture) 14 textField.keyboardType = .namePhonePad 15 textField.delegate = self 16 textField.becomeFirstResponder() 17 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) 18 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) 19 20 } 21 @objc func keyboardWillShow(notification: NSNotification) { 22 if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { 23 24 25 let suggestionHeight = self.view.frame.origin.y + keyboardSize.height 26 self.view.frame.origin.y -= suggestionHeight 27 } 28 } 29 @objc func keyboardWillHide() { 30 if self.view.frame.origin.y != 0 { 31 self.view.frame.origin.y = 0 32 } 33 } 34 override func viewWillDisappear(_ animated: Bool) { 35 super.viewWillDisappear(animated) 36 NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil) 37 NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) 38 } 39 override func viewDidLayoutSubviews() { 40 if !hasSetPointOrigin { 41 hasSetPointOrigin = true 42 pointOrigin = self.view.frame.origin 43 } 44 45 } 46 @objc func panGestureRecognizerAction(sender: UIPanGestureRecognizer) { 47 let translation = sender.translation(in: view) 48 49 // Not allowing the user to drag the view upward 50 guard translation.y >= 0 else { return } 51 52 // setting x as 0 because we don't want users to move the frame side ways!! Only want straight up or down 53 view.frame.origin = CGPoint(x: 0, y: self.pointOrigin!.y + translation.y) 54 55 if sender.state == .ended { 56 let dragVelocity = sender.velocity(in: view) 57 if dragVelocity.y >= 1300 { 58 self.dismiss(animated: true, completion: nil) 59 } else { 60 // Set back to original position of the view controller 61 UIView.animate(withDuration: 0.3) { 62 self.view.frame.origin = self.pointOrigin ?? CGPoint(x: 0, y: 400) 63 } 64 } 65 } 66 } 67} 68extension OverlayView: UITextFieldDelegate { 69 func textFieldShouldReturn(_ textField: UITextField) -> Bool { 70 textField.resignFirstResponder() 71 return true 72 } 73}

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

関数keyboardWillShowにて

swift.OverlayView

1self.view.frame.origin.y = self.view.frame.height * 1.22 - keyboardSize.height

である程度の高さを狙って改善しました。
完璧では無いですが、とりあえず妥協策とします。

投稿2022/05/19 20:33

masaboy

総合スコア61

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問