1 给视图添加重力效果

1.1 问题

当给某个视图加上UIGravityBehavior重力行为之后,这个视图就具有重力,会如同掉入了无底洞,不断地下坠,不断的加速,本案例使用UIGravityBehavior重力行为给imageView添加重力行为,如图-1所示:

图-1

1.2 方案

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和两个Button控件,在右边栏的检查器中设置好ImageView的显示图片。

将ImageView控件关联成TRViewController的属性imageView,两个按钮关联成TRViewController的动作方法start和end。

其次在TRViewController中定义两个私有属性UIDynamicAnimator类型的animator和UIGravityBehavior类型的gravityBehavior。

然后在viewDidLoad方法中创建属性animator和gravityBehavior,将self.view设置为属性animator的referenceView引用视图,给属性imageView添加重力行为。

最后实现start方法和end方法,点击start按钮imageView开始执行重力行为往下坠,点击end按钮停止重力行为。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:搭建Storyboard界面

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件和两个Button控件,在右边栏的检查器中设置好ImageView的显示图片,Storyboard中的界面如图-2所示:

图-2

将ImageView控件关联成TRViewController的属性imageView,两个按钮关联成TRViewController的动作方法start和end,代码如下所示:

  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  3. @end

步骤二:定义animator和gravityBehavior属性

首先在TRViewController中定义两个私有属性UIDynamicAnimator类型的animator和UIGravityBehavior类型的gravityBehavior,代码如下所示:

  1. @interface TRViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  3. @property (strong, nonatomic)UIDynamicAnimator *animator;
  4. @property (strong, nonatomic)UIGravityBehavior *gravityBehavior;
  5. @end

然后在viewDidLoad方法中创建属性animator和gravityBehavior,将self.view设置为属性animator的referenceView引用视图,给属性imageView添加重力行为,代码如下所示:

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. //将self.view设置为动力坐标系的参考
  5. UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  6. //给imageView添加重力行为
  7. UIGravityBehavior *gravity = [[UIGravityBehavior alloc]initWithItems:@[self.imageView]];
  8. self.gravityBehavior = gravity;
  9. self.animator = animator;
  10. }

步骤三:实现start和end方法

当点击start按钮时imageView开始执行重力行为往下坠,在start方法中使用addBehavior:方法执行重力行为。

当点击end按钮时停止重力行为,在end方法中使用removeBehavior:方法将重力行为移除,代码如下所示:

  1. - (IBAction)start
  2. {
  3. //当点击start按钮时将重力行为添加到self.animator
  4. [self.animator addBehavior:self.gravityBehavior];
  5. }
  6. - (IBAction)end
  7. {
  8. //当点击end按钮时将重力行为移除
  9. [self.animator removeBehavior:self.gravityBehavior];
  10. }

1.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. @interface TRViewController ()
  3. @property (weak, nonatomic) IBOutlet UIImageView *imageView;
  4. @property (strong, nonatomic)UIDynamicAnimator *animator;
  5. @property (strong, nonatomic)UIGravityBehavior *gravityBehavior;
  6. @end
  7. @implementation TRViewController
  8. - (void)viewDidLoad
  9. {
  10. [super viewDidLoad];
  11. //将self.view设置为动力坐标系的参考
  12. UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  13. //给imageView添加重力行为
  14. UIGravityBehavior *gravity = [[UIGravityBehavior alloc]initWithItems:@[self.imageView]];
  15. self.gravityBehavior = gravity;
  16. self.animator = animator;
  17. }
  18. - (IBAction)start
  19. {
  20. //当点击start按钮时将重力行为添加到self.animator
  21. [self.animator addBehavior:self.gravityBehavior];
  22. }
  23. - (IBAction)end
  24. {
  25. //当点击end按钮时将重力行为移除
  26. [self.animator removeBehavior:self.gravityBehavior];
  27. }
  28. @end

2 给视图添加碰撞效果

2.1 问题

如果给某个视图添加了UICollisionBehavior碰撞行为,该视图就有碰撞能力,能与引用视图产生碰撞效果,本案例使用UICollisionBehavior给视图添加碰撞效果,如图-3所示:

图-3

2.2 方案

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRCollisionViewController的属性boxImageView。

其次创建一个TRBackgroundView类继承至UIView,该类有一个UIBezierPath类型的公开属性path。在Storyboard中将View关联成TRBackgroundView。

在TRBackgroundView.m文件中重写initWithCoder:方法和drawRect:绘制方法,initWithCoder:方法中使用colorWithPatternImage:方法设置背景颜色,drawRect:方法中则根据path属性进行绘制。

然后在TRCollisionViewController类中定义一个UIDynamicAnimator类型的属性animator。

在viewDidLoad方法中使boxImageView旋转45度,使一个角朝下。

在viewDidAppear:方法中创建属性animator,将self.view设置为属性animator的referenceView引用视图,给属性boxImageView添加重力行为和碰撞行为,使boxImageView和绘制出来的path进行碰撞。

最后通过实现UICollisionBehaviorDelegate的协议方法,当碰撞开始时boxImageView颜色发生改变。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:拖放ImageView控件

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRCollisionViewController的属性boxImageView,代码如下所示:

 
  1. @interface TRCollisionViewController () <UICollisionBehaviorDelegate>
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @end

步骤二:创建TRBackgroundView类

首先创建一个TRBackgroundView类继承至UIView,该类有一个UIBezierPath类型的公开属性path。在Storyboard中将View关联成TRBackgroundView,如图-4所示:

图-4

