From ec99ea745655fece224a570a3cbdaef8968e3417 Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 14:35:02 +0800 Subject: [PATCH 01/24] add ConversationMessagePreviewTransitionManager --- Yep.xcodeproj/project.pbxproj | 4 + ...ationMessagePreviewTransitionManager.swift | 100 ++++++++++++++++++ .../ConversationViewController.swift | 19 +++- 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift diff --git a/Yep.xcodeproj/project.pbxproj b/Yep.xcodeproj/project.pbxproj index 1cb2f939..c24b58be 100644 --- a/Yep.xcodeproj/project.pbxproj +++ b/Yep.xcodeproj/project.pbxproj @@ -103,6 +103,7 @@ 506E241E1AE6391A00A33C1A /* TouchZoomButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506E241D1AE6391A00A33C1A /* TouchZoomButton.swift */; }; 506EC20A1AC95BFC00CE42B3 /* UIFont+Yep.swift in Sources */ = {isa = PBXBuildFile; fileRef = 506EC2091AC95BFC00CE42B3 /* UIFont+Yep.swift */; }; 5076C56A1AC46B9F00B22952 /* FayeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5076C5691AC46B9F00B22952 /* FayeService.swift */; }; + 5076FC5A1AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5076FC591AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift */; }; 50894CF11AEA4726000981AF /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50894CF01AEA4726000981AF /* SettingsViewController.swift */; }; 50894CF51AEA4A01000981AF /* SettingsUserCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50894CF31AEA4A01000981AF /* SettingsUserCell.swift */; }; 50894CF61AEA4A01000981AF /* SettingsUserCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50894CF41AEA4A01000981AF /* SettingsUserCell.xib */; }; @@ -273,6 +274,7 @@ 506E241D1AE6391A00A33C1A /* TouchZoomButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TouchZoomButton.swift; path = Views/Buttons/TouchZoomButton.swift; sourceTree = ""; }; 506EC2091AC95BFC00CE42B3 /* UIFont+Yep.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIFont+Yep.swift"; path = "Extensions/UIFont+Yep.swift"; sourceTree = ""; }; 5076C5691AC46B9F00B22952 /* FayeService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FayeService.swift; path = Services/FayeService.swift; sourceTree = ""; }; + 5076FC591AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ConversationMessagePreviewTransitionManager.swift; path = ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift; sourceTree = ""; }; 50894CF01AEA4726000981AF /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingsViewController.swift; path = ViewControllers/Settings/SettingsViewController.swift; sourceTree = ""; }; 50894CF31AEA4A01000981AF /* SettingsUserCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SettingsUserCell.swift; path = Views/Cells/SettingsUser/SettingsUserCell.swift; sourceTree = ""; }; 50894CF41AEA4A01000981AF /* SettingsUserCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SettingsUserCell.xib; path = Views/Cells/SettingsUser/SettingsUserCell.xib; sourceTree = ""; }; @@ -769,6 +771,7 @@ children = ( 503CAB421AC00CB100DFE830 /* ConversationViewController.swift */, 50165C441AC2860900C7AEBE /* ConversationLayout.swift */, + 5076FC591AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift */, ); name = Conversation; sourceTree = ""; @@ -1362,6 +1365,7 @@ 506EC20A1AC95BFC00CE42B3 /* UIFont+Yep.swift in Sources */, 0A0A11821AE389380008772C /* RegisterSkillsLayout.swift in Sources */, 50C0909B1ADE234F00CC6389 /* RegisterPickSkillsViewController.swift in Sources */, + 5076FC5A1AF9DF6B00D7381A /* ConversationMessagePreviewTransitionManager.swift in Sources */, 508D16BD1ADCAF0400270E3F /* PullToRefreshView.swift in Sources */, 508D17441ACCDC9F0092D666 /* VoiceRecordButton.swift in Sources */, 502AE5271AB72D06005BD199 /* YepNetworking.swift in Sources */, diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift new file mode 100644 index 00000000..343a73d1 --- /dev/null +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -0,0 +1,100 @@ +// +// ConversationMessagePreviewTransitionManager.swift +// Yep +// +// Created by NIX on 15/5/6. +// Copyright (c) 2015年 Catch Inc. All rights reserved. +// + +import UIKit + +class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { + + var frame = CGRectZero + + + var isPresentation = false + + // MARK: UIViewControllerTransitioningDelegate + + func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { + isPresentation = true + + return self + } + + func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { + isPresentation = false + + return self + } + + // MARK: UIViewControllerAnimatedTransitioning + + func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { + return 2.6 + } + + func animateTransition(transitionContext: UIViewControllerContextTransitioning) { + + if isPresentation { + presentTransition(transitionContext) + } else { + dismissTransition(transitionContext) + } + } + + func presentTransition(transitionContext: UIViewControllerContextTransitioning) { + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) + let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) + + let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) + let toView = transitionContext.viewForKey(UITransitionContextToViewKey) + + let containerView = transitionContext.containerView() + + containerView.addSubview(toView!) + + let animatingVC = toVC! + let animatingView = toView! + + let finalFrame = transitionContext.finalFrameForViewController(animatingVC) + + animatingView.frame = frame + + UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: .AllowUserInteraction | .BeginFromCurrentState, animations: { () -> Void in + animatingView.frame = finalFrame + + }, completion: { (finished) -> Void in + transitionContext.completeTransition(true) + }) + } + + func dismissTransition(transitionContext: UIViewControllerContextTransitioning) { + //let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) + //let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) + + let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) + //let toView = transitionContext.viewForKey(UITransitionContextToViewKey) + + //let containerView = transitionContext.containerView() + + //containerView.addSubview(toView!) + + //let animatingVC = fromVC! + let animatingView = fromView! + + //let finalFrame = transitionContext.finalFrameForViewController(animatingVC) + + //animatingView.frame = frame + + UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: .AllowUserInteraction | .BeginFromCurrentState, animations: { () -> Void in + animatingView.frame = self.frame + + }, completion: { (finished) -> Void in + animatingView.removeFromSuperview() + transitionContext.completeTransition(true) + }) + } + +} \ No newline at end of file diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 3200f1ae..4bd8f2d0 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -39,6 +39,8 @@ class ConversationViewController: UIViewController { return dateFormatter }() + var messagePreviewTransitionManager: ConversationMessagePreviewTransitionManager? + var conversationCollectionViewHasBeenMovedToBottomOnce = false @@ -900,7 +902,22 @@ class ConversationViewController: UIViewController { override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if segue.identifier == "presentMessageMedia" { let vc = segue.destinationViewController as! MessageMediaViewController - vc.message = sender as? Message + if let message = sender as? Message { + vc.message = message + + let indexPath = NSIndexPath(forRow: Int(messages.indexOfObject(message)) - displayedMessagesRange.location , inSection: 0) + + if let cell = conversationCollectionView.cellForItemAtIndexPath(indexPath) { + let frame = conversationCollectionView.convertRect(cell.frame, toView: view) + vc.modalPresentationStyle = UIModalPresentationStyle.Custom + + let transitionManager = ConversationMessagePreviewTransitionManager() + transitionManager.frame = frame + vc.transitioningDelegate = transitionManager + + messagePreviewTransitionManager = transitionManager + } + } } else if segue.identifier == "presentPickLocation" { let nvc = segue.destinationViewController as! UINavigationController From 03e88967263b9f5099688a5b2de8fb67ace1a8ac Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 15:29:10 +0800 Subject: [PATCH 02/24] use path animation --- ...ationMessagePreviewTransitionManager.swift | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 343a73d1..764b352e 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -15,6 +15,8 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra var isPresentation = false + var transitionContext: UIViewControllerContextTransitioning? + // MARK: UIViewControllerTransitioningDelegate func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { @@ -32,11 +34,13 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra // MARK: UIViewControllerAnimatedTransitioning func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { - return 2.6 + return isPresentation ? 0.5 : 0.5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { + self.transitionContext = transitionContext + if isPresentation { presentTransition(transitionContext) } else { @@ -60,41 +64,49 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let finalFrame = transitionContext.finalFrameForViewController(animatingVC) - animatingView.frame = frame + let initialMaskPath = UIBezierPath(rect: CGRectInset(frame, 50, 0)) + let finalMaskPath = UIBezierPath(rect: finalFrame) - UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: .AllowUserInteraction | .BeginFromCurrentState, animations: { () -> Void in - animatingView.frame = finalFrame + let maskLayer = CAShapeLayer() + maskLayer.path = finalMaskPath.CGPath + animatingView.layer.mask = maskLayer - }, completion: { (finished) -> Void in - transitionContext.completeTransition(true) - }) + let maskLayerAnimation = CABasicAnimation(keyPath: "path") + maskLayerAnimation.fromValue = initialMaskPath.CGPath + maskLayerAnimation.toValue = finalMaskPath.CGPath + maskLayerAnimation.duration = transitionDuration(transitionContext) + maskLayerAnimation.delegate = self + maskLayer.addAnimation(maskLayerAnimation, forKey: "path") } func dismissTransition(transitionContext: UIViewControllerContextTransitioning) { - //let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) - //let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) - //let toView = transitionContext.viewForKey(UITransitionContextToViewKey) - //let containerView = transitionContext.containerView() - - //containerView.addSubview(toView!) - - //let animatingVC = fromVC! + let animatingVC = fromVC! let animatingView = fromView! - //let finalFrame = transitionContext.finalFrameForViewController(animatingVC) + let initialFrame = transitionContext.initialFrameForViewController(animatingVC) - //animatingView.frame = frame + let initialMaskPath = UIBezierPath(rect: initialFrame) + let finalMaskPath = UIBezierPath(rect: CGRectInset(frame, 50, 0)) - UIView.animateWithDuration(transitionDuration(transitionContext), delay: 0, options: .AllowUserInteraction | .BeginFromCurrentState, animations: { () -> Void in - animatingView.frame = self.frame + let maskLayer = CAShapeLayer() + maskLayer.path = finalMaskPath.CGPath + animatingView.layer.mask = maskLayer - }, completion: { (finished) -> Void in - animatingView.removeFromSuperview() - transitionContext.completeTransition(true) - }) + let maskLayerAnimation = CABasicAnimation(keyPath: "path") + maskLayerAnimation.fromValue = initialMaskPath.CGPath + maskLayerAnimation.toValue = finalMaskPath.CGPath + maskLayerAnimation.duration = transitionDuration(transitionContext) + maskLayerAnimation.delegate = self + maskLayerAnimation.removedOnCompletion = true + maskLayer.addAnimation(maskLayerAnimation, forKey: "path") + } + + override func animationDidStop(anim: CAAnimation!, finished flag: Bool) { + transitionContext?.completeTransition(true) } } \ No newline at end of file From 6a888588a580d61c5f3482fa5a4d1a15aa8d0f0f Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 16:27:09 +0800 Subject: [PATCH 03/24] real media frame --- ...ationMessagePreviewTransitionManager.swift | 4 +- .../ConversationViewController.swift | 45 ++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 764b352e..bfa6ee27 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -64,7 +64,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let finalFrame = transitionContext.finalFrameForViewController(animatingVC) - let initialMaskPath = UIBezierPath(rect: CGRectInset(frame, 50, 0)) + let initialMaskPath = UIBezierPath(rect: frame) let finalMaskPath = UIBezierPath(rect: finalFrame) let maskLayer = CAShapeLayer() @@ -90,7 +90,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let initialFrame = transitionContext.initialFrameForViewController(animatingVC) let initialMaskPath = UIBezierPath(rect: initialFrame) - let finalMaskPath = UIBezierPath(rect: CGRectInset(frame, 50, 0)) + let finalMaskPath = UIBezierPath(rect: frame) let maskLayer = CAShapeLayer() maskLayer.path = finalMaskPath.CGPath diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 4bd8f2d0..0de6861a 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -908,7 +908,50 @@ class ConversationViewController: UIViewController { let indexPath = NSIndexPath(forRow: Int(messages.indexOfObject(message)) - displayedMessagesRange.location , inSection: 0) if let cell = conversationCollectionView.cellForItemAtIndexPath(indexPath) { - let frame = conversationCollectionView.convertRect(cell.frame, toView: view) + + var frame = CGRectZero + + if let sender = message.fromFriend { + if sender.friendState != UserFriendState.Me.rawValue { + switch message.mediaType { + + case MessageMediaType.Image.rawValue: + let cell = cell as! ChatLeftImageCell + frame = cell.convertRect(cell.messageImageView.frame, toView: view) + + case MessageMediaType.Video.rawValue: + let cell = cell as! ChatLeftVideoCell + frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) + + case MessageMediaType.Location.rawValue: + let cell = cell as! ChatLeftLocationCell + frame = cell.convertRect(cell.mapImageView.frame, toView: view) + + default: + break + } + + } else { + switch message.mediaType { + + case MessageMediaType.Image.rawValue: + let cell = cell as! ChatRightImageCell + frame = cell.convertRect(cell.messageImageView.frame, toView: view) + + case MessageMediaType.Video.rawValue: + let cell = cell as! ChatRightVideoCell + frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) + + case MessageMediaType.Location.rawValue: + let cell = cell as! ChatRightLocationCell + frame = cell.convertRect(cell.mapImageView.frame, toView: view) + + default: + break + } + } + } + vc.modalPresentationStyle = UIModalPresentationStyle.Custom let transitionManager = ConversationMessagePreviewTransitionManager() From 256bdf198d676f0cf9ee4d6765a6ce4ad2a1410d Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 17:02:28 +0800 Subject: [PATCH 04/24] media imageView AspectFit --- Yep/Views/Media/MediaView.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Yep/Views/Media/MediaView.swift b/Yep/Views/Media/MediaView.swift index d607bb33..f848dc7c 100644 --- a/Yep/Views/Media/MediaView.swift +++ b/Yep/Views/Media/MediaView.swift @@ -13,14 +13,14 @@ class MediaView: UIView { lazy var imageView: UIImageView = { let imageView = UIImageView() - imageView.contentMode = .ScaleAspectFill + imageView.contentMode = .ScaleAspectFit return imageView }() lazy var videoPlayerLayer: AVPlayerLayer = { let player = AVPlayer() let playerLayer = AVPlayerLayer(player: player) - playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill + playerLayer.videoGravity = AVLayerVideoGravityResizeAspect //playerLayer.backgroundColor = UIColor.darkGrayColor().CGColor return playerLayer }() @@ -31,7 +31,8 @@ class MediaView: UIView { makeUI() layer.addSublayer(videoPlayerLayer) - videoPlayerLayer.frame = bounds + videoPlayerLayer.frame = UIScreen.mainScreen().bounds + println("videoPlayerLayer.frame: \(videoPlayerLayer.frame)") } func makeUI() { From a0edae6ca487ede28c891471f63170217abce4b1 Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 18:42:41 +0800 Subject: [PATCH 05/24] zoom in --- ...ationMessagePreviewTransitionManager.swift | 100 +++++++++++++++++- .../ConversationViewController.swift | 9 ++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index bfa6ee27..04b15450 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -11,6 +11,8 @@ import UIKit class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { var frame = CGRectZero + var transitionView: UIView? + var isPresentation = false @@ -34,7 +36,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra // MARK: UIViewControllerAnimatedTransitioning func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { - return isPresentation ? 0.5 : 0.5 + return isPresentation ? 0.7 : 0.5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { @@ -48,6 +50,100 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra } } + func presentTransition(transitionContext: UIViewControllerContextTransitioning) { + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? ConversationsViewController + let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? MessageMediaViewController + + let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) + let toView = transitionContext.viewForKey(UITransitionContextToViewKey) + + let containerView = transitionContext.containerView() + + containerView.addSubview(toView!) + + let animatingVC = toVC! + let animatingView = toView! + + let finalFrame = transitionContext.finalFrameForViewController(animatingVC) + + let initialMaskPath = UIBezierPath(rect: frame) + let finalMaskPath = UIBezierPath(rect: finalFrame) + + let maskLayer = CAShapeLayer() + maskLayer.path = finalMaskPath.CGPath + animatingView.layer.mask = maskLayer + + let maskLayerAnimation = CABasicAnimation(keyPath: "path") + maskLayerAnimation.fromValue = finalMaskPath.CGPath + maskLayerAnimation.toValue = finalMaskPath.CGPath + maskLayerAnimation.duration = transitionDuration(transitionContext) + maskLayerAnimation.delegate = self + maskLayer.addAnimation(maskLayerAnimation, forKey: "path") + + + + if let transitionView = transitionView { + animatingView.addSubview(transitionView) + transitionView.frame = frame + + toVC?.mediaView.alpha = 0 + + let fullDuration = transitionDuration(transitionContext) + + UIView.animateWithDuration(fullDuration * 0.6, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in + transitionView.center = animatingView.center + + }, completion: { finished in + + UIView.animateWithDuration(fullDuration * 0.4, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in + + let dw = animatingView.bounds.width - transitionView.bounds.width + let ratio = animatingView.bounds.width / transitionView.bounds.width + let height = ratio * transitionView.bounds.height + let dh = height - transitionView.bounds.height + + let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) + + transitionView.frame = frame + + }, completion: { finished in + toVC?.mediaView.alpha = 1 + transitionView.removeFromSuperview() + }) + + }) + } + } + + func dismissTransition(transitionContext: UIViewControllerContextTransitioning) { + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) + + let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) + + let animatingVC = fromVC! + let animatingView = fromView! + + let initialFrame = transitionContext.initialFrameForViewController(animatingVC) + + let initialMaskPath = UIBezierPath(rect: initialFrame) + let finalMaskPath = UIBezierPath(rect: frame) + + let maskLayer = CAShapeLayer() + maskLayer.path = finalMaskPath.CGPath + animatingView.layer.mask = maskLayer + + let maskLayerAnimation = CABasicAnimation(keyPath: "path") + maskLayerAnimation.fromValue = initialMaskPath.CGPath + maskLayerAnimation.toValue = finalMaskPath.CGPath + maskLayerAnimation.duration = transitionDuration(transitionContext) + maskLayerAnimation.delegate = self + maskLayerAnimation.removedOnCompletion = true + maskLayer.addAnimation(maskLayerAnimation, forKey: "path") + + + } + + #if XXX func presentTransition(transitionContext: UIViewControllerContextTransitioning) { let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) @@ -104,9 +200,9 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra maskLayerAnimation.removedOnCompletion = true maskLayer.addAnimation(maskLayerAnimation, forKey: "path") } + #endif override func animationDidStop(anim: CAAnimation!, finished flag: Bool) { transitionContext?.completeTransition(true) } - } \ No newline at end of file diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index 0de6861a..eea210f4 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -910,6 +910,7 @@ class ConversationViewController: UIViewController { if let cell = conversationCollectionView.cellForItemAtIndexPath(indexPath) { var frame = CGRectZero + var transitionView: UIView? if let sender = message.fromFriend { if sender.friendState != UserFriendState.Me.rawValue { @@ -917,14 +918,17 @@ class ConversationViewController: UIViewController { case MessageMediaType.Image.rawValue: let cell = cell as! ChatLeftImageCell + transitionView = cell.messageImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.messageImageView.frame, toView: view) case MessageMediaType.Video.rawValue: let cell = cell as! ChatLeftVideoCell + transitionView = cell.thumbnailImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) case MessageMediaType.Location.rawValue: let cell = cell as! ChatLeftLocationCell + transitionView = cell.mapImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.mapImageView.frame, toView: view) default: @@ -936,14 +940,17 @@ class ConversationViewController: UIViewController { case MessageMediaType.Image.rawValue: let cell = cell as! ChatRightImageCell + transitionView = cell.messageImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.messageImageView.frame, toView: view) case MessageMediaType.Video.rawValue: let cell = cell as! ChatRightVideoCell + transitionView = cell.thumbnailImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) case MessageMediaType.Location.rawValue: let cell = cell as! ChatRightLocationCell + transitionView = cell.mapImageView.snapshotViewAfterScreenUpdates(false) frame = cell.convertRect(cell.mapImageView.frame, toView: view) default: @@ -956,6 +963,8 @@ class ConversationViewController: UIViewController { let transitionManager = ConversationMessagePreviewTransitionManager() transitionManager.frame = frame + transitionManager.transitionView = transitionView + vc.transitioningDelegate = transitionManager messagePreviewTransitionManager = transitionManager From bba1799e3c7588d1ee23b7e6c860be0e2abbf03f Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 19:13:17 +0800 Subject: [PATCH 06/24] animation detail --- Yep/Base.lproj/Main.storyboard | 2 +- ...ationMessagePreviewTransitionManager.swift | 52 +++++++++++++------ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/Yep/Base.lproj/Main.storyboard b/Yep/Base.lproj/Main.storyboard index a1486c2a..73f9cf01 100644 --- a/Yep/Base.lproj/Main.storyboard +++ b/Yep/Base.lproj/Main.storyboard @@ -244,7 +244,7 @@ - + diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 04b15450..f0c42c5d 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -36,7 +36,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra // MARK: UIViewControllerAnimatedTransitioning func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { - return isPresentation ? 0.7 : 0.5 + return isPresentation ? 0.9 : 0.5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { @@ -86,31 +86,49 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra animatingView.addSubview(transitionView) transitionView.frame = frame + toVC?.view.backgroundColor = UIColor.clearColor() toVC?.mediaView.alpha = 0 let fullDuration = transitionDuration(transitionContext) - UIView.animateWithDuration(fullDuration * 0.6, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in - transitionView.center = animatingView.center + UIView.animateWithDuration(fullDuration * 0.2, delay: 0.0, options: .CurveEaseInOut, animations: { _ in + animatingVC.view.backgroundColor = UIColor.whiteColor() }, completion: { finished in - - UIView.animateWithDuration(fullDuration * 0.4, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in - - let dw = animatingView.bounds.width - transitionView.bounds.width - let ratio = animatingView.bounds.width / transitionView.bounds.width - let height = ratio * transitionView.bounds.height - let dh = height - transitionView.bounds.height - - let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) - - transitionView.frame = frame + UIView.animateWithDuration(fullDuration * 0.5, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in + transitionView.center = animatingView.center }, completion: { finished in - toVC?.mediaView.alpha = 1 - transitionView.removeFromSuperview() - }) + let largerOffset: CGFloat = 80 + + UIView.animateWithDuration(fullDuration * 0.2, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in + + let targetWidth = animatingView.bounds.width + largerOffset + + let dw = targetWidth - transitionView.bounds.width + let ratio = targetWidth / transitionView.bounds.width + let height = ratio * transitionView.bounds.height + let dh = height - transitionView.bounds.height + + let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) + + transitionView.frame = frame + + }, completion: { finished in + + let ratio = (animatingView.bounds.width + largerOffset) / animatingView.bounds.width + toVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) + toVC?.mediaView.alpha = 1 + transitionView.removeFromSuperview() + + UIView.animateWithDuration(fullDuration * 0.1, delay: 0.0, options: .CurveEaseInOut, animations: { _ in + toVC?.mediaView.transform = CGAffineTransformMakeScale(1.0, 1.0) + }, completion: { finished in + toVC?.mediaView.transform = CGAffineTransformIdentity + }) + }) + }) }) } } From 6fb3403f7979ec14abdd01f15abc068d7b9e45fe Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 19:33:09 +0800 Subject: [PATCH 07/24] sexy keyframe present animation --- ...ationMessagePreviewTransitionManager.swift | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index f0c42c5d..33cdd1bf 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -36,7 +36,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra // MARK: UIViewControllerAnimatedTransitioning func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { - return isPresentation ? 0.9 : 0.5 + return isPresentation ? 0.5 : 0.5 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { @@ -91,6 +91,47 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let fullDuration = transitionDuration(transitionContext) + UIView.animateKeyframesWithDuration(fullDuration, delay: 0.0, options: .CalculationModeCubic, animations: { () -> Void in + + UIView.addKeyframeWithRelativeStartTime(0, relativeDuration: 0.2, animations: { () -> Void in + animatingVC.view.backgroundColor = UIColor.whiteColor() + }) + + UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.5, animations: { () -> Void in + transitionView.center = animatingView.center + }) + + let largerOffset: CGFloat = 80 + + UIView.addKeyframeWithRelativeStartTime(0.7, relativeDuration: 0.2, animations: { () -> Void in + let targetWidth = animatingView.bounds.width + largerOffset + + let dw = targetWidth - transitionView.bounds.width + let ratio = targetWidth / transitionView.bounds.width + let height = ratio * transitionView.bounds.height + let dh = height - transitionView.bounds.height + + let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) + + transitionView.frame = frame + }) + + UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.0, animations: { () -> Void in + let ratio = (animatingView.bounds.width + largerOffset) / animatingView.bounds.width + toVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) + toVC?.mediaView.alpha = 1 + transitionView.alpha = 0 + }) + + UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.1, animations: { () -> Void in + toVC?.mediaView.transform = CGAffineTransformMakeScale(1.0, 1.0) + }) + + }, completion: { (finished) -> Void in + + }) + + #if YYY UIView.animateWithDuration(fullDuration * 0.2, delay: 0.0, options: .CurveEaseInOut, animations: { _ in animatingVC.view.backgroundColor = UIColor.whiteColor() @@ -130,6 +171,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) }) }) + #endif } } From 747281bc338b49d28b1b67b8235ce91fbd079a6e Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 21:28:52 +0800 Subject: [PATCH 08/24] dismiss keyframe animation --- ...ationMessagePreviewTransitionManager.swift | 88 +++++++++---------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 33cdd1bf..4f72aa65 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -50,6 +50,9 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra } } + + let largerOffset: CGFloat = 80 + func presentTransition(transitionContext: UIViewControllerContextTransitioning) { let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? ConversationsViewController let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? MessageMediaViewController @@ -81,7 +84,6 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra maskLayer.addAnimation(maskLayerAnimation, forKey: "path") - if let transitionView = transitionView { animatingView.addSubview(transitionView) transitionView.frame = frame @@ -101,10 +103,9 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra transitionView.center = animatingView.center }) - let largerOffset: CGFloat = 80 UIView.addKeyframeWithRelativeStartTime(0.7, relativeDuration: 0.2, animations: { () -> Void in - let targetWidth = animatingView.bounds.width + largerOffset + let targetWidth = animatingView.bounds.width + self.largerOffset let dw = targetWidth - transitionView.bounds.width let ratio = targetWidth / transitionView.bounds.width @@ -117,7 +118,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.0, animations: { () -> Void in - let ratio = (animatingView.bounds.width + largerOffset) / animatingView.bounds.width + let ratio = (animatingView.bounds.width + self.largerOffset) / animatingView.bounds.width toVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) toVC?.mediaView.alpha = 1 transitionView.alpha = 0 @@ -128,55 +129,14 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) }, completion: { (finished) -> Void in - + transitionView.removeFromSuperview() }) - #if YYY - UIView.animateWithDuration(fullDuration * 0.2, delay: 0.0, options: .CurveEaseInOut, animations: { _ in - animatingVC.view.backgroundColor = UIColor.whiteColor() - - }, completion: { finished in - UIView.animateWithDuration(fullDuration * 0.5, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in - transitionView.center = animatingView.center - - }, completion: { finished in - - let largerOffset: CGFloat = 80 - - UIView.animateWithDuration(fullDuration * 0.2, delay: 0.0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.0, options: UIViewAnimationOptions(0), animations: { _ in - - let targetWidth = animatingView.bounds.width + largerOffset - - let dw = targetWidth - transitionView.bounds.width - let ratio = targetWidth / transitionView.bounds.width - let height = ratio * transitionView.bounds.height - let dh = height - transitionView.bounds.height - - let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) - - transitionView.frame = frame - - }, completion: { finished in - - let ratio = (animatingView.bounds.width + largerOffset) / animatingView.bounds.width - toVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) - toVC?.mediaView.alpha = 1 - transitionView.removeFromSuperview() - - UIView.animateWithDuration(fullDuration * 0.1, delay: 0.0, options: .CurveEaseInOut, animations: { _ in - toVC?.mediaView.transform = CGAffineTransformMakeScale(1.0, 1.0) - }, completion: { finished in - toVC?.mediaView.transform = CGAffineTransformIdentity - }) - }) - }) - }) - #endif } } func dismissTransition(transitionContext: UIViewControllerContextTransitioning) { - let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? MessageMediaViewController let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) @@ -194,13 +154,45 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let maskLayerAnimation = CABasicAnimation(keyPath: "path") maskLayerAnimation.fromValue = initialMaskPath.CGPath - maskLayerAnimation.toValue = finalMaskPath.CGPath + maskLayerAnimation.toValue = initialMaskPath.CGPath maskLayerAnimation.duration = transitionDuration(transitionContext) maskLayerAnimation.delegate = self maskLayerAnimation.removedOnCompletion = true maskLayer.addAnimation(maskLayerAnimation, forKey: "path") + let fullDuration = transitionDuration(transitionContext) + + if let transitionView = transitionView { + + UIView.animateKeyframesWithDuration(fullDuration, delay: 0.0, options: .CalculationModeCubic, animations: { () -> Void in + + UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.2, animations: { () -> Void in + let ratio = (animatingView.bounds.width + self.largerOffset) / animatingView.bounds.width + fromVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) + }) + + UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.0, animations: { () -> Void in + animatingView.addSubview(transitionView) + transitionView.center = animatingView.center + transitionView.alpha = 1 + + fromVC?.mediaView.alpha = 0 + }) + + UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.5, animations: { () -> Void in + transitionView.frame = self.frame + }) + + UIView.addKeyframeWithRelativeStartTime(0.7, relativeDuration: 0.3, animations: { () -> Void in + animatingVC.view.backgroundColor = UIColor.clearColor() + }) + + }, completion: { (finished) -> Void in + transitionView.removeFromSuperview() + }) + } + } #if XXX From 0a7f10f8f147804dab1ee7cf5246a1ba9e819d3d Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 21:34:42 +0800 Subject: [PATCH 09/24] clean code --- ...ationMessagePreviewTransitionManager.swift | 127 +++--------------- 1 file changed, 18 insertions(+), 109 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 4f72aa65..4409a62b 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -14,7 +14,6 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra var transitionView: UIView? - var isPresentation = false var transitionContext: UIViewControllerContextTransitioning? @@ -67,29 +66,12 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let animatingVC = toVC! let animatingView = toView! - let finalFrame = transitionContext.finalFrameForViewController(animatingVC) - - let initialMaskPath = UIBezierPath(rect: frame) - let finalMaskPath = UIBezierPath(rect: finalFrame) - - let maskLayer = CAShapeLayer() - maskLayer.path = finalMaskPath.CGPath - animatingView.layer.mask = maskLayer - - let maskLayerAnimation = CABasicAnimation(keyPath: "path") - maskLayerAnimation.fromValue = finalMaskPath.CGPath - maskLayerAnimation.toValue = finalMaskPath.CGPath - maskLayerAnimation.duration = transitionDuration(transitionContext) - maskLayerAnimation.delegate = self - maskLayer.addAnimation(maskLayerAnimation, forKey: "path") - - if let transitionView = transitionView { animatingView.addSubview(transitionView) transitionView.frame = frame - toVC?.view.backgroundColor = UIColor.clearColor() - toVC?.mediaView.alpha = 0 + animatingVC.view.backgroundColor = UIColor.clearColor() + animatingVC.mediaView.alpha = 0 let fullDuration = transitionDuration(transitionContext) @@ -119,19 +101,23 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.0, animations: { () -> Void in let ratio = (animatingView.bounds.width + self.largerOffset) / animatingView.bounds.width - toVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) - toVC?.mediaView.alpha = 1 + animatingVC.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) + animatingVC.mediaView.alpha = 1 transitionView.alpha = 0 }) UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.1, animations: { () -> Void in - toVC?.mediaView.transform = CGAffineTransformMakeScale(1.0, 1.0) + animatingVC.mediaView.transform = CGAffineTransformMakeScale(1.0, 1.0) }) }, completion: { (finished) -> Void in transitionView.removeFromSuperview() + + transitionContext.completeTransition(true) }) + } else { + transitionContext.completeTransition(false) } } @@ -143,24 +129,6 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let animatingVC = fromVC! let animatingView = fromView! - let initialFrame = transitionContext.initialFrameForViewController(animatingVC) - - let initialMaskPath = UIBezierPath(rect: initialFrame) - let finalMaskPath = UIBezierPath(rect: frame) - - let maskLayer = CAShapeLayer() - maskLayer.path = finalMaskPath.CGPath - animatingView.layer.mask = maskLayer - - let maskLayerAnimation = CABasicAnimation(keyPath: "path") - maskLayerAnimation.fromValue = initialMaskPath.CGPath - maskLayerAnimation.toValue = initialMaskPath.CGPath - maskLayerAnimation.duration = transitionDuration(transitionContext) - maskLayerAnimation.delegate = self - maskLayerAnimation.removedOnCompletion = true - maskLayer.addAnimation(maskLayerAnimation, forKey: "path") - - let fullDuration = transitionDuration(transitionContext) if let transitionView = transitionView { @@ -169,7 +137,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra UIView.addKeyframeWithRelativeStartTime(0.0, relativeDuration: 0.2, animations: { () -> Void in let ratio = (animatingView.bounds.width + self.largerOffset) / animatingView.bounds.width - fromVC?.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) + animatingVC.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) }) UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.0, animations: { () -> Void in @@ -177,84 +145,25 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra transitionView.center = animatingView.center transitionView.alpha = 1 - fromVC?.mediaView.alpha = 0 + animatingVC.mediaView.alpha = 0 }) - UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.5, animations: { () -> Void in + UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.6, animations: { () -> Void in transitionView.frame = self.frame }) - UIView.addKeyframeWithRelativeStartTime(0.7, relativeDuration: 0.3, animations: { () -> Void in + UIView.addKeyframeWithRelativeStartTime(0.8, relativeDuration: 0.2, animations: { () -> Void in animatingVC.view.backgroundColor = UIColor.clearColor() }) }, completion: { (finished) -> Void in transitionView.removeFromSuperview() + + transitionContext.completeTransition(true) }) + + } else { + transitionContext.completeTransition(false) } - - } - - #if XXX - func presentTransition(transitionContext: UIViewControllerContextTransitioning) { - let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) - let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) - - let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) - let toView = transitionContext.viewForKey(UITransitionContextToViewKey) - - let containerView = transitionContext.containerView() - - containerView.addSubview(toView!) - - let animatingVC = toVC! - let animatingView = toView! - - let finalFrame = transitionContext.finalFrameForViewController(animatingVC) - - let initialMaskPath = UIBezierPath(rect: frame) - let finalMaskPath = UIBezierPath(rect: finalFrame) - - let maskLayer = CAShapeLayer() - maskLayer.path = finalMaskPath.CGPath - animatingView.layer.mask = maskLayer - - let maskLayerAnimation = CABasicAnimation(keyPath: "path") - maskLayerAnimation.fromValue = initialMaskPath.CGPath - maskLayerAnimation.toValue = finalMaskPath.CGPath - maskLayerAnimation.duration = transitionDuration(transitionContext) - maskLayerAnimation.delegate = self - maskLayer.addAnimation(maskLayerAnimation, forKey: "path") - } - - func dismissTransition(transitionContext: UIViewControllerContextTransitioning) { - let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) - - let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) - - let animatingVC = fromVC! - let animatingView = fromView! - - let initialFrame = transitionContext.initialFrameForViewController(animatingVC) - - let initialMaskPath = UIBezierPath(rect: initialFrame) - let finalMaskPath = UIBezierPath(rect: frame) - - let maskLayer = CAShapeLayer() - maskLayer.path = finalMaskPath.CGPath - animatingView.layer.mask = maskLayer - - let maskLayerAnimation = CABasicAnimation(keyPath: "path") - maskLayerAnimation.fromValue = initialMaskPath.CGPath - maskLayerAnimation.toValue = finalMaskPath.CGPath - maskLayerAnimation.duration = transitionDuration(transitionContext) - maskLayerAnimation.delegate = self - maskLayerAnimation.removedOnCompletion = true - maskLayer.addAnimation(maskLayerAnimation, forKey: "path") - } - #endif - - override func animationDidStop(anim: CAAnimation!, finished flag: Bool) { - transitionContext?.completeTransition(true) } } \ No newline at end of file From b2e211c7f759196548d009df4433c7ff52ecea2f Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 21:47:10 +0800 Subject: [PATCH 10/24] better logic for hide transitionView first when dismiss (feel better) --- ...ationMessagePreviewTransitionManager.swift | 56 ++++++++++++------- .../ConversationViewController.swift | 12 ++-- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift index 4409a62b..1804d616 100644 --- a/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift +++ b/Yep/ViewControllers/Conversation/ConversationMessagePreviewTransitionManager.swift @@ -11,7 +11,14 @@ import UIKit class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { var frame = CGRectZero - var transitionView: UIView? + var transitionView: UIView? { + didSet { + if let transitionView = transitionView { + transitionViewSnapshot = transitionView.snapshotViewAfterScreenUpdates(false) + } + } + } + var transitionViewSnapshot: UIView? var isPresentation = false @@ -66,9 +73,10 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let animatingVC = toVC! let animatingView = toView! - if let transitionView = transitionView { - animatingView.addSubview(transitionView) - transitionView.frame = frame + if let transitionViewSnapshot = transitionViewSnapshot { + + animatingView.addSubview(transitionViewSnapshot) + transitionViewSnapshot.frame = frame animatingVC.view.backgroundColor = UIColor.clearColor() animatingVC.mediaView.alpha = 0 @@ -82,28 +90,29 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.5, animations: { () -> Void in - transitionView.center = animatingView.center + transitionViewSnapshot.center = animatingView.center }) UIView.addKeyframeWithRelativeStartTime(0.7, relativeDuration: 0.2, animations: { () -> Void in let targetWidth = animatingView.bounds.width + self.largerOffset - let dw = targetWidth - transitionView.bounds.width - let ratio = targetWidth / transitionView.bounds.width - let height = ratio * transitionView.bounds.height - let dh = height - transitionView.bounds.height + let dw = targetWidth - transitionViewSnapshot.bounds.width + let ratio = targetWidth / transitionViewSnapshot.bounds.width + let height = ratio * transitionViewSnapshot.bounds.height + let dh = height - transitionViewSnapshot.bounds.height - let frame = CGRectInset(transitionView.frame, -dw * 0.5, -dh * 0.5) + let frame = CGRectInset(transitionViewSnapshot.frame, -dw * 0.5, -dh * 0.5) - transitionView.frame = frame + transitionViewSnapshot.frame = frame }) UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.0, animations: { () -> Void in let ratio = (animatingView.bounds.width + self.largerOffset) / animatingView.bounds.width animatingVC.mediaView.transform = CGAffineTransformMakeScale(ratio, ratio) animatingVC.mediaView.alpha = 1 - transitionView.alpha = 0 + + transitionViewSnapshot.alpha = 0 }) UIView.addKeyframeWithRelativeStartTime(0.9, relativeDuration: 0.1, animations: { () -> Void in @@ -111,7 +120,7 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) }, completion: { (finished) -> Void in - transitionView.removeFromSuperview() + transitionViewSnapshot.removeFromSuperview() transitionContext.completeTransition(true) }) @@ -131,7 +140,11 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra let fullDuration = transitionDuration(transitionContext) - if let transitionView = transitionView { + if let transitionViewSnapshot = transitionViewSnapshot { + + if let transitionView = self.transitionView { + transitionView.alpha = 0 + } UIView.animateKeyframesWithDuration(fullDuration, delay: 0.0, options: .CalculationModeCubic, animations: { () -> Void in @@ -141,15 +154,15 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.0, animations: { () -> Void in - animatingView.addSubview(transitionView) - transitionView.center = animatingView.center - transitionView.alpha = 1 + animatingView.addSubview(transitionViewSnapshot) + transitionViewSnapshot.center = animatingView.center + transitionViewSnapshot.alpha = 1 animatingVC.mediaView.alpha = 0 }) UIView.addKeyframeWithRelativeStartTime(0.2, relativeDuration: 0.6, animations: { () -> Void in - transitionView.frame = self.frame + transitionViewSnapshot.frame = self.frame }) UIView.addKeyframeWithRelativeStartTime(0.8, relativeDuration: 0.2, animations: { () -> Void in @@ -157,7 +170,12 @@ class ConversationMessagePreviewTransitionManager: NSObject, UIViewControllerTra }) }, completion: { (finished) -> Void in - transitionView.removeFromSuperview() + + if let transitionView = self.transitionView { + transitionView.alpha = 1 + } + + transitionViewSnapshot.removeFromSuperview() transitionContext.completeTransition(true) }) diff --git a/Yep/ViewControllers/Conversation/ConversationViewController.swift b/Yep/ViewControllers/Conversation/ConversationViewController.swift index eea210f4..3c786d5a 100644 --- a/Yep/ViewControllers/Conversation/ConversationViewController.swift +++ b/Yep/ViewControllers/Conversation/ConversationViewController.swift @@ -918,17 +918,17 @@ class ConversationViewController: UIViewController { case MessageMediaType.Image.rawValue: let cell = cell as! ChatLeftImageCell - transitionView = cell.messageImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.messageImageView frame = cell.convertRect(cell.messageImageView.frame, toView: view) case MessageMediaType.Video.rawValue: let cell = cell as! ChatLeftVideoCell - transitionView = cell.thumbnailImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.thumbnailImageView frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) case MessageMediaType.Location.rawValue: let cell = cell as! ChatLeftLocationCell - transitionView = cell.mapImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.mapImageView frame = cell.convertRect(cell.mapImageView.frame, toView: view) default: @@ -940,17 +940,17 @@ class ConversationViewController: UIViewController { case MessageMediaType.Image.rawValue: let cell = cell as! ChatRightImageCell - transitionView = cell.messageImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.messageImageView frame = cell.convertRect(cell.messageImageView.frame, toView: view) case MessageMediaType.Video.rawValue: let cell = cell as! ChatRightVideoCell - transitionView = cell.thumbnailImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.thumbnailImageView frame = cell.convertRect(cell.thumbnailImageView.frame, toView: view) case MessageMediaType.Location.rawValue: let cell = cell as! ChatRightLocationCell - transitionView = cell.mapImageView.snapshotViewAfterScreenUpdates(false) + transitionView = cell.mapImageView frame = cell.convertRect(cell.mapImageView.frame, toView: view) default: From c3cbe9cd1753c2241fc17480389e290ed0a5635c Mon Sep 17 00:00:00 2001 From: kevinzhow Date: Wed, 6 May 2015 22:05:34 +0800 Subject: [PATCH 11/24] Fix video gravity --- Yep/Base.lproj/Main.storyboard | 2 +- Yep/Views/Media/MediaView.swift | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Yep/Base.lproj/Main.storyboard b/Yep/Base.lproj/Main.storyboard index 73f9cf01..ecf16e7d 100644 --- a/Yep/Base.lproj/Main.storyboard +++ b/Yep/Base.lproj/Main.storyboard @@ -71,7 +71,7 @@ - + diff --git a/Yep/Views/Media/MediaView.swift b/Yep/Views/Media/MediaView.swift index f848dc7c..8b241f5a 100644 --- a/Yep/Views/Media/MediaView.swift +++ b/Yep/Views/Media/MediaView.swift @@ -31,9 +31,14 @@ class MediaView: UIView { makeUI() layer.addSublayer(videoPlayerLayer) - videoPlayerLayer.frame = UIScreen.mainScreen().bounds + println("videoPlayerLayer.frame: \(videoPlayerLayer.frame)") } + + override func layoutSubviews() { + videoPlayerLayer.frame = UIScreen.mainScreen().bounds + super.layoutSubviews() + } func makeUI() { From c8acd5ebc111d004a05117b4aaa9188727466229 Mon Sep 17 00:00:00 2001 From: nixzhu Date: Wed, 6 May 2015 22:36:18 +0800 Subject: [PATCH 12/24] fix upload video thumbnail key --- Yep/Services/YepService.swift | 16 +++++++++++++--- Yep/Views/Media/MediaView.swift | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Yep/Services/YepService.swift b/Yep/Services/YepService.swift index 6efb27d8..f8ec70da 100644 --- a/Yep/Services/YepService.swift +++ b/Yep/Services/YepService.swift @@ -1081,15 +1081,25 @@ func sendMessageWithMediaType(mediaType: MessageMediaType, inFilePath filePath: thumbnailData = UIImageJPEGRepresentation(image, YepConfig.messageImageCompressionQuality()) } - s3PrivateUploadParams(failureHandler: nil) { s3UploadParams in + s3PrivateUploadParams(failureHandler: nil) { thumbnailS3UploadParams in uploadFileToS3(inFilePath: nil, orFileData: thumbnailData, mimeType: MessageMediaType.Image.mineType(), s3UploadParams: s3UploadParams) { (result, error) in if let metaData = metaData { - let attachments = ["video": [["file": s3UploadParams.key, "metadata": metaData]], "thumbnail": [["file": s3UploadParams.key]]] + let attachments = [ + "video": [ + ["file": s3UploadParams.key, "metadata": metaData] + ], + "thumbnail": [["file": thumbnailS3UploadParams.key]] + ] messageInfo["attachments"] = attachments } else { - let attachments = ["video": [["file": s3UploadParams.key]], "thumbnail": [["file": s3UploadParams.key]]] + let attachments = [ + "video": [ + ["file": s3UploadParams.key] + ], + "thumbnail": [["file": thumbnailS3UploadParams.key]] + ] messageInfo["attachments"] = attachments } diff --git a/Yep/Views/Media/MediaView.swift b/Yep/Views/Media/MediaView.swift index 8b241f5a..c7b723c2 100644 --- a/Yep/Views/Media/MediaView.swift +++ b/Yep/Views/Media/MediaView.swift @@ -36,8 +36,9 @@ class MediaView: UIView { } override func layoutSubviews() { - videoPlayerLayer.frame = UIScreen.mainScreen().bounds super.layoutSubviews() + + videoPlayerLayer.frame = UIScreen.mainScreen().bounds } func makeUI() { From 8a5890e026a4d43f0fcb63e3e5eb64e7dca96c2b Mon Sep 17 00:00:00 2001 From: nixzhu Date: Thu, 7 May 2015 00:04:23 +0800 Subject: [PATCH 13/24] fix thumbnail uploadFileToS3 --- Yep/Services/YepService.swift | 2 +- .../MessageMedia/MessageMediaViewController.swift | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Yep/Services/YepService.swift b/Yep/Services/YepService.swift index f8ec70da..ad7184a5 100644 --- a/Yep/Services/YepService.swift +++ b/Yep/Services/YepService.swift @@ -1082,7 +1082,7 @@ func sendMessageWithMediaType(mediaType: MessageMediaType, inFilePath filePath: } s3PrivateUploadParams(failureHandler: nil) { thumbnailS3UploadParams in - uploadFileToS3(inFilePath: nil, orFileData: thumbnailData, mimeType: MessageMediaType.Image.mineType(), s3UploadParams: s3UploadParams) { (result, error) in + uploadFileToS3(inFilePath: nil, orFileData: thumbnailData, mimeType: MessageMediaType.Image.mineType(), s3UploadParams: thumbnailS3UploadParams) { (result, error) in if let metaData = metaData { let attachments = [ diff --git a/Yep/ViewControllers/MessageMedia/MessageMediaViewController.swift b/Yep/ViewControllers/MessageMedia/MessageMediaViewController.swift index 3b1d0d3e..b78c637b 100644 --- a/Yep/ViewControllers/MessageMedia/MessageMediaViewController.swift +++ b/Yep/ViewControllers/MessageMedia/MessageMediaViewController.swift @@ -37,7 +37,6 @@ class MessageMediaViewController: UIViewController { let x = NSFileManager.defaultManager().fileExistsAtPath(videoFileURL.path!) - mediaView.videoPlayerLayer.frame = mediaView.bounds playerItem.seekToTime(kCMTimeZero) //mediaView.videoPlayerLayer.player.replaceCurrentItemWithPlayerItem(playerItem) mediaView.videoPlayerLayer.player = AVPlayer(playerItem: playerItem) From c99b3312e0d586d41dfd874f56a3106cb2f9e2f2 Mon Sep 17 00:00:00 2001 From: nixzhu Date: Thu, 7 May 2015 00:05:53 +0800 Subject: [PATCH 14/24] fix downloadAttachmentOfMessage for thumbnail --- Yep/Services/YepServiceSync.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Yep/Services/YepServiceSync.swift b/Yep/Services/YepServiceSync.swift index 1c69ad4f..e3884405 100644 --- a/Yep/Services/YepServiceSync.swift +++ b/Yep/Services/YepServiceSync.swift @@ -70,7 +70,7 @@ func downloadAttachmentOfMessage(message: Message) { let thumbnailURLString = message.thumbnailURLString if !thumbnailURLString.isEmpty && message.localThumbnailName.isEmpty { - if let url = NSURL(string: attachmentURLString) { + if let url = NSURL(string: thumbnailURLString) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { let data = NSData(contentsOfURL: url) From 73abd6da0bf096628972718dd561b1e7542bcc5a Mon Sep 17 00:00:00 2001 From: nixzhu Date: Thu, 7 May 2015 01:59:25 +0800 Subject: [PATCH 15/24] add MediaControlView --- Yep.xcodeproj/project.pbxproj | 4 ++ Yep/Base.lproj/Main.storyboard | 29 ++++++---- Yep/Views/Media/MediaControlView.swift | 74 ++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 Yep/Views/Media/MediaControlView.swift diff --git a/Yep.xcodeproj/project.pbxproj b/Yep.xcodeproj/project.pbxproj index c24b58be..a9434762 100644 --- a/Yep.xcodeproj/project.pbxproj +++ b/Yep.xcodeproj/project.pbxproj @@ -144,6 +144,7 @@ 50CDBE461ACA9F2200459CE0 /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE451ACA9F2200459CE0 /* ImageCache.swift */; }; 50CDBE491ACBAD3200459CE0 /* ChatLeftImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */; }; 50CDBE4A1ACBAD3200459CE0 /* ChatLeftImageCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */; }; + 50D4D0DB1AFA825B005AEB6F /* MediaControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50D4D0DA1AFA825B005AEB6F /* MediaControlView.swift */; }; 50E114F41ABBF9CC00F13000 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F31ABBF9CC00F13000 /* Models.swift */; }; 50E114F71ABBFA7000F13000 /* RLMSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F61ABBFA7000F13000 /* RLMSupport.swift */; }; 50E114F91ABC137A00F13000 /* YepServiceSync.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50E114F81ABC137A00F13000 /* YepServiceSync.swift */; }; @@ -315,6 +316,7 @@ 50CDBE451ACA9F2200459CE0 /* ImageCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Caches/ImageCache.swift; sourceTree = ""; }; 50CDBE471ACBAD3200459CE0 /* ChatLeftImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChatLeftImageCell.swift; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.swift; sourceTree = ""; }; 50CDBE481ACBAD3200459CE0 /* ChatLeftImageCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = ChatLeftImageCell.xib; path = Views/Cells/ChatLeftImage/ChatLeftImageCell.xib; sourceTree = ""; }; + 50D4D0DA1AFA825B005AEB6F /* MediaControlView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MediaControlView.swift; path = Views/Media/MediaControlView.swift; sourceTree = ""; }; 50E114F31ABBF9CC00F13000 /* Models.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Models.swift; path = Realm/Models.swift; sourceTree = ""; }; 50E114F61ABBFA7000F13000 /* RLMSupport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RLMSupport.swift; path = Realm/RLMSupport.swift; sourceTree = ""; }; 50E114F81ABC137A00F13000 /* YepServiceSync.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = YepServiceSync.swift; path = Services/YepServiceSync.swift; sourceTree = ""; }; @@ -1063,6 +1065,7 @@ isa = PBXGroup; children = ( 50EB8CCA1AEA1AC0001AC1EE /* MediaView.swift */, + 50D4D0DA1AFA825B005AEB6F /* MediaControlView.swift */, ); name = Media; sourceTree = ""; @@ -1330,6 +1333,7 @@ 508D174C1ACCF49B0092D666 /* ChatRightAudioCell.swift in Sources */, 502AE53D1AB87C0D005BD199 /* YepUserDefaults.swift in Sources */, 50EB8CC41AE89F12001AC1EE /* ChatRightVideoCell.swift in Sources */, + 50D4D0DB1AFA825B005AEB6F /* MediaControlView.swift in Sources */, 508D17471ACCF4710092D666 /* ChatLeftAudioCell.swift in Sources */, 50894D021AEA6433000981AF /* EditProfileLessInfoCell.swift in Sources */, 50894CFA1AEA54BA000981AF /* SettingsMoreCell.swift in Sources */, diff --git a/Yep/Base.lproj/Main.storyboard b/Yep/Base.lproj/Main.storyboard index ecf16e7d..8c766bf1 100644 --- a/Yep/Base.lproj/Main.storyboard +++ b/Yep/Base.lproj/Main.storyboard @@ -72,14 +72,14 @@ - + - + - - -