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

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

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

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

解決済

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

masaboy
masaboy

総合スコア55

Swift

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

1回答

0評価

0クリップ

126閲覧

投稿2022/05/06 19:52

実現したいこと

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

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

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

該当のソースコード

以下コード全文です。

swift.ViewController

import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } @objc func showMiracle() { let slideVC = OverlayView() slideVC.modalPresentationStyle = .custom slideVC.transitioningDelegate = self self.present(slideVC, animated: true, completion: nil) } @IBAction func onButton(_ sender: Any) { showMiracle() } } extension ViewController: UIViewControllerTransitioningDelegate { func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? { PresentationController(presentedViewController: presented, presenting: presenting) } }

swift.PresentationController

import UIKit class PresentationController: UIPresentationController { let blurEffectView: UIVisualEffectView! var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer() override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) { let blurEffect = UIBlurEffect(style: .dark) blurEffectView = UIVisualEffectView(effect: blurEffect) super.init(presentedViewController: presentedViewController, presenting: presentingViewController) tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController)) blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] self.blurEffectView.isUserInteractionEnabled = true self.blurEffectView.addGestureRecognizer(tapGestureRecognizer) } override var frameOfPresentedViewInContainerView: CGRect { CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height * 0.37), size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height * 0.63)) } override func presentationTransitionWillBegin() { self.blurEffectView.alpha = 0 self.containerView?.addSubview(blurEffectView) self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in self.blurEffectView.alpha = 0.7 }, completion: { (UIViewControllerTransitionCoordinatorContext) in }) } override func dismissalTransitionWillBegin() { self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in self.blurEffectView.alpha = 0 }, completion: { (UIViewControllerTransitionCoordinatorContext) in self.blurEffectView.removeFromSuperview() }) } override func containerViewWillLayoutSubviews() { super.containerViewWillLayoutSubviews() presentedView!.roundCorners([.topLeft, .topRight], radius: 22) } override func containerViewDidLayoutSubviews() { super.containerViewDidLayoutSubviews() presentedView?.frame = frameOfPresentedViewInContainerView blurEffectView.frame = containerView!.bounds } @objc func dismissController(){ self.presentedViewController.dismiss(animated: true, completion: nil) } } extension UIView { func roundCorners(_ corners: UIRectCorner, radius: CGFloat) { let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) let mask = CAShapeLayer() mask.path = path.cgPath layer.mask = mask } }

swift.OverlayView

import UIKit class OverlayView: UIViewController { @IBOutlet weak var textField: UITextField! var hasSetPointOrigin = false var pointOrigin: CGPoint? override func viewDidLoad() { super.viewDidLoad() let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction)) view.addGestureRecognizer(panGesture) textField.keyboardType = .namePhonePad textField.delegate = self textField.becomeFirstResponder() NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) } @objc func keyboardWillShow(notification: NSNotification) { if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { let suggestionHeight = self.view.frame.origin.y + keyboardSize.height self.view.frame.origin.y -= suggestionHeight } } @objc func keyboardWillHide() { if self.view.frame.origin.y != 0 { self.view.frame.origin.y = 0 } } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil) NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil) } override func viewDidLayoutSubviews() { if !hasSetPointOrigin { hasSetPointOrigin = true pointOrigin = self.view.frame.origin } } @objc func panGestureRecognizerAction(sender: UIPanGestureRecognizer) { let translation = sender.translation(in: view) // Not allowing the user to drag the view upward guard translation.y >= 0 else { return } // setting x as 0 because we don't want users to move the frame side ways!! Only want straight up or down view.frame.origin = CGPoint(x: 0, y: self.pointOrigin!.y + translation.y) if sender.state == .ended { let dragVelocity = sender.velocity(in: view) if dragVelocity.y >= 1300 { self.dismiss(animated: true, completion: nil) } else { // Set back to original position of the view controller UIView.animate(withDuration: 0.3) { self.view.frame.origin = self.pointOrigin ?? CGPoint(x: 0, y: 400) } } } } } extension OverlayView: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } }

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

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

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

まだ回答がついていません

会員登録して回答してみよう

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

ただいまの回答率
87.20%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Swift

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