然后在TRBackgroundView.m文件中重写initWithCoder:方法和drawRect:绘制方法,initWithCoder:方法中使用colorWithPatternImage:方法设置背景颜色,drawRect:方法中则根据path属性进行绘制,代码如下所示:

 
  1. #import "TRBackgroundView.h"
  2. @implementation TRBackgroundView
  3. - (id)initWithCoder:(NSCoder *)aDecoder
  4. {
  5. self = [super initWithCoder:aDecoder];
  6. if(self){
  7. self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"BackgroundTile"]];
  8. }
  9. return self;
  10. }
  11. - (void)drawRect:(CGRect)rect
  12. {
  13. [[UIColor redColor]setFill];
  14. [[UIColor greenColor]setStroke];
  15. [self.path stroke];
  16. [self.path fill];
  17. }
  18. @end

步骤三:添加重力行为和碰撞行为

首先在TRCollisionViewController类中定义一个UIDynamicAnimator类型的私用属性animator,代码如下所示:

 
  1. @interface TRCollisionViewController () <UICollisionBehaviorDelegate>
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @property (strong, nonatomic) UIDynamicAnimator *animator;
  4. @end

然后在viewDidLoad方法中使boxImageView旋转45度,使boxImageView的一个角朝下,代码如下所示:

 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. self.boxImageView.transform = CGAffineTransformRotate(self.boxImageView.transform, M_PI_4);
  5. }

最后在viewDidAppear:方法中创建属性animator,将self.view设置为属性animator的referenceView引用视图,给属性boxImageView添加重力行为和碰撞行为,使boxImageView和绘制出来的path进行碰撞,代码如下所示:

 
  1. - (void)viewDidAppear:(BOOL)animated
  2. {
  3. UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  4. self.animator = animator;
  5. //创建重力行为
  6. UIGravityBehavior *gravity = [[UIGravityBehavior alloc]initWithItems:@[self.boxImageView]];
  7. //重力的强度
  8. gravity.magnitude = 0.1;
  9. //重力的方向
  10. gravity.gravityDirection = CGVectorMake(0, 1);
  11. [animator addBehavior:gravity];
  12. //创建碰撞行为
  13. UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.boxImageView]];
  14. //将引用视图的四周翻译成可碰撞的四个边
  15. collision.translatesReferenceBoundsIntoBoundary = YES;
  16. //设置delegate
  17. collision.collisionDelegate = self;
  18. //用UIBezierPath创建一个形状并具有碰撞行为
  19. UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 450, 280, 30) cornerRadius:10.0];
  20. TRBackgroundView *myView = (TRBackgroundView *)self.view;
  21. myView.path = path;
  22. [myView setNeedsDisplay];
  23. [collision addBoundaryWithIdentifier:@"MyPathIdenrifier" forPath:path];
  24. [animator addBehavior:collision];
  25. }

步骤四:实现协议方法

