UISnapBehavior

96
Laughingg
2016.07.15 09:55* 字数 61

捕获行为是定义了一个 item 运动到一个指定的点。
运动的过程像一个弹簧效果,在结束的时候会产生震荡。

//
//  UISnapBehavior.h
//  UIKit
//
//  Copyright (c) 2012-2015 Apple Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIView.h>
#import <UIKit/UIDynamicBehavior.h>

NS_ASSUME_NONNULL_BEGIN

NS_CLASS_AVAILABLE_IOS(7_0) @interface UISnapBehavior : UIDynamicBehavior

// The point argument is expressed in the reference coordinate system
// 创建一个捕获行为
- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point NS_DESIGNATED_INITIALIZER;

// 捕获的点
@property (nonatomic, assign) CGPoint snapPoint NS_AVAILABLE_IOS(9_0);

// 阻尼系数
@property (nonatomic, assign) CGFloat damping; // damping value from 0.0 to 1.0. 0.0 is the least oscillation.  默认值是 0.5

@end

NS_ASSUME_NONNULL_END

演示代码是 swift2.2 的

var testView: UIView?
var snapBehavior: UISnapBehavior?

var animator: UIDynamicAnimator?
override func viewDidLoad() {
    super.viewDidLoad()
    
    // item
    let testView = UIView()
    testView.backgroundColor = UIColor.redColor()
    testView.frame = CGRect(x: 100, y: 100 , width: 10, height: 10)
    self.view.addSubview(testView)
    self.testView = testView;

    // behavior
    self.snapBehavior = UISnapBehavior(item: testView, snapToPoint: testView.center)


    // animator
    self.animator = UIDynamicAnimator(referenceView:self.view )
    animator!.addBehavior(self.snapBehavior!)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    
    // 获取当前触摸的位置
    let touch = touches.first

    //  locationInView 是获取某个视图所在的坐标系中的点
    let point = touch?.locationInView(self.view)

    // 设置捕获的点
    /*
      重新设置这个捕获点的时候会产生一个动画效果
    */
    self.snapBehavior?.snapPoint = point!
}

1.gif
self.snapBehavior?.damping = 0.5   // 0.5 为默认值

damping : 值越大,震荡的幅度越小。


self.snapBehavior?.snapPoint = point!    // 修改这个值 ,item 的 rect 和 rotation 都会发生变化。
当要设置的点 和 Behavior 中记录的点是一样的时候是不会产生震荡效果的。

遇到的一个坑:

var testView: UIView?
var snapBehavior: UISnapBehavior?

var animator: UIDynamicAnimator?
override func viewDidLoad() {
    super.viewDidLoad()
    
    // item
    let testView = UIView()
    testView.backgroundColor = UIColor.redColor()
    testView.frame = CGRect(x: 100, y: 100 , width: 10, height: 10)
    self.view.addSubview(testView)
    self.testView = testView;

    // 在这里没有创建行为

    // animator
    self.animator = UIDynamicAnimator(referenceView:self.view )
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    
    // 获取当前触摸的位置
    let touch = touches.first
    let point = touch?.locationInView(view)
    print(self.snapBehavior?.snapPoint)

    //   注释了这里就会有一个 bug ,多次点击屏幕后就没有动画效果了。item 不动了。 但是 item 的 snapPoint 还是变化的。所有还是建议我第一个示例的写法。
    //        if self.snapBehavior != nil {
    //            self.animator?.removeBehavior(self.snapBehavior!)
    //        }
    
    self.snapBehavior = UISnapBehavior(item: self.testView!, snapToPoint: point!)
    self.animator?.addBehavior(self.snapBehavior!)
}
2. UIKit tips