2.0. Introduction(Creating Dynamic and Interactive User Interfaces)
重力,碰撞,弹跳等
2.1. Adding Gravity to Your UI Components
给UI增加重力
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic,strong) UIView *squareView;
@property (nonatomic,strong) UIDynamicAnimator *animator;
@end
@implementation ViewController
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated{ [superviewDidAppear:animated];
/* Create our little square view and add it to self.view */
self.squareView = [[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, 100.0f,100.0f)];
self.squareView.backgroundColor = [UIColorgreenColor];
self.squareView.center =self.view.center;
[self.viewaddSubview:self.squareView];
/* Create the animator and the gravity */
self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
UIGravityBehavior *gravity = [[UIGravityBehavioralloc]
initWithItems:@[self.squareView]];
[self.animatoraddBehavior:gravity];
}
@end
运行之后,绿色方块从屏幕中央向下掉出屏幕
2.2. Detecting and Reacting to Collisions Between UI Components
碰撞检测
#import "ViewController.h"
NSString *const kBottomBoundary =@"bottomBoundary";
@interface ViewController ()<UICollisionBehaviorDelegate>
@property (nonatomic,strong) NSMutableArray *squareViews;
@property (nonatomic,strong) UIDynamicAnimator *animator;
@end
@implementation ViewController
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated{
[superviewDidAppear:animated];
/* Create the views */
NSUInteger const NumberOfViews =15;
self.squareViews = [[NSMutableArrayalloc] initWithCapacity:NumberOfViews];
NSArray *colors = @[[UIColor redColor], [UIColor greenColor],[UIColor blueColor]];
CGPoint currentCenterPoint = self.view.center;
CGSize eachViewSize = CGSizeMake(30.0f, 30.0f);
for (NSUInteger counter =0; counter < NumberOfViews; counter++){
// for (int colomn = 0; colomn < 15; colomn++) {
// currentCenterPoint.x = (eachViewSize.width+10)*colomn;
UIView *newView =
[[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, eachViewSize.width, eachViewSize.height)];
newView.backgroundColor = colors[counter % colors.count];
newView.center = currentCenterPoint;
currentCenterPoint.y -= eachViewSize.height +10.0f;
[self.viewaddSubview:newView];
[self.squareViewsaddObject:newView];
// }
}
self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
/* Create gravity */
UIGravityBehavior *gravity = [[UIGravityBehavioralloc]
initWithItems:self.squareViews];
[self.animatoraddBehavior:gravity];
#if 0
//碰撞检测
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavior alloc]
initWithItems:self.squareViews];
collision.translatesReferenceBoundsIntoBoundary =YES;
[self.animator addBehavior:collision];
#elif 0
//在离底部100的地方设为边界
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavior alloc]
initWithItems:self.squareViews];
[collision
addBoundaryWithIdentifier:@"bottomBoundary"
fromPoint:CGPointMake(0.0f,self.view.bounds.size.height - 100.0f)
toPoint:CGPointMake(self.view.bounds.size.width,
self.view.bounds.size.height - 100.0f)];
[self.animator addBehavior:collision];
#elif 1
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavioralloc]
initWithItems:self.squareViews];
[collision
addBoundaryWithIdentifier:kBottomBoundary
fromPoint:CGPointMake(0.0f,self.view.bounds.size.height - 100.0f)
toPoint:CGPointMake(self.view.bounds.size.width,
self.view.bounds.size.height -100.0f)];
collision.collisionDelegate =self;
collision.collisionMode =UICollisionBehaviorModeEverything;
// typedef NS_OPTIONS(NSUInteger, UICollisionBehaviorMode) {
// UICollisionBehaviorModeItems = 1 << 0,//只检测方块之间的碰撞,结果都溜出屏幕
// UICollisionBehaviorModeBoundaries = 1 << 1,//只检测边界碰撞,结果所有方块都一下子到边界了
// UICollisionBehaviorModeEverything = NSUIntegerMax //检测所有,结果方块在边界处叠起来了
// } NS_ENUM_AVAILABLE_IOS(7_0);
[self.animatoraddBehavior:collision];
#endif
}
- (void)collisionBehavior:(UICollisionBehavior*)paramBehavior
beganContactForItem:(id <UIDynamicItem>)paramItem
withBoundaryIdentifier:(id <NSCopying>)paramIdentifier
atPoint:(CGPoint)paramPoint{
NSString *identifier = (NSString *)paramIdentifier;
if ([identifier isEqualToString:kBottomBoundary]){
[UIViewanimateWithDuration:1.0fanimations:^{
UIView *view = (UIView *)paramItem;
view.backgroundColor = [UIColorredColor];
view.alpha =0.0f;
view.transform =CGAffineTransformMakeScale(2.0f,2.0f);
}completion:^(BOOL finished) {
UIView *view = (UIView *)paramItem;
[paramBehaviorremoveItem:paramItem];
[viewremoveFromSuperview];
}];
}
}
@end
初始时,15个方块掉下来叠在一起,然后最下面一个变淡消失,上面的所有方块往下掉一格。到后面方块柱倒下,所有方块很快消失
2.3. Animating Your UI Components with a Push
#import "ViewController2_3.h"
@interface ViewController2_3 ()
@property (nonatomic,strong) UIView *squareView;
@property (nonatomic,strong) UIDynamicAnimator *animator;
@property (nonatomic,strong) UIPushBehavior *pushBehavior;
@end
@implementation ViewController2_3
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated{
[superviewDidAppear:animated];
[selfcreateGestureRecognizer];
[selfcreateSmallSquareView];
[selfcreateAnimatorAndBehaviors];
}
- (void) createGestureRecognizer{
UITapGestureRecognizer *tapGestureRecognizer =
[[UITapGestureRecognizeralloc] initWithTarget:self
action:@selector(handleTap:)];
[self.viewaddGestureRecognizer:tapGestureRecognizer];
}
- (void) createSmallSquareView{self.squareView =
[[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, 80.0f,80.0f)];
self.squareView.backgroundColor = [UIColorgreenColor];
self.squareView.center =self.view.center;
[self.viewaddSubview:self.squareView];
}
- (void) createAnimatorAndBehaviors{
self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavioralloc]
initWithItems:@[self.squareView]];
collision.translatesReferenceBoundsIntoBoundary =YES;
self.pushBehavior = [[UIPushBehavioralloc]
initWithItems:@[self.squareView]
mode:UIPushBehaviorModeContinuous];
[self.animatoraddBehavior:collision];
[self.animatoraddBehavior:self.pushBehavior];
}
- (void) handleTap:(UITapGestureRecognizer *)paramTap{
/* Get the angle between the center of the square view
and the tap point */
CGPoint tapPoint = [paramTap locationInView:self.view];
CGPoint squareViewCenterPoint = self.squareView.center;
/* Calculate the angle between the center point of the square view and
the tap point to find out the angle of the push
Formula for detecting the angle between two points is:
arc tangent 2((p1.x - p2.x), (p1.y - p2.y)) */
CGFloat deltaX = tapPoint.x - squareViewCenterPoint.x;
CGFloat deltaY = tapPoint.y - squareViewCenterPoint.y;
CGFloat angle = atan2(deltaY, deltaX);
[self.pushBehaviorsetAngle:angle];
/* Use the distance between the tap point and the center of our square
view to calculate the magnitude of the push
Distance formula is:
square root of ((p1.x - p2.x)^2 + (p1.y - p2.y)^2) */
CGFloat distanceBetweenPoints =
sqrt(pow(tapPoint.x - squareViewCenterPoint.x,2.0) +
pow(tapPoint.y - squareViewCenterPoint.y,2.0));
[self.pushBehaviorsetMagnitude:distanceBetweenPoints / 200.0f];
}
@end
点一点任何地方会对方块产生一个拉力
2.4. Attaching Multiple Dynamic Items to Each Other
#import "ViewController2_4.h"
@interface ViewController2_4 ()
@property (nonatomic,strong) UIView *squareView;
@property (nonatomic,strong) UIView *squareViewAnchorView;
@property (nonatomic,strong) UIView *anchorView;
@property (nonatomic,strong) UIDynamicAnimator *animator;
@property (nonatomic,strong) UIAttachmentBehavior *attachmentBehavior;
@end
@implementation ViewController2_4
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated{
[superviewDidAppear:animated];
[selfcreateGestureRecognizer];
[selfcreateSmallSquareView];
[selfcreateAnchorView];
[selfcreateAnimatorAndBehaviors];
}
- (void) createSmallSquareView{self.squareView =
[[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, 80.0f,80.0f)];
self.squareView.backgroundColor = [UIColorgreenColor];
self.squareView.center =self.view.center;
self.squareViewAnchorView = [[UIViewalloc] initWithFrame:
CGRectMake(60.0f,0.0f, 20.0f,20.0f)];
self.squareViewAnchorView.backgroundColor = [UIColorbrownColor];
[self.squareViewaddSubview:self.squareViewAnchorView];
[self.viewaddSubview:self.squareView];
}
- (void) createAnchorView{
self.anchorView = [[UIViewalloc] initWithFrame:
CGRectMake(120.0f,120.0f, 20.0f,20.0f)];
self.anchorView.backgroundColor = [UIColorredColor];
[self.viewaddSubview:self.anchorView];
}
- (void) createGestureRecognizer{
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizeralloc] initWithTarget:selfaction:@selector(handlePan:)];
[self.viewaddGestureRecognizer:panGestureRecognizer];
}
- (void) createAnimatorAndBehaviors{
self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavioralloc]
initWithItems:@[self.squareView]];
collision.translatesReferenceBoundsIntoBoundary =YES;
self.attachmentBehavior = [[UIAttachmentBehavioralloc]
initWithItem:self.squareView
// point:self.squareViewAnchorView.center
attachedToAnchor:self.anchorView.center];
[self.animatoraddBehavior:collision];
[self.animatoraddBehavior:self.attachmentBehavior];
}
- (void) handlePan:(UIPanGestureRecognizer *)paramPan{
CGPoint tapPoint = [paramPan locationInView:self.view];
[self.attachmentBehaviorsetAnchorPoint:tapPoint];
self.anchorView.center = tapPoint;
}
@end
红色的小方块跟着鼠标走,绿色方块跟着红色方块
2.5. Adding a Dynamic Snap Effect to Your UI Components
#import "ViewController2_5.h"
@interface ViewController2_5 ()
@property (nonatomic,strong) UIView *squareView;
@property (nonatomic,strong) UIDynamicAnimator *animator;
@property (nonatomic,strong) UISnapBehavior *snapBehavior;
@end
@implementation ViewController2_5
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated{
[superviewDidAppear:animated];
[selfcreateGestureRecognizer];
[selfcreateSmallSquareView];
[selfcreateAnimatorAndBehaviors];
}
- (void) createGestureRecognizer{
UITapGestureRecognizer *tap = [[UITapGestureRecognizeralloc]
initWithTarget:self
action:@selector(handleTap:)];
[self.viewaddGestureRecognizer:tap];
}
- (void) createSmallSquareView{self.squareView =
[[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, 80.0f,80.0f)];
self.squareView.backgroundColor = [UIColorgreenColor];
self.squareView.center =self.view.center;
[self.viewaddSubview:self.squareView];
}
- (void) createAnimatorAndBehaviors{self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavioralloc]
initWithItems:@[self.squareView]];
collision.translatesReferenceBoundsIntoBoundary =YES;
[self.animatoraddBehavior:collision];
/* For now, snap the square view to its current center */
self.snapBehavior = [[UISnapBehavioralloc]
initWithItem:self.squareView
snapToPoint:self.squareView.center];
self.snapBehavior.damping = 0.5f; /* Medium oscillation */
[self.animatoraddBehavior:self.snapBehavior];
}
- (void) handleTap:(UITapGestureRecognizer *)paramTap{
/* Get the angle between the center of the square view
and the tap point */
CGPoint tapPoint = [paramTap locationInView:self.view];
if (self.snapBehavior !=nil){
[self.animatorremoveBehavior:self.snapBehavior];
}
self.snapBehavior = [[UISnapBehavioralloc] initWithItem:self.squareView
snapToPoint:tapPoint];
self.snapBehavior.damping = 1.5f; /* Medium oscillation */
[self.animatoraddBehavior:self.snapBehavior];
}
@end
你点到哪里,它就以一种很“酷”的方式移到你点的地方,下图是移动过程中的一帧
2.6. Assigning Characteristics to Your Dynamic Effects
#import "ViewController2_6.h"
@interface ViewController2_6 ()
@property (nonatomic,strong) UIDynamicAnimator *animator;
@end
@implementation ViewController2_6
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [superinitWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[superviewDidLoad];
// Do any additional setup after loading the view.
[selftestDynamicItem];
}
- (void)didReceiveMemoryWarning
{
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UIView *) newViewWithCenter:(CGPoint)paramCenter
backgroundColor:(UIColor *)paramBackgroundColor{
UIView *newView =
[[UIViewalloc] initWithFrame:
CGRectMake(0.0f,0.0f, 50.0f,50.0f)];
newView.backgroundColor = paramBackgroundColor;
newView.center = paramCenter;
return newView;
}
-(void)testDynamicItem
{
UIView *topView = [selfnewViewWithCenter:CGPointMake(100.0f,0.0f)
backgroundColor:[UIColorgreenColor]];
UIView *bottomView = [selfnewViewWithCenter:CGPointMake(100.0f,50.0f)
backgroundColor:[UIColorredColor]];
[self.viewaddSubview:topView];
[self.viewaddSubview:bottomView];
self.animator = [[UIDynamicAnimatoralloc]
initWithReferenceView:self.view];
/* Create gravity */
UIGravityBehavior *gravity = [[UIGravityBehavioralloc]
initWithItems:@[topView, bottomView]];
[self.animatoraddBehavior:gravity];
/* Create collision detection */
UICollisionBehavior *collision = [[UICollisionBehavioralloc]
initWithItems:@[topView, bottomView]];
collision.translatesReferenceBoundsIntoBoundary =YES;
[self.animatoraddBehavior:collision];
/* Now specify the elasticity of the items */
UIDynamicItemBehavior *moreElasticItem = [[UIDynamicItemBehavioralloc]
initWithItems:@[bottomView]];
moreElasticItem.elasticity =1.0f;
[self.animatoraddBehavior:moreElasticItem];
UIDynamicItemBehavior *lessElasticItem = [[UIDynamicItemBehavioralloc]
initWithItems:@[topView]];
lessElasticItem.elasticity =0.5f;
[self.animatoraddBehavior:lessElasticItem];
}
@end
绿色比较没弹性,很快就停下来了,红色弹性很好,弹了很久