实现UICollisionBehaviorDelegate的协议方法beganContactForItem: withBoundaryIdentifier:atPoint:,完碰撞开始时boxImageView颜色发生改变,代码如下所示:

 
  1. - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p
  2. {
  3. UIImageView *box = (UIImageView *)item;
  4. box.tintColor = [UIColor redColor];
  5. // imageWithRenderingMode:IOS7提供的新的功能,设置一个UIImage在渲染时是否使用当前视图的Tint Color
  6. //UIImageRenderingModeAlwaysTemplate表示始终根据Tint Color绘制图片,忽略图片的颜色信息。
  7. box.image = [box.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
  8. NSLog(@"%@,%@,point:(%.0f, %.0f", item, identifier, p.x, p.y);
  9. }

2.4 完整代码

本案例中,TRCollisionViewController.m文件中的完整代码如下所示:

 
  1. #import "TRCollisionViewController.h"
  2. #import "TRBackgroundView.h"
  3. @interface TRCollisionViewController () <UICollisionBehaviorDelegate>
  4. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  5. @property (strong, nonatomic) UIDynamicAnimator *animator;
  6. @end
  7. @implementation TRCollisionViewController
  8. - (void)viewDidLoad
  9. {
  10. [super viewDidLoad];
  11. self.boxImageView.transform = CGAffineTransformRotate(self.boxImageView.transform, M_PI_4);
  12. }
  13. - (void)viewDidAppear:(BOOL)animated
  14. {
  15. UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  16. self.animator = animator;
  17. //重力行为
  18. UIGravityBehavior *gravity = [[UIGravityBehavior alloc]initWithItems:@[self.boxImageView]];
  19. //重力的强度
  20. gravity.magnitude = 0.1;
  21. //重力的方向
  22. gravity.gravityDirection = CGVectorMake(0, 1);
  23. [animator addBehavior:gravity];
  24. //碰撞行为
  25. UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.boxImageView]];
  26. //将引用视图的四周翻译成可碰撞的四个边
  27. collision.translatesReferenceBoundsIntoBoundary = YES;
  28. collision.collisionDelegate = self;
  29. //用UIBezierPath创建一个形状并具有碰撞行为
  30. UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 450, 280, 30) cornerRadius:10.0];
  31. TRBackgroundView *myView = (TRBackgroundView *)self.view;
  32. myView.path = path;
  33. [myView setNeedsDisplay];
  34. [collision addBoundaryWithIdentifier:@"MyPathIdenrifier" forPath:path];
  35. [animator addBehavior:collision];
  36. }
  37. - (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p
  38. {
  39. UIImageView *box = (UIImageView *)item;
  40. box.tintColor = [UIColor redColor];
  41. // imageWithRenderingMode:IOS7提供的新的功能,设置一个UIImage在渲染时是否使用当前视图的Tint Color
  42. //UIImageRenderingModeAlwaysTemplate表示始终根据Tint Color绘制图片,忽略图片的颜色信息。
  43. box.image = [box.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
  44. NSLog(@"%@,%@,point:(%.0f, %.0f", item, identifier, p.x, p.y);
  45. }
  46. - (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier
  47. {
  48. NSLog(@"....");
  49. }
  50. @end

本案例中,TRBackgroundView.h文件中的完整代码如下所示:

  1. #import<UIKit/UIKit.h>
  2. @interface TRBackgroundView : UIView
  3. @property (nonatomic, strong) UIBezierPath *path;
  4. @end

本案例中,TRBackgroundView.m文件中的完整代码如下所示:

 
  1. #import "TRBackgroundView.h"
  2. @implementation TRBackgroundView
  3. - (id)initWithCoder:(NSCoder *)aDecoder
  4. {
  5. self = [super initWithCoder:aDecoder];
  6. if(self){
  7. self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"BackgroundTile"]];
  8. }
  9. return self;
  10. }
  11. - (void)drawRect:(CGRect)rect
  12. {
  13. [[UIColor redColor]setFill];
  14. [[UIColor greenColor]setStroke];
  15. [self.path stroke];
  16. [self.path fill];
  17. }
  18. @end

3 给视图添加吸附效果

3.1 问题

UIAttachmentBehavior吸附行为,一个视图产生某种行为后相关联的对象也随之一起运动,本案例使用UIAttachmentBehavior给视图添加吸附效果,是两个视图产生关联行为,如图-5所示:

图-5

3.2 方案

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRAttachmentViewController的属性boxImageView。

本案例同样需要一个TRBackgroundView类,直接使用上一个案例的TRBackgroundView类即可,在Storyboard中将View关联成TRBackgroundView。

然后在TRAttachmentViewController类中定义三个属性分别为UIDynamicAnimator类型的animator,UIGravityBehavior类型的gravityBehavior,以及UIAttachmentBehavior类型的attachmentBehavior,并且使用重写setter的方法进行初始化。

在Storyboard中给View添加UIPanGestureRecognizer类型的手势,关联成pan:方法。

最后在TRAttachmentViewController中实现pan:方法,每次触摸屏幕则在boxImageView的中心点和手指触摸点绘制一条直线,并且boxImageView和手指触摸点产生关联的动力行为。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:拖放ImageView控件

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRAttachmentViewController的属性boxImageView,代码如下所示:

 
  1. @interface TRAttachmentViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @end

本案例同样需要一个TRBackgroundView类,直接使用上一个案例的TRBackgroundView类即可,在Storyboard中将View关联成TRBackgroundView。

步骤二:定义属性

在TRAttachmentViewController类中定义三个属性分别为UIDynamicAnimator类型的animator,UIGravityBehavior类型的gravityBehavior,以及UIAttachmentBehavior类型的attachmentBehavior,并且使用重写setter的方法进行初始化,代码如下所示:

 
  1. @interface TRAttachmentViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @property (strong, nonatomic) UIDynamicAnimator *animator;
  4. @property (strong, nonatomic) UIGravityBehavior *gravityBehavior;
  5. @property (strong, nonatomic) UIAttachmentBehavior *attachmentBehavior;
  6. @end
  7. //重写setter方法
  8. - (UIDynamicAnimator *)animator
  9. {
  10. if(!_animator)_animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  11. return _animator;
  12. }
  13. - (UIGravityBehavior *)gravityBehavior
  14. {
  15. if (!_gravityBehavior) {
  16. _gravityBehavior = [[UIGravityBehavior alloc]initWithItems:@[self.boxImageView]];
  17. }
  18. return _gravityBehavior;
  19. }
  20. - (UIAttachmentBehavior *)attachmentBehavior
  21. {
  22. CGPoint attachedToAnchor = CGPointMake(self.boxImageView.center.x, self.boxImageView.frame.origin.y - 50);
  23. if (!_attachmentBehavior) {
  24. //使用initWithItem:attachedToAnchor:方法进行初始化,使boxImageView和attachedToAnchor产生关联行为
  25. _attachmentBehavior = [[UIAttachmentBehavior alloc]initWithItem:self.boxImageView attachedToAnchor:attachedToAnchor];
  26. }
  27. return _attachmentBehavior;
  28. }

步骤三:添加手势,实现关联动力行为

首先在Storyboard中给View添加UIPanGestureRecognizer类型的手势,关联成pan:方法。

然后在TRAttachmentViewController中实现pan:方法,该方法中根据手势的状态在boxImageView的中心点和手指触摸点绘制一条直线,并且boxImageView和手指触摸点产生关联的动力行为,代码如下所示:

 
  1. - (IBAction)pan:(UIPanGestureRecognizer *)sender
  2. {
  3. if (sender.state == UIGestureRecognizerStateBegan) {
  4. //手势开始添加关联行为和重力行为
  5. [self.animator addBehavior:self.gravityBehavior];
  6. self.attachmentBehavior.anchorPoint = [sender locationInView:self.view];
  7. //阻尼
  8. self.attachmentBehavior.damping = 0.1;
  9. //频率
  10. self.attachmentBehavior.frequency = 1.0;
  11. [self.animator addBehavior:self.attachmentBehavior];
  12. [self drawLine];
  13. [self.view setNeedsDisplay];
  14. }
  15. if(sender.state == UIGestureRecognizerStateChanged){
  16. CGPoint location = [sender locationInView:self.view];
  17. //手指移动过程中改变anchorPoint
  18. self.attachmentBehavior.anchorPoint = location;
  19. [self drawLine];
  20. [self.view setNeedsDisplay];
  21. }else if(sender.state == UIGestureRecognizerStateEnded){
  22. //手势结束移除关联行为和重力行为
  23. [self.animator removeBehavior:self.attachmentBehavior];
  24. [self.animator removeBehavior:self.gravityBehavior];
  25. ((TRBackgroundView *)self.view).path = nil;
  26. [self.view setNeedsDisplay];
  27. }
  28. }
  29. - (void)drawLine
  30. {
  31. __weak UIAttachmentBehavior *weakAttachmentBehavior = self.attachmentBehavior;
  32. __weak UIImageView *weakBoxImageView = self.boxImageView;
  33. __weak TRBackgroundView *weakMyView = (TRBackgroundView *)self.view;
  34. self.attachmentBehavior.action = ^{
  35. UIBezierPath *path = [UIBezierPath bezierPath];
  36. [path moveToPoint:weakAttachmentBehavior.anchorPoint];
  37. [path addLineToPoint:weakBoxImageView.center];
  38. path.lineWidth = 2;
  39. weakMyView.path = path;
  40. [weakMyView setNeedsDisplay];
  41. };
  42. }

3.4 完整代码

本案例中,TRAttachmentViewController.m文件中的完整代码如下所示:

 
  1. #import "TRAttachmentViewController.h"
  2. #import "TRBackgroundView.h"
  3. @interface TRAttachmentViewController ()
  4. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  5. @property (strong, nonatomic) UIDynamicAnimator *animator;
  6. @property (strong, nonatomic) UIGravityBehavior *gravityBehavior;
  7. @property (strong, nonatomic) UIAttachmentBehavior *attachmentBehavior;
  8. @end
  9. @implementation TRAttachmentViewController
  10. - (UIDynamicAnimator *)animator
  11. {
  12. if(!_animator)_animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  13. return _animator;
  14. }
  15. - (UIGravityBehavior *)gravityBehavior
  16. {
  17. if (!_gravityBehavior) {
  18. _gravityBehavior = [[UIGravityBehavior alloc]initWithItems:@[self.boxImageView]];
  19. }
  20. return _gravityBehavior;
  21. }
  22. - (UIAttachmentBehavior *)attachmentBehavior
  23. {
  24. CGPoint attachedToAnchor = CGPointMake(self.boxImageView.center.x, self.boxImageView.frame.origin.y - 50);
  25. if (!_attachmentBehavior) {
  26. _attachmentBehavior = [[UIAttachmentBehavior alloc]initWithItem:self.boxImageView attachedToAnchor:attachedToAnchor];
  27. }
  28. return _attachmentBehavior;
  29. }
  30. - (IBAction)pan:(UIPanGestureRecognizer *)sender
  31. {
  32. if (sender.state == UIGestureRecognizerStateBegan) {
  33. [self.animator addBehavior:self.gravityBehavior];
  34. self.attachmentBehavior.anchorPoint = [sender locationInView:self.view];
  35. //阻尼
  36. self.attachmentBehavior.damping = 0.1;
  37. //频率
  38. self.attachmentBehavior.frequency = 1.0;
  39. [self.animator addBehavior:self.attachmentBehavior];
  40. [self drawLine];
  41. [self.view setNeedsDisplay];
  42. }
  43. if(sender.state == UIGestureRecognizerStateChanged){
  44. CGPoint location = [sender locationInView:self.view];
  45. self.attachmentBehavior.anchorPoint = location;
  46. [self drawLine];
  47. [self.view setNeedsDisplay];
  48. }else if(sender.state == UIGestureRecognizerStateEnded){
  49. [self.animator removeBehavior:self.attachmentBehavior];
  50. [self.animator removeBehavior:self.gravityBehavior];
  51. ((TRBackgroundView *)self.view).path = nil;
  52. [self.view setNeedsDisplay];
  53. }
  54. }
  55. - (void)drawLine
  56. {
  57. __weak UIAttachmentBehavior *weakAttachmentBehavior = self.attachmentBehavior;
  58. __weak UIImageView *weakBoxImageView = self.boxImageView;
  59. __weak TRBackgroundView *weakMyView = (TRBackgroundView *)self.view;
  60. self.attachmentBehavior.action = ^{
  61. UIBezierPath *path = [UIBezierPath bezierPath];
  62. [path moveToPoint:weakAttachmentBehavior.anchorPoint];
  63. [path addLineToPoint:weakBoxImageView.center];
  64. path.lineWidth = 2;
  65. weakMyView.path = path;
  66. [weakMyView setNeedsDisplay];
  67. };
  68. }
  69. @end

4 给视图添加闪的效果

4.1 问题

本案例使用UISnapBehavior给视图添加闪的效果,点击屏幕某处imageView就闪向某处,如图-6所示:

图-6

4.2 方案

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRSnapViewController的属性boxImageView。

从对象库中拖放一个TapGestureRecognizer类型的手势到Storyboard的场景中,并将手势关联成TRSnapViewController的动作方法tap:。

其次在TRSnapViewController中定义两个私有属性UIDynamicAnimator类型的animator和UISnapBehavior类型的snapBehavior。重写setter方法对animator属性进行初始化。

最后实现tap:方法,该方法中创建snapBehavior行为,使boxImageView闪向手指触摸的地方。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:搭建Storyboard界面

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRSnapViewController的属性boxImageView,代码如下所示:

  1. @interface TRSnapViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @end

然后从对象库中拖放一个TapGestureRecognizer类型的手势到Storyboard的场景中,并将手势关联成TRSnapViewController的动作方法tap:。

步骤二:定义属性animator和snapBehavior

首先在TRSnapViewController中定义两个私有属性UIDynamicAnimator类型的animator和UISnapBehavior类型的snapBehavior。

然后重写setter方法对animator属性进行初始化,代码如下所示:

 
  1. @interface TRSnapViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @property (strong, nonatomic) UIDynamicAnimator *animator;
  4. @property (strong, nonatomic) UISnapBehavior *snapBehavior;
  5. @end

最后实现tap:方法,该方法中创建snapBehavior行为,使boxImageView闪向手指触摸的地方,代码如下所示:

  1. - (IBAction)tap:(UITapGestureRecognizer *)sender
  2. {
  3. CGPoint point = [sender locationInView:self.view];
  4. [self.animator removeBehavior:self.snapBehavior];
  5. self.snapBehavior = [[UISnapBehavior alloc]initWithItem:self.boxImageView snapToPoint:point];
  6. [self.animator addBehavior:self.snapBehavior];
  7. }

4.4 完整代码

本案例中,TRSnapViewController.m文件中的完整代码如下所示:

 
  1. #import "TRSnapViewController.h"
  2. @interface TRSnapViewController ()
  3. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  4. @property (strong, nonatomic) UIDynamicAnimator *animator;
  5. @property (strong, nonatomic) UISnapBehavior *snapBehavior;
  6. @end
  7. @implementation TRSnapViewController
  8. - (UIDynamicAnimator *)animator
  9. {
  10. if (!_animator) {
  11. _animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  12. }
  13. return _animator;
  14. }
  15. - (IBAction)tap:(UITapGestureRecognizer *)sender
  16. {
  17. CGPoint point = [sender locationInView:self.view];
  18. [self.animator removeBehavior:self.snapBehavior];
  19. self.snapBehavior = [[UISnapBehavior alloc]initWithItem:self.boxImageView snapToPoint:point];
  20. [self.animator addBehavior:self.snapBehavior];
  21. }
  22. @end

5 给视图添加推(拍)效果和UIDynamicItemBehavior

5.1 问题

本案例使用UIPushBehavior和UIDynamicItemBehavior给视图添加pushBehavior行为和dynamicItemBehavior行为,使视图可以在某个动作结束后,继续沿轨迹运动,如图-7所示:

图-7

5.2 方案

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRPushViewController的属性boxImageView。

从对象库中拖放一个PanGestureRecognizer类型的手势到Storyboard的场景中,并将手势关联成TRPushViewController的动作方法panAction:。

其次在TRPushViewController中定义两个私有属性UIDynamicAnimator类型的animator和UIPushBehavior类型pushBehavior。重写setter方法对animator属性进行初始化。

然后创建碰撞行为和push行为,由于碰撞行为需要计算视图边距,需要获取self.topLayoutGuide.length的值,所以将碰撞行为和push行为的代码写在viewDidAppear:方法中。

最后实现tap:方法,该方法中boxImageView随着手指滑动实现碰撞和推动,并具有摩擦和反弹效果。

5.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:搭建Storyboard界面

首先在创建好的Xcode项目的Storyboard中拖放一个ImageView控件,在右边栏的检查器中设置好ImageView的显示图片。将ImageView控件关联成TRPushViewController的属性boxImageView,代码如下所示:

 
  1. @interface TRPushViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @end

从对象库中拖放一个PanGestureRecognizer类型的手势到Storyboard的场景中,并将手势关联成TRPushViewController的动作方法panAction:。

步骤二:定义属性animator和pushBehavior

在TRPushViewController中定义两个私有属性UIDynamicAnimator类型的animator和UIPushBehavior类型pushBehavior,代码如下所示:

 
  1. @interface TRPushViewController ()
  2. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  3. @property (strong, nonatomic) UIDynamicAnimator *animator;
  4. @property (strong, nonatomic)UIPushBehavior *pushBehavior;
  5. @end

然后重写setter方法对animator属性进行初始化,代码如下所示:

 
  1. - (UIDynamicAnimator *)animator
  2. {
  3. if(!_animator)_animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  4. return _animator;
  5. }

属性三:创建动力行为,实现手势的动作方法

首先创建碰撞行为和push行为,由于碰撞行为需要计算视图边距,需要获取self.topLayoutGuide.length的值,所以将碰撞行为和push行为的代码写在viewDidAppear:方法中,代码如下所示:

 
  1. - (void)viewDidAppear:(BOOL)animated
  2. {
  3. [super viewDidAppear:animated];
  4. //创建碰撞行为
  5. UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc]initWithItems:@[self.boxImageView]];
  6. [collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0)];
  7. [self.animator addBehavior:collisionBehavior];
  8. //创建pushBehavior行为,UIPushBehaviorModeContinuous模式表示推力持续施加
  9. self.pushBehavior = [[UIPushBehavior alloc]initWithItems:@[self.boxImageView] mode:UIPushBehaviorModeContinuous];
  10. [self.animator addBehavior:self.pushBehavior];
  11. }

