在iOS上进行深度页面转换

我正在尝试创build一个animation,如Facebook菜单向下滑动POP框架的animation或完全像InShorts应用程序 。 Android文档涵盖了这个..但是在iOS中找不到任何提示。

我所尝试的是将细胞转化为

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { UIView.animateWithDuration(0.1, animations: { () -> Void in cell.transform = CGAffineTransformMakeScale(0.8, 0.8) }) } 

但是,这并不像预期的那样工作。使用Google Googling,我发现这正是我想要实现的。 但是它在UIView 。 我认为这是最适合的,如果我们在UITableViewCellanimation? 我真的很感激有人愿意帮助这个问题。 这是我正在开发的启动项目

这个效果可以使用UICollectionView获得。这里是UICollectionViewFlowLayout类。

 class UltravisualLayout: UICollectionViewLayout { private var contentWidth:CGFloat! private var contentHeight:CGFloat! private var yOffset:CGFloat = 0 var maxAlpha:CGFloat = 1 var minAlpha:CGFloat = 0 var widthOffset:CGFloat = 35 var heightOffset:CGFloat = 35 private var cache = [UICollectionViewLayoutAttributes]() private var itemWidth:CGFloat{ return (collectionView?.bounds.width)! } private var itemHeight:CGFloat{ return (collectionView?.bounds.height)! } private var collectionViewHeight:CGFloat{ return (collectionView?.bounds.height)! } private var numberOfItems:Int{ return (collectionView?.numberOfItemsInSection(0))! } private var dragOffset:CGFloat{ return (collectionView?.bounds.height)! } private var currentItemIndex:Int{ return max(0, Int(collectionView!.contentOffset.y / collectionViewHeight)) } var nextItemBecomeCurrentPercentage:CGFloat{ return (collectionView!.contentOffset.y / (collectionViewHeight)) - CGFloat(currentItemIndex) } override func prepareLayout() { cache.removeAll(keepCapacity: false) yOffset = 0 for item in 0 ..< numberOfItems{ let indexPath = NSIndexPath(forItem: item, inSection: 0) let attribute = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) attribute.zIndex = -indexPath.row if (indexPath.item == currentItemIndex+1) && (indexPath.item < numberOfItems){ attribute.alpha = minAlpha + max((maxAlpha-minAlpha) * nextItemBecomeCurrentPercentage, 0) let width = itemWidth - widthOffset + (widthOffset * nextItemBecomeCurrentPercentage) let height = itemHeight - heightOffset + (heightOffset * nextItemBecomeCurrentPercentage) let deltaWidth = width/itemWidth let deltaHeight = height/itemHeight attribute.frame = CGRectMake(0, yOffset, itemWidth, itemHeight) attribute.transform = CGAffineTransformMakeScale(deltaWidth, deltaHeight) attribute.center.y = (collectionView?.center.y)! + (collectionView?.contentOffset.y)! attribute.center.x = (collectionView?.center.x)! + (collectionView?.contentOffset.x)! yOffset += collectionViewHeight }else{ attribute.frame = CGRectMake(0, yOffset, itemWidth, itemHeight) attribute.center.y = (collectionView?.center.y)! + yOffset attribute.center.x = (collectionView?.center.x)! yOffset += collectionViewHeight } cache.append(attribute) } } //Return the size of ContentView override func collectionViewContentSize() -> CGSize { contentWidth = (collectionView?.bounds.width)! contentHeight = CGFloat(numberOfItems) * (collectionView?.bounds.height)! return CGSizeMake(contentWidth, contentHeight) } //Return Attributes whose frame lies in the Visible Rect override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { var layoutAttributes = [UICollectionViewLayoutAttributes]() for attribute in cache{ if CGRectIntersectsRect(attribute.frame, rect){ layoutAttributes.append(attribute) } } return layoutAttributes } override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { return true } override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { let itemIndex = round(proposedContentOffset.y / (dragOffset)) let yOffset = itemIndex * (collectionView?.bounds.height)! return CGPoint(x: 0, y: yOffset) } override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { // Logic that calculates the UICollectionViewLayoutAttributes of the item // and returns the UICollectionViewLayoutAttributes return UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) } } 

