LoginSignup
11
12

More than 5 years have passed since last update.

【Swift】TwitterのWebViewが表示されるときのtransitionをやってみた

Last updated at Posted at 2015-06-22

こんな感じです。

SampleTwitterTransition.gif

対応バージョンは iOS7 からです。

GitHub

以下にプロジェクトを置いておきましたので、興味があったらどうぞ

ryokosuge/SampleTwitterTransition

Transition

以下のクラスを作成しました。

ModalTransition.swift
import UIKit

class ModalTransition: NSObject {
}

extension ModalTransition: UIViewControllerTransitioningDelegate {

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

}

extension ModalTransition: UIViewControllerAnimatedTransitioning {

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        let destination: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
        if destination.isBeingPresented() {
            animatePresentedTransition(transitionContext: transitionContext)
        } else {
            animateDismissedTransition(transitionContext: transitionContext)
        }
    }

    func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
        return 0.5
    }
}

// MARK : transition

extension ModalTransition {

    private func animatePresentedTransition(#transitionContext: UIViewControllerContextTransitioning) {
        let duration = transitionDuration(transitionContext)
        let fromViewController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
        let toViewController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
        let containerView = transitionContext.containerView()

        fromViewController.view.frame = containerView.bounds
        toViewController.view.frame = containerView.bounds

        containerView.insertSubview(toViewController.view, belowSubview: fromViewController.view)

        toViewController.view.frame = presentingControllerFrame(transitionContext: transitionContext)
        toViewController.beginAppearanceTransition(true, animated: true)

        UIView.animateKeyframesWithDuration(duration, delay: 0.0, options: .CalculationModeCubic, animations: {
            UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1.0, animations: {
                toViewController.view.frame = containerView.bounds
            })
            UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1.0, animations: {
                var perspectiveTransform = fromViewController.view.layer.transform
                perspectiveTransform.m34 = 1.0 / -1000.0
                perspectiveTransform = CATransform3DTranslate(perspectiveTransform, 0, 0, -100)
                fromViewController.view.layer.transform = perspectiveTransform
            })
        }) { finished in
            fromViewController.view.layer.transform = CATransform3DIdentity
            toViewController.endAppearanceTransition()
            transitionContext.completeTransition(true)
        }

    }

    private func animateDismissedTransition(#transitionContext: UIViewControllerContextTransitioning) {
        let duration = transitionDuration(transitionContext)
        let fromViewController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)
        let toViewController: UIViewController! = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)
        let containerView = transitionContext.containerView()

        fromViewController.view.frame = containerView.bounds
        toViewController.view.frame = containerView.bounds

        containerView.superview?.sendSubviewToBack(containerView)
        containerView.addSubview(toViewController.view)

        let originalTransform = toViewController.view.layer.transform
        var perspectiveTransform = originalTransform
        perspectiveTransform.m34 = 1.0 / -1000.0
        perspectiveTransform = CATransform3DTranslate(perspectiveTransform, 0, 0, -100)
        toViewController.view.layer.transform = perspectiveTransform

        fromViewController.beginAppearanceTransition(false, animated: true)
        let frame = presentingControllerFrame(transitionContext: transitionContext)

        UIView.animateKeyframesWithDuration(duration, delay: 0.0, options: .CalculationModeCubic, animations: {
            UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 1.0, animations: {
                fromViewController.view.frame = frame
            })
            UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.8, animations: {
                toViewController.view.layer.transform = originalTransform
            })
        }) { finished in
            fromViewController.endAppearanceTransition()
            toViewController.view.layer.transform = originalTransform
            toViewController.view.transform = CGAffineTransformIdentity
            transitionContext.completeTransition(true)
        }

    }

    private func presentingControllerFrame(#transitionContext: UIViewControllerContextTransitioning) -> CGRect {
        let bounds = transitionContext.containerView().bounds
        if floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 {
            return CGRect(origin: CGPoint(x: 0, y: bounds.height), size: bounds.size)
        }
        let orientation = UIApplication.sharedApplication().statusBarOrientation
        switch orientation {
        case .LandscapeLeft:
            return CGRect(origin: CGPoint(x: bounds.width, y: 0), size: bounds.size)
        case .LandscapeRight:
            return CGRect(origin: CGPoint(x: -bounds.width, y: 0), size: bounds.size)
        case .Portrait:
            return CGRect(origin: CGPoint(x: 0, y: bounds.height), size: bounds.size)
        case .PortraitUpsideDown:
            return CGRect(origin: CGPoint(x: 0, y: -bounds.height), size: bounds.size)
        case .Unknown:
            return CGRectZero
        }
    }
}

これをUIViewControllertransitioningDelegateに代入すれば、gifみたいなアニメーションができます。

まとめ

はてなカード素敵

はてなカード表示されていないことに今気がつきました。。。

iframeダメなんですね。

11
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12