然后实现tap:方法,该方法中boxImageView随着手指滑动实现碰撞和推动,代码如下所示:

 
  1. - (IBAction)panAction:(UIPanGestureRecognizer *)sender {
  2. CGPoint point = [sender locationInView:self.view];
  3. CGPoint center = self.boxImageView.center;
  4. //计算移动的方向
  5. CGFloat angle = atan2(center.y - point.y, center.x - point.x) + M_PI;
  6. self.pushBehavior.angle = angle;
  7. //计算移动的速度
  8. CGFloat distance = sqrt(powf(point.x - center.x, 2) + powf(point.y - center.y, 2));
  9. self.pushBehavior.magnitude = distance / 10;
  10. //激活
  11. self.pushBehavior.active = YES;
  12. }

最后添加dynamicItemBehavior行为,是视图在移动过程中产生摩擦和反弹,代码如下所示:

 
  1. - (IBAction)panAction:(UIPanGestureRecognizer *)sender {
  2. CGPoint point = [sender locationInView:self.view];
  3. CGPoint center = self.boxImageView.center;
  4. //计算移动的方向
  5. CGFloat angle = atan2(center.y - point.y, center.x - point.x) + M_PI;
  6. self.pushBehavior.angle = angle;
  7. //计算移动的速度
  8. CGFloat distance = sqrt(powf(point.x - center.x, 2) + powf(point.y - center.y, 2));
  9. self.pushBehavior.magnitude = distance / 10;
  10. //激活
  11. self.pushBehavior.active = YES;
  12. //添加UIDynamicItemBehavior
  13. UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.boxImageView]];
  14. //设置摩擦力大小
  15. itemBehavior.friction = 0.2;
  16. //允许旋转
  17. itemBehavior.allowsRotation = YES;
  18. //设置旋转速度
  19. [itemBehavior addAngularVelocity:M_PI_4 forItem:self.boxImageView];
  20. [self.animator addBehavior:itemBehavior];
  21. }