这是演示项目链接 …

非常感谢这个教程 。

如果你想要什么InShortsvideo正在做,我build议使用视图控制器转换 。 一个有用的文章在这里 。

下面是您要实现的完整示例代码。 为了简洁起见,我在应用程序委托中实现了这一切,但是您绝对应该将其分解为不同的类。

video: 这里

更新的代码

 import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDelegate, UIViewControllerAnimatedTransitioning { var window: UIWindow? var percentManager: UIPercentDrivenInteractiveTransition? /** Keep track of which way the animation is going */ var isPopping = false /** The index of the view controller that is currently presented. */ var index: Int { get { guard let lastVC = navController.viewControllers.last as? ViewController else { return NSNotFound } return lastVC.index } } /** Acting as a very basic data source. - Note: When this value is set the navigation stack is reset and the first VC is created */ var count: Int = 0 { didSet { guard count > 0 else { return } // load the first view controller navController.setViewControllers([ViewController(index: 0)], animated: true) } } lazy var navController: UINavigationController = { // create a navigation controller and hide it's nav bar let navController = UINavigationController() navController.navigationBar.hidden = true return navController }() func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // add the nav controller (and it's first view controller) to the window window = UIWindow(frame: UIScreen.mainScreen().bounds) window?.rootViewController = navController window?.makeKeyAndVisible() // add a pan recognizer to the nav controller let panRecognizer = UIPanGestureRecognizer(target: self, action: Selector("didPan:")) navController.view.addGestureRecognizer(panRecognizer) navController.delegate = self // update the 'data source' count = 5 return true } internal func didPan(recognizer: UIPanGestureRecognizer) { guard let view = recognizer.view else { assertionFailure("no view"); return } switch (recognizer.state) { case .Began: // detect if it is an upward swipe if recognizer.velocityInView(view).y < 0 { // don't go out of bounds guard index + 1 < count else { recognizer.enabled = false; recognizer.enabled = true; return } isPopping = false // create the percentManager and start pushing the next view controller percentManager = UIPercentDrivenInteractiveTransition() navController.pushViewController(ViewController(index: index+1), animated: true) } // detect if it is a downward swipe else if recognizer.velocityInView(view).y > 0 { // don't go out of bounds guard index - 1 >= 0 else { recognizer.enabled = false; recognizer.enabled = true; return } isPopping = true // create the percentManager and start popping the current view controller percentManager = UIPercentDrivenInteractiveTransition() navController.popViewControllerAnimated(true) } case .Changed: // update the percent manager let translation = recognizer.translationInView(view) let percentOffset = translation.y/CGRectGetHeight(view.bounds) * (isPopping ? 1 : -1) percentManager?.updateInteractiveTransition(percentOffset) case .Ended: // give the percent manager it's final instruction before niling it if isPopping { if recognizer.velocityInView(view).y > 0 { percentManager?.finishInteractiveTransition() } else { percentManager?.cancelInteractiveTransition() } } else { if recognizer.velocityInView(view).y < 0 { percentManager?.finishInteractiveTransition() } else { percentManager?.cancelInteractiveTransition() } } percentManager = nil default: break } } // MARK: UINavigationControllerDelegate func navigationController(navigationController: UINavigationController, interactionControllerForAnimationController animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { return percentManager } func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { return self } // MARK: UIViewControllerAnimatedTransitioning func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { return 0.4 } func animateTransition(transitionContext: UIViewControllerContextTransitioning) { guard let newVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as? ViewController else { assertionFailure("no new view controller"); return } guard let oldVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as? ViewController else { assertionFailure("no existing view controller"); return } let scaleTransform = CGAffineTransformMakeScale(0.9, 0.9) let yOffsetTransform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(oldVC.view.frame)) let isPopping = newVC.index < oldVC.index let animationBlock: Void -> Void if isPopping == true { // place the previous vc at the top of the screen newVC.view.transform = yOffsetTransform animationBlock = { oldVC.view.transform = scaleTransform newVC.view.transform = CGAffineTransformIdentity } // add the views onto the transition view controller transitionContext.containerView()?.addSubview(oldVC.view) transitionContext.containerView()?.addSubview(newVC.view) } else { // scale the new view a bit smaller newVC.view.transform = scaleTransform // slide the old view controller up and scale the new view controller back to 100% animationBlock = { oldVC.view.transform = yOffsetTransform newVC.view.transform = CGAffineTransformIdentity } // add the views onto the transition view controller transitionContext.containerView()?.addSubview(newVC.view) transitionContext.containerView()?.addSubview(oldVC.view) } // perform the animation UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: animationBlock, completion: { finished in // cleanup oldVC.view.transform = CGAffineTransformIdentity newVC.view.transform = CGAffineTransformIdentity transitionContext.completeTransition(!transitionContext.transitionWasCancelled()) }) } } class ViewController: UIViewController { let index: Int init(index: Int) { self.index = index super.init(nibName: nil, bundle: nil) } override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor(red: CGFloat((arc4random()%255))/255.0, green: CGFloat((arc4random()%255))/255.0, blue: CGFloat((arc4random()%255))/255.0, alpha: 1) view.layer.cornerRadius = 12 } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } } 

更新

根据你的video我整理出你想要做什么样的animation。 所以这次我的做法

  1. 使用3个视图引用,这是前一个当前下一个
  2. 将平移手势添加到持有这些视图(当前self.view )的视图中,并实现平移触摸的三种状态
  3. 根据手势logging应用转场,并排列视图
  4. 一些学分在GitHub上的这个图书馆,这真的帮了我很多。

这段代码有简单的视图,它们的背景相应于我们在颜色数组上的颜色数量。 所以在你的情况下,你可以创build自定义的XIB视图,而不是颜色,你可以添加自己的数据源。 🙂

 import UIKit class StackedViewController: UIViewController { var previousView: UIView! = nil var currentView: UIView! = nil var nextView: UIView! = nil var currentIndex = 0 let colors: [UIColor] = [.redColor(), .greenColor(), .yellowColor(), .grayColor()] var offset: CGFloat = CGFloat() // MARK: - View lifecycle override func viewDidLoad() { super.viewDidLoad() // Set the offset offset = 64.0 setupViews() } // MARK: - Setups func setupViews() { self.view.backgroundColor = .blackColor() self.currentView = getCurrentView() self.view.addSubview(currentView) let pan = UIPanGestureRecognizer(target: self, action: "panAction:") self.view.addGestureRecognizer(pan) } // MARK: - Actions func panAction(gesture:UIPanGestureRecognizer){ let p = gesture.translationInView(self.view) // Edge cases to disable panning when the view stack is finished if py < 0 && getPreviousView() == nil || py > 0 && getNextView() == nil { return } if gesture.state == .Began { if let prev = getPreviousView() { self.previousView = prev self.view.addSubview(prev) prev.frame = self.view.frame prev.center = CGPointMake(self.view.bounds.width/2, self.view.bounds.height/2) self.view.sendSubviewToBack(previousView) } if let next = getNextView() { self.nextView = next self.view.addSubview(next) next.frame = CGRect(origin: CGPoint(x: 0, y: -self.view.bounds.height), size: self.view.frame.size) } } else if gesture.state == .Changed { UIView.animateWithDuration(0.1, animations: { () -> Void in if py < 0 { self.previousView.hidden = false self.currentView.center.y = self.view.bounds.height/2 + py self.previousView.center.y = self.view.bounds.height/2 // Transforming ratio from 0-1 to 0.9-1 let ratio = (-py/CGRectGetHeight(self.view.bounds)) let lightRatio = 0.9 + (ratio/10) // Apply transformation self.apply3DDepthTransform(self.previousView, ratio: lightRatio) } else if py > 0 { self.currentView.center.y = self.view.bounds.height/2 let prevPosY = -self.view.bounds.height/2 + py if prevPosY < self.view.bounds.height/2 { self.nextView?.center.y = prevPosY } else { self.nextView?.center.y = self.view.bounds.height/2 } // Transforming ratio from 0-1 to 0.9-1 let ratio = py/CGRectGetHeight(self.view.bounds) let lightRatio = 1 - (ratio/10) // Apply transformation self.apply3DDepthTransform(self.currentView, ratio: lightRatio) // Hide the background view when showing another because the edges of this will be shown due to transformation if self.previousView != nil { self.previousView.hidden = true } } }) } else if gesture.state == .Ended { UIView.animateWithDuration(0.5, delay: 0, options: [.CurveEaseOut], animations: { () -> Void in if py < -self.offset && self.previousView != nil { // Showing previous item self.currentView.center.y = -self.view.bounds.height/2 // Finish the whole transition self.apply3DDepthTransform(self.previousView, ratio: 1) } else if py > self.offset && self.nextView != nil { // Showing next item self.nextView?.center.y = self.view.bounds.height/2 // Finish the whole transition self.apply3DDepthTransform(self.currentView, ratio: 0.9) } else { // The pan has not passed offset so just return to the main coordinates self.previousView?.center.y = -self.view.bounds.height/2 self.currentView.center.y = self.view.bounds.height/2 } }, completion: { (_) -> Void in if py < -self.offset && self.previousView != nil { self.currentView = self.getPreviousView() self.currentIndex = (self.currentIndex > 0) ? self.currentIndex - 1 : self.currentIndex; } else if py > self.offset && self.nextView != nil { self.currentView = self.getNextView() self.currentIndex = (self.currentIndex == self.colors.count - 1) ? self.currentIndex : self.currentIndex + 1; } // Remove all views and show the currentView for view in self.view.subviews { view.removeFromSuperview() } self.previousView = nil self.nextView = nil self.view.addSubview(self.currentView) self.currentView.center = CGPointMake(self.view.bounds.width/2, self.view.bounds.height/2) }) } } // MARK: - Helpers func getCurrentView() -> UIView? { let current = UIView(frame: self.view.frame) current.backgroundColor = colors[currentIndex] return current } func getNextView() -> UIView? { if currentIndex >= colors.count - 1 { return nil } let next = UIView(frame: self.view.frame) next.backgroundColor = colors[currentIndex + 1] return next } func getPreviousView() -> UIView? { if currentIndex <= 0 { return nil } let prev = UIView(frame: self.view.frame) prev.backgroundColor = colors[currentIndex - 1] return prev } // MARK: Animation func apply3DDepthTransform(view: UIView, ratio: CGFloat) { view.layer.transform = CATransform3DMakeScale(ratio, ratio, ratio) view.alpha = 1 - ((1 - ratio)*10) } } 

产量

在这里输入图像说明

原始答复

你可以只用需要的单元格,而不必使用UIViewController进行自定义转换

解决scheme包括:

  1. 跟踪2个单元格,一个是主持人( 演示Cell ),一个是将要呈现的( isBeingPresentedCell
  2. 实现scrollViewDidScroll:它协调整个操作,因为一切都依赖于scrollingOffset
  3. 处理滚动的方向,以select哪个单元格作为演示者,以及正在呈现哪个单元格
  4. 每当一个单元格将被出队,它将被设置为一个身份转换,因为在正常的屏幕上我们只有一个单元格显示
  5. 保持覆盖整个框架的矩形的比例因子,以便在变换中应用正确的因子
  6. ****您在ViewControllerAutolayout上遇到了一些问题。 请清除现有约束,用tableView填充视图,然后从顶部 (非顶部布局指南 )将其设置为0px。

没有更多的谈话,代码自己谈论(这也是一些评论)

 import UIKit enum ViewControllerScrollDirection: Int { case Up case Down case None } class ViewController: UIViewController { @IBOutlet weak var menuTableView: UITableView! var colors :[UIColor] = [UIColor.greenColor(),UIColor.grayColor(),UIColor.purpleColor(),UIColor.redColor()] var presenterCell: UITableViewCell! = nil var isBeingPresentedCell: UITableViewCell! = nil var lastContentOffset: CGFloat = CGFloat() var scrollDirection: ViewControllerScrollDirection = .None // MARK: - View Lifecycle override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. menuTableView.dataSource = self menuTableView.delegate = self menuTableView.pagingEnabled = true } } extension ViewController:UITableViewDataSource,UITableViewDelegate { // MARK: - Delegation // MARK: TableView Datasource func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell cell.contentView.backgroundColor = colors[indexPath.row] cell.backgroundColor = UIColor.blackColor() cell.contentView.layer.transform = CATransform3DIdentity cell.selectionStyle = .None return cell } // MARK: TableView Delegate func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return self.view.frame.size.height } // MARK: ScrollView Delegate func scrollViewDidScroll(scrollView: UIScrollView) { self.scrollDirection = getScrollDirection(scrollView) // The cells in visible cells are ordered, so depending on scroll we set the one that we want to present if self.scrollDirection == .Up { self.presenterCell = menuTableView.visibleCells.last self.isBeingPresentedCell = menuTableView.visibleCells.first } else { self.presenterCell = menuTableView.visibleCells.first self.isBeingPresentedCell = menuTableView.visibleCells.last } // If we have the same cells or either of them is nil don't do anything if (self.isBeingPresentedCell == nil || self.presenterCell == nil) { return; } else if (self.isBeingPresentedCell == self.presenterCell) { return; } // Always animate the presenter cell to the identity (fixes the problem when changing direction on pan gesture) UIView.animateWithDuration(0.1, animations: { () -> Void in self.presenterCell.contentView.layer.transform = CATransform3DIdentity; }) // Get the indexPath guard let indexPath = menuTableView.indexPathForCell(presenterCell) else { return; } // Get the frame for that indexPath let frame = menuTableView.rectForRowAtIndexPath(indexPath) // Find how much vertical space is the isBeingPresented cell using on the frame and return always the positive value var diffY = frame.origin.y - self.lastContentOffset diffY = (diffY > 0) ? diffY : -diffY // Find the ratio from 0-1 which corresponds on transformation from 0.8-1 var ratio = CGFloat(diffY/CGRectGetHeight(self.menuTableView.frame)) ratio = 0.8 + (ratio/5) // Make the animation UIView.animateWithDuration(0.1, animations: { () -> Void in self.isBeingPresentedCell.contentView.layer.transform = CATransform3DMakeScale(ratio, ratio, ratio) }) } // MARK: - Helpers func getScrollDirection(scrollView: UIScrollView) -> ViewControllerScrollDirection { let scrollDirection = (self.lastContentOffset > scrollView.contentOffset.y) ? ViewControllerScrollDirection.Down : ViewControllerScrollDirection.Up self.lastContentOffset = scrollView.contentOffset.y; return scrollDirection } } 

UI修复

在这里输入图像说明

输出animation

在这里输入图像说明

希望它会填补你的要求:)

使用Facebook的POPanimation对于拖放的视图与animationrest

 private func resetViewPositionAndTransformations() { let resetPositionAnimation = POPSpringAnimation(propertyNamed: kPOPLayerTranslationXY) resetPositionAnimation.fromValue = NSValue(CGPoint: CGPoint(x: dragDistance.x, y: dragDistance.y)) resetPositionAnimation.toValue = NSValue(CGPoint: CGPointZero) resetPositionAnimation.springBounciness = cardResetAnimationSpringBounciness resetPositionAnimation.springSpeed = cardResetAnimationSpringSpeed resetPositionAnimation.completionBlock = { (_, _) in self.layer.transform = CATransform3DIdentity } layer.pop_addAnimation(resetPositionAnimation, forKey: "resetPositionAnimation") let resetRotationAnimation = POPBasicAnimation(propertyNamed: kPOPLayerRotation) resetRotationAnimation.fromValue = POPLayerGetRotationZ(layer) resetRotationAnimation.toValue = CGFloat(0.0) resetRotationAnimation.duration = cardResetAnimationDuration layer.pop_addAnimation(resetRotationAnimation, forKey: "resetRotationAnimation") let overlayAlphaAnimation = POPBasicAnimation(propertyNamed: kPOPViewAlpha) overlayAlphaAnimation.toValue = 0.0 overlayAlphaAnimation.duration = cardResetAnimationDuration overlayAlphaAnimation.completionBlock = { _, _ in } overlayView?.pop_addAnimation(overlayAlphaAnimation, forKey: "resetOverlayAnimation") let resetScaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY) resetScaleAnimation.toValue = NSValue(CGPoint: CGPoint(x: 1.0, y: 1.0)) resetScaleAnimation.duration = cardResetAnimationDuration layer.pop_addAnimation(resetScaleAnimation, forKey: "resetScaleAnimation") } 

在我看来, UICollectionviewUICollectionViewLayout更适合这样的事情。 UITableView不会给你每个滚动变换,你会需要做各种肮脏的黑客。

如果你使用UICollectionview ,你所寻找的是-[UICollectionViewLayout layoutAttributesForElementsInRect:]-[UICollectionViewLayout shouldInvalidateLayoutForBoundsChange:] ,其他的一切都是有点math的。

试试这个:你可以用我们的脸书/stream行的https://github.com/facebook/pop来获得更stream畅的效果&#x3002; 这个代码只是给你一些想法,没有太多的testing。

 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("cell") if cell?.contentView.viewWithTag(100) == nil { let view = UIView(frame: (cell?.contentView.bounds)!) view.tag = 100 view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight] cell?.contentView.addSubview(view) } if cell!.contentView.viewWithTag(100) != nil { let view = cell!.contentView.viewWithTag(100) view!.backgroundColor = colors[indexPath.row] } return cell! } func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return self.view.frame.size.height - 20 } func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { if cell.contentView.viewWithTag(100) != nil { let view = cell.contentView.viewWithTag(100) let basicAnimation = CABasicAnimation(keyPath: "transform.scale") basicAnimation.toValue = NSNumber(float: 1) basicAnimation.fromValue = NSNumber(float: 0.8) basicAnimation.duration = 0.4 basicAnimation.removedOnCompletion = false view!.layer.addAnimation(basicAnimation, forKey: "transform.scale") } // if tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row - 1, inSection: 0)) != nil // { // let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row - 1, inSection: 0)) // if cell!.contentView.viewWithTag(100) != nil // { // let view = cell!.contentView.viewWithTag(100) // let basicAnimation = CABasicAnimation(keyPath: "transform.scale") // basicAnimation.toValue = NSNumber(float: 0.8) // basicAnimation.fromValue = NSNumber(float: 1) // basicAnimation.duration = 0.4 // basicAnimation.removedOnCompletion = false // view!.layer.addAnimation(basicAnimation, forKey: "transform.scale") // } // } // if tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row + 1, inSection: 0)) != nil // { // let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexPath.row + 1, inSection: 0)) // // if cell!.contentView.viewWithTag(100) != nil // { // let view = cell!.contentView.viewWithTag(100) // let basicAnimation = CABasicAnimation(keyPath: "transform.scale") // basicAnimation.toValue = NSNumber(float: 0.8) // basicAnimation.fromValue = NSNumber(float: 1) // basicAnimation.duration = 0.4 // basicAnimation.removedOnCompletion = false // view!.layer.addAnimation(basicAnimation, forKey: "transform.scale") // } // } // let scaleAnimation = POPDecayAnimation(propertyNamed: kPOPLayerScaleXY) // scaleAnimation.fromValue = NSValue(CGSize: CGSize(width: 0.8, height: 0.8)) // scaleAnimation.toValue = NSValue(CGSize: CGSize(width: 1, height: 1)) // cell.contentView.layer.pop_addAnimation(scaleAnimation, forKey: "kPOPLayerScaleXY") // UIView.animateWithDuration(0.1, animations: { () -> Void in // cell.transform = CGAffineTransformMakeScale(0.8, 0.8) // }) }