Help us understand the problem. What is going on with this article?

[iOS] Xibを使って自前のダイアログを作る

More than 3 years have passed since last update.

きっかけ

Androidとおなじにしてよ。っていわれたのが最初のきっかけです。
IDやパスワードを入力したり、カスタマイズがしやすいようにXibでAlertViewが簡単に作れるといいなと思いました。

今までこんな書き方をよく使ってましたが
self.presentViewController(vc, animated: true, completion: nil)

Viewを上に重ねるだけでなく、Alertっぽくしたい!!っていうのが一番の希望。

でも

でも、実際Alertなわけではなく、ViewControllerをAlertっぽくみせているだけです

プロジェクトを作る

シングルビューアプリケーションでプロジェクトを作ります

ss00.png

プロジェクト名を入力します

ss02.png

Alertに使うViewControllerを作ります

メニューからFile-New-FileでCocoa Touch Classを選択します。

ss01.png

ViewControllerの名前をつけます

*Also create XIB fileにチェックをつけます
ss03.png

出来上がったMyAlertViewController.swiftを修正します

*画面遷移のアニメーションをカスタマイズするのでUIViewControllerTransitioningDelegateを追加します
ss04.png

外観のカスタマイズ

MyAlertViewController.Xibにボタンをつけたり、タイトルをつけてMyAlertViewController.swiftとOutletで結んでください。
ss06.png

MyAlertViewController.swiftを編集

3つのinit

1.xibを初期化するinit。背景を透明にしたり、アニメーションをカスタマイズする設定をします

MyAlertViewController.swift
override init(nibName nibNameOrNil:String?, bundle ninBundleOrNil:Bundle? ){
        super.init(nibName:nibNameOrNil,bundle:ninBundleOrNil)
        self.transitioningDelegate = self
        self.providesPresentationContextTransitionStyle = true
        self.definesPresentationContext = true
        self.modalPresentationStyle = .custom

    }

2.実際に使用する初期化処理です

MyAlertViewController.swift
    convenience init(title:String,desc:String){
        self.init(nibName:"MyAlertViewController",bundle:nil)
        titleText = title
        messageText = desc
    }

3.普通のinitは使わないのでエラーにします

MyAlertViewController.swift
    required init?(coder aDecider: NSCoder){
        fatalError("init error")
    }

UIViewControllerTransitioningDelegate

デフォルトのアニメーションだと画面下から上に移動するアニメーションなので書き換えます

MyAlertViewController.swift
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return AlertAnimation(show:true)
    }
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return AlertAnimation(show:false)
    }

アニメーションの実態を書きます

class MyAlertViewController: UIViewController,UIViewControllerTransitioningDelegate {

の最後の括弧「}」が閉じてから下に付け足すか、もしくは別ファイルにしてください

MyAlertViewController.swift
class AlertAnimation : NSObject, UIViewControllerAnimatedTransitioning {

    let show: Bool

    init(show: Bool) {
        self.show = show
    }
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        if (show) {
            return 0.45
        } else {
            return 0.25
        }
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        if (show) {
            self.presentAnimateTransition(transitionContext: transitionContext)
        } else {
            self.dismissAnimateTransition(transitionContext: transitionContext)
        }
    }

    func presentAnimateTransition(transitionContext: UIViewControllerContextTransitioning) {

        let alertVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) as! MyAlertViewController
        alertVC.view.frame = UIScreen.main.bounds
        let containerView = transitionContext.containerView
        alertVC.alertView.alpha = 0.0
        alertVC.alertView.center = alertVC.view.center
        alertVC.alertView.transform = CGAffineTransform.init(scaleX: 0.5, y: 0.5)
        containerView.addSubview(alertVC.view)

        UIView.animate(withDuration: 0.25,
                       animations: {
                                    alertVC.view.alpha = 1.0
                                    alertVC.alertView.alpha = 1.0
                                    alertVC.alertView.transform = CGAffineTransform.init(scaleX: 1.05, y:1.05)
        },
                                   completion: { finished in
                                    UIView.animate(withDuration:0.2,
                                                    animations: {
                                                    alertVC.alertView.transform = CGAffineTransform.identity
                                    },
                                                    completion: { finished in
                                                            if (finished) {
                                                                    transitionContext.completeTransition(true)
                                                            }
                                    })
        })
    }
    func dismissAnimateTransition(transitionContext: UIViewControllerContextTransitioning) {

        let alertVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) as! MyAlertViewController

        UIView.animate(withDuration:self.transitionDuration(using: transitionContext),
                                   animations: {
                                    alertVC.view.alpha = 0.0
                                    alertVC.alertView.alpha = 0.0
                                    alertVC.alertView.transform = CGAffineTransform.init(scaleX: 0.9, y: 0.9)
        },
                                   completion: { finished in
                                    transitionContext.completeTransition(true)
        })
    }
}

ソース

GitHubにおきました

naochi___
サーバーからクライアントからスマホアプリまで。
https://www.interrupt.technology/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away