5.4 完整代码

本案例中,TRPushViewController.m文件中的完整代码如下所示:

 
  1. #import "TRPushViewController.h"
  2. @interface TRPushViewController ()
  3. @property (weak, nonatomic) IBOutlet UIImageView *boxImageView;
  4. @property (strong, nonatomic) UIDynamicAnimator *animator;
  5. @property (strong, nonatomic)UIPushBehavior *pushBehavior;
  6. @end
  7. @implementation TRPushViewController
  8. - (UIDynamicAnimator *)animator
  9. {
  10. if(!_animator)_animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
  11. return _animator;
  12. }
  13. - (void)viewDidAppear:(BOOL)animated
  14. {
  15. [super viewDidAppear:animated];
  16. //创建碰撞行为
  17. UICollisionBehavior *collisionBehavior = [[UICollisionBehavior alloc]initWithItems:@[self.boxImageView]];
  18. [collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0)];
  19. [self.animator addBehavior:collisionBehavior];
  20. //创建pushBehavior行为,UIPushBehaviorModeContinuous模式表示推力持续施加
  21. self.pushBehavior = [[UIPushBehavior alloc]initWithItems:@[self.boxImageView] mode:UIPushBehaviorModeContinuous];
  22. [self.animator addBehavior:self.pushBehavior];
  23. }
  24. - (IBAction)panAction:(UIPanGestureRecognizer *)sender {
  25. CGPoint point = [sender locationInView:self.view];
  26. CGPoint center = self.boxImageView.center;
  27. //计算移动的方向
  28. CGFloat angle = atan2(center.y - point.y, center.x - point.x) + M_PI;
  29. self.pushBehavior.angle = angle;
  30. //计算移动的速度
  31. CGFloat distance = sqrt(powf(point.x - center.x, 2) + powf(point.y - center.y, 2));
  32. self.pushBehavior.magnitude = distance / 10;
  33. //激活
  34. self.pushBehavior.active = YES;
  35. //添加UIDynamicItemBehavior
  36. UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.boxImageView]];
  37. //设置摩擦力大小
  38. itemBehavior.friction = 0.2;
  39. //允许旋转
  40. itemBehavior.allowsRotation = YES;
  41. //设置旋转速度
  42. [itemBehavior addAngularVelocity:M_PI_4 forItem:self.boxImageView];
  43. [self.animator addBehavior:itemBehavior];
  44. }
  45. @end

