我正在尝试创建一个类似于POP框架的Facebook菜单滑动动画或类似于InShorts App的动画。 Android Documentation涵盖了这一点。但是在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搜索我发现this正是我想要实现的目标。但它在UIView
上。我认为如果我们在UITableViewCell
中制作动画最合适吗?我真的很感激有人愿意帮助解决这个问题。 Here是我正在开展的初学项目
答案 0 :(得分:5)
如果你想要InShorts视频正在做什么,我建议使用view controller transitions。一篇有用的文章是here。
您要尝试实现的完整示例代码如下。为简洁起见,我在app委托中实现了所有这些,但你绝对应该把它分成不同的类。
视频:here
更新代码
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")
}
}
答案 1 :(得分:5)
可以使用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)
}
}
这是演示项目link ...
非常感谢tutorial。
答案 2 :(得分:4)
根据您的视频,我整理出您想要制作的动画类型。所以这次我的方法
self.view
),并实现pan touch的3种状态此代码具有简单的视图,可以根据颜色数组上的颜色数更改背景。因此,在您的情况下,您可以创建自定义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 p.y < 0 && getPreviousView() == nil || p.y > 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 p.y < 0 {
self.previousView.hidden = false
self.currentView.center.y = self.view.bounds.height/2 + p.y
self.previousView.center.y = self.view.bounds.height/2
// Transforming ratio from 0-1 to 0.9-1
let ratio = (-p.y/CGRectGetHeight(self.view.bounds))
let lightRatio = 0.9 + (ratio/10)
// Apply transformation
self.apply3DDepthTransform(self.previousView, ratio: lightRatio)
} else if p.y > 0 {
self.currentView.center.y = self.view.bounds.height/2
let prevPosY = -self.view.bounds.height/2 + p.y
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 = p.y/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 p.y < -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 p.y > 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 p.y < -self.offset && self.previousView != nil {
self.currentView = self.getPreviousView()
self.currentIndex = (self.currentIndex > 0) ? self.currentIndex - 1 : self.currentIndex;
} else if p.y > 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
进行自定义转换
解决方案包括:
scrollViewDidScroll:
,因为一切都依赖于scrollingOffset
ViewController
上的 Autolayout 存在问题。请清除现有约束,使用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
}
}
希望它能满足您的要求:)
答案 3 :(得分:2)
使用facebook POP动画将拖动视图拖放到动画
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")
}
答案 4 :(得分:0)
UICollectionview
和UICollectionViewLayout
更适合这类事情。 UITableView
不会为每个滚动转换提供给你,你需要做各种肮脏的黑客攻击。
如果你选择UICollectionview
,你要找的是-[UICollectionViewLayout layoutAttributesForElementsInRect:]
和-[UICollectionViewLayout shouldInvalidateLayoutForBoundsChange:]
,其他一切都是数学上的。
答案 5 :(得分:-1)
试试这个: 你可以通过facebook / pop https://github.com/facebook/pop获得更流畅的效果。 这段代码只是为了给你一些想法,而不是经过多次测试。
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)
// })
}