6 使用集合视图的布局实现Cell滚动时候的动画效果

6.1 问题

集合视图的布局是其精髓,相当于集合视图的大脑和中枢,负责设置集合视图的一些属性,包括位置、尺寸、透明度、层级关系、形状等。本案例将使用集合视图的布局实现单元格滚动时的动画效果,如图-8所示:

图-8

6.2 方案

首先创建一个SingleViewApplication项目,在StoryBoard中拖放一个CollectionViewController作为根视图控制器,并于TRViewController进行绑定,TRViewController继承至UICollectionViewController。

其次创建一个TRCell类,继承至UICollectionViewCell,TRCell有一个公开属性UILabel类型的label。然后重写initWithFrame:方法,通过frame参数计算出每个cell中子视图label的frame,并且设置cell的contentView的layer属性。

然后创建一个TRCollectionViewCustomLayout继承至UICollectionViewFlowLayout。重写初始化方法initWithCoder:对布局类进行一些初始化的设置,例如滚动方向、间距、item的大小等。

UICollectionViewLayoutAttributes是一个非常重要的类包含了cell布局信息,包括边框、中心点、大小、形状、透明度、层次关系以及是否隐藏等信息。本案例在TRCollectionViewCustomLayout类中重写layoutAttributesForElementsInRect:方法,获取每一个Cell的布局属性,通过attributes.transform3D实现Cell的缩放动画。

最后在TRViewController的viewDidLoad方法中注册集合视图的cell,TRViewController遵守集合视图协议,并且实现协议方法给集合视图加载数据。

6.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建集合视图项目

首先创建一个SingleViewApplication项目,在StoryBoard中拖放一个CollectionViewController作为根视图控制器,并于TRViewController进行绑定,TRViewController继承至UICollectionViewController,Storyboard中的界面如图-9所示:

图-9

步骤二:创建TRCell类

首先创建一个TRCell类,继承至UICollectionViewCell,TRCell有一个公开属性UILabel类型的label,代码如下所示:

 
  1. @interface TRCell : UICollectionViewCell
  2. @property (nonatomic, strong) UILabel *label;
  3. @end

然后重写initWithFrame:方法,通过frame参数计算出每个cell中子视图label的frame,并且设置cell的contentView的layer属性,代码如下所示:

 
  1. - (id)initWithFrame:(CGRect)frame
  2. {
  3. self = [super initWithFrame:frame];
  4. if (self) {
  5. //创建并设置label属性
  6. self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
  7. self.label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  8. self.label.textAlignment = NSTextAlignmentCenter;
  9. self.label.backgroundColor = [UIColor lightGrayColor];
  10. self.label.textColor = [UIColor blackColor];
  11. [self.contentView addSubview:self.label];
  12. //设置contentView的layer属性,添加圆角和边框
  13. self.contentView.layer.borderWidth = 1.0f;
  14. self.contentView.layer.cornerRadius = 8.0;
  15. self.contentView.layer.masksToBounds = YES;
  16. self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;
  17. }
  18. return self;
  19. }

步骤三:创建布局类TRCollectionViewCustomLayout

首先创建一个TRCollectionViewCustomLayout继承至UICollectionViewFlowLayout。重写初始化方法initWithCoder:对布局类进行一些初始化的设置,例如滚动方向、间距、item的大小等,代码如下所示:

 
  1. - (id)initWithCoder:(NSCoder *)aDecoder
  2. {
  3. self = [super initWithCoder:aDecoder];
  4. if (self) {
  5. [self initiate];
  6. }
  7. return self;
  8. }
  9. - (void)initiate
  10. {
  11. //设置Cell的大小
  12. self.itemSize = CGSizeMake(100, 100);
  13. //设置CollectionView的滚动方向
  14. self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  15. //设置CollectionView的内边距
  16. self.sectionInset = UIEdgeInsetsMake(100, 0, 100, 0);
  17. //设置Cell之间的间距
  18. self.minimumLineSpacing = 50;
  19. }

然后在TRCollectionViewCustomLayout类中重写layoutAttributesForElementsInRect:方法,获取每一个Cell的布局属性,通过attributes.transform3D实现Cell的缩放动画,代码如下所示:

 
  1. //当边界改变时重新计算布局
  2. - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
  3. {
  4. return YES;
  5. }
  6. //返回所有Cell的布局属性
  7. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
  8. {
  9. //获取每一个Cell的布局属性
  10. NSArray *array = [super layoutAttributesForElementsInRect:rect];
  11. CGRect visibleRect;
  12. visibleRect.origin = self.collectionView.contentOffset;
  13. visibleRect.size = self.collectionView.bounds.size;
  14. for (UICollectionViewLayoutAttributes *attributes in array) {
  15. CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
  16. CGFloat distance2 = distance / 100;
  17. if(ABS(distance) < 100){
  18. CGFloat zoom = 1 + 0.3* (1 - ABS(distance2));
  19. attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1);
  20. }
  21. }
  22. return array;
  23. }

步骤四:遵守委托协议,实现协议方法

首先在TRViewController的viewDidLoad方法中注册集合视图的cell,代码如下所示:

 
  1. static NSString *cellIdentifier = @"MyCell";
  2. - (void)viewDidLoad
  3. {
  4. [super viewDidLoad];
  5. [self.collectionView registerClass:[TRCell class] forCellWithReuseIdentifier:cellIdentifier];
  6. }

然后TRViewController遵守集合视图协议,并且实现协议方法给集合视图加载数据,代码如下所示:

 
  1. -(NSInteger)collectionView:(UICollectionView *)collectionView
  2. numberOfItemsInSection:(NSInteger)section
  3. {
  4. return 60;
  5. }
  6. -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
  7. cellForItemAtIndexPath:(NSIndexPath *)indexPath
  8. {
  9. TRCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
  10. cell.label.text = [NSString stringWithFormat:@"%d", indexPath.row];
  11. return cell;
  12. }

6.4 完整代码

本案例中,TRViewController.m文件中的完整代码如下所示:

 
  1. #import "TRViewController.h"
  2. #import "TRCell.h"
  3. @implementation TRViewController
  4. static NSString *cellIdentifier = @"MyCell";
  5. - (void)viewDidLoad
  6. {
  7. [super viewDidLoad];
  8. [self.collectionView registerClass:[TRCell class] forCellWithReuseIdentifier:cellIdentifier];
  9. }
  10. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
  11. {
  12. return 60;
  13. }
  14. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
  15. {
  16. TRCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
  17. cell.label.text = [NSString stringWithFormat:@"%d", indexPath.row];
  18. return cell;
  19. }
  20. @end

本案例中,TRCell.h文件中的完整代码如下所示:

 
  1. #import<UIKit/UIKit.h>
  2. @interface TRCell : UICollectionViewCell
  3. @property (nonatomic, strong) UILabel *label;
  4. @end

本案例中,TRCell.m文件中的完整代码如下所示:

 
  1. #import "TRCell.h"
  2. @implementation TRCell
  3. - (id)initWithFrame:(CGRect)frame
  4. {
  5. self = [super initWithFrame:frame];
  6. if (self) {
  7. self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
  8. self.label.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  9. self.label.textAlignment = NSTextAlignmentCenter;
  10. self.label.backgroundColor = [UIColor lightGrayColor];
  11. self.label.textColor = [UIColor blackColor];
  12. [self.contentView addSubview:self.label];
  13. self.contentView.layer.borderWidth = 1.0f;
  14. self.contentView.layer.cornerRadius = 8.0;
  15. self.contentView.layer.masksToBounds = YES;
  16. self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;
  17. }
  18. return self;
  19. }
  20. @end

本案例中,TRCollectionViewCustomLayout.m文件中的完整代码如下所示:

 
  1. #import "TRCollectionViewCustomLayout.h"
  2. @implementation TRCollectionViewCustomLayout
  3. - (id)initWithCoder:(NSCoder *)aDecoder
  4. {
  5. self = [super initWithCoder:aDecoder];
  6. if (self) {
  7. [self initiate];
  8. }
  9. return self;
  10. }
  11. - (void)initiate
  12. {
  13. //设置Cell的大小
  14. self.itemSize = CGSizeMake(100, 100);
  15. //设置CollectionView的滚动方向
  16. self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  17. //设置CollectionView的内边距
  18. self.sectionInset = UIEdgeInsetsMake(100, 0, 100, 0);
  19. //设置Cell之间的间距
  20. self.minimumLineSpacing = 50;
  21. }
  22. //当边界改变时重新计算布局
  23. - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
  24. {
  25. return YES;
  26. }
  27. //返回所有Cell的布局属性
  28. - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
  29. {
  30. //获取每一个Cell的布局属性
  31. NSArray *array = [super layoutAttributesForElementsInRect:rect];
  32. CGRect visibleRect;
  33. visibleRect.origin = self.collectionView.contentOffset;
  34. visibleRect.size = self.collectionView.bounds.size;
  35. for (UICollectionViewLayoutAttributes *attributes in array) {
  36. CGFloat distance = CGRectGetMidX(visibleRect) - attributes.center.x;
  37. CGFloat distance2 = distance / 100;
  38. if(ABS(distance) < 100){
  39. CGFloat zoom = 1 + 0.3* (1 - ABS(distance2));
  40. attributes.transform3D = CATransform3DMakeScale(zoom, zoom, 1);
  41. }
  42. }
  43. return array;
  44. }
  45. @end

Dynamic Animator 、 CollectionViewLayout的更多相关文章

  1. java之多态(Polymorphic)、动态绑定(Dynamic Binding)、迟绑定(Late Binding)

    今天,我们来说说java面向对象最核心的东西,多态.通过多态可以使我们的程序可复用性达到极致,这就是我们为什么要学多态的原因. “多态”(Polymorphic)也叫“动态绑定”(Dynamic Bi ...

  2. 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )

    在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...

  3. hive中简单介绍分区表(partition table)——动态分区(dynamic partition)、静态分区(static partition)

    一.基本概念 hive中分区表分为:范围分区.列表分区.hash分区.混合分区等. 分区列:分区列不是表中的一个实际的字段,而是一个或者多个伪列.翻译一下是:“在表的数据文件中实际上并不保存分区列的信 ...

  4. [UE4]圆形的动态材质,使用VectorParameter、Get Dynamic Material、Set Vector Parameter Value

    一.新建一个名为M_FriendColor的材质.使用VectorParameter函数 二.新建一个名为FriendFlag的UserWidget,生成随机颜色,并传递给上一步设置的材质参数Colo ...

  5. Objective-C中的@dynamic 、@synthesize

    Objective-C中的@dynamic 一.@dynamic与@synthesize的区别 @property有两个对应的词,一个是@synthesize,一个是@dynamic.如果@synth ...

  6. (8/18)重学Standford_iOS7开发_协议、block、动画_课程笔记

    第八课: 1.协议 另一种安全处理id类型的方式如:id <MyProtocol> obj a.声明 //协议一般放于.h文件中或者在类的.h文件中 @protocol Foo <X ...

  7. iOS开发概述UIkit动力学,讲述UIKit的Dynamic特性,UIkit动力学是UIkit框架中模拟真实世界的一些特性。

    转发:http://my.oschina.net/u/1378445/blog/335014 iOS UIKit动力学 Dynamics UIAttachmentBehavior 实现iMessage ...

  8. AJ学IOS 之UIDynamic重力、弹性碰撞吸附等现象

    AJ分享,必须精品 一:效果 重力和碰撞 吸附现象 二:简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真 ...

  9. var和dynamic的区别

    1.var 1.均是声明动态类型的变量. 2.在编译阶段已经确定类型,在初始化的时候必须提供初始化的值. 3.无法作为方法参数类型,也无法作为返回值类型. 2.dynamic 1.均是声明动态类型的变 ...

随机推荐

  1. HTML第一部分

    HTML      内容(hyper text  markup language,超文本标记语言) CSS        网页美化 Javacript 脚本语言 第一部分 HTML <html ...

  2. Java多线程-新特征-阻塞队列ArrayBlockingQueue

    阻塞队列是Java5线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue,阻塞队列的概念是,一个指定长度的队列,如果队列满了,添加新元素 ...

  3. 用js实现返回上一页

    <a href="javascript :;" onClick="javascript :history.back(-1);">返回上一页</ ...

  4. DOM系列---进阶篇【转】

    内容提纲: 1.DOM类型 2.DOM扩展 3.DOM操作内容 一.DOM类型 DOM基础篇中,我们了解了DOM的节点并且了解怎样查询和操作节点,而本身这些不同的节点,又有着不同的类型.   DOM类 ...

  5. Group by的使用方法

    sql中如果要分组查询,一般都会使用到group by语句,如何熟练使用group by语句呢,我分以下几点进行总结. Group by与聚合函数 Group by与Having 需要注意的地方 Gr ...

  6. 如何在 Ubuntu 15.04 系统中安装 Logwatch

    大家好,今天我们会讲述在 Ubuntu 15.04 操作系统上如何安装 Logwatch 软件,它也可以在各种 Linux 系统和类 Unix 系统上安装.Logwatch 是一款可定制的日志分析和日 ...

  7. bzoj 2049: [Sdoi2008]Cave 洞穴勘测

    #include<cstdio> #include<iostream> using namespace std; ][],n,m,fa[],st[]; ]; bool isro ...

  8. js字符转换成整型 parseInt()函数规程Number()函数

    今天在做一个js加法的时候,忘记将字符转换成整型,导致将加号认为是连接符,  在运算前要先对字符井行类型转换,使用parseInt()函数   使用Number()将字符转换成int型效果更好

  9. RM报表预览,只有固定的1个订单页面

    明明选了多个记录,预览时,只显示最后一个. 原因: 主项数据的数据集选了报表自带的虚拟数据集了.

  10. 五大要求让BPM与企业对接

    BPM(即业务流程管理)在中国已经有多年的发展历史,但人们经常提到的还是企业对流程的迫切需要,鲜有人讨论什么样的企业才能实施BPM,或者换句话说BPM的本身对企业有什么要求.不是所有的工作都适合BPM ...