UIKit动力学实现的结构
为了实现动力UI,需要注册一套UI行为的体系,之后UI便会按照预先的设定进行运动了。我们应该了解的新的基本概念有如下四个:
- UIDynamicItem:用来描述一个力学物体的状态,其实就是实现了UIDynamicItem委托的对象,或者抽象为有面积有旋转的质点;
- UIDynamicBehavior:动力行为的描述,用来指定UIDynamicItem应该如何运动,即定义适用的物理规则。一般我们使用这个类的子类对象来对一组UIDynamicItem应该遵守的行为规则进行描述;
- UIDynamicAnimator;动画的播放者,动力行为(UIDynamicBehavior)的容器,添加到容器内的行为将发挥作用;
- ReferenceView:等同于力学参考系,如果你的初中物理不是语文老师教的话,我想你知道这是啥..只有当想要添加力学的UIView是ReferenceView的子view时,动力UI才发生作用。
-
- (void)viewDidLoad { [super viewDidLoad]; UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(100, 50, 100, 100)]; aView.backgroundColor = [UIColor lightGrayColor]; [self.view addSubview:aView]; UIDynamicAnimator* animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; UIGravityBehavior* gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:@[aView]]; [animator addBehavior:gravityBeahvior]; self.animator = animator; }
以现在ViewController的view为参照系(ReferenceView),来初始化一个UIDynamicAnimator。
然后分配并初始化一个动力行为,这里是UIGravityBehavior,将需要进行物理模拟的UIDynamicItem传入。
UIGravityBehavior
的initWithItems:
接受的参数为包含id的数组,另外UIGravityBehavior
实例还有一个addItem:
方法接受单个的id。就是说,实现了UIDynamicItem委托的对象,都可以看作是被力学特性影响的,进而参与到计算中。UIDynamicItem委托需要我们实现bounds
,center
和transform
三个属性,在UIKit Dynamics计算新的位置时,需要向Behavior内的item询问这些参数,以进行正确计算。iOS7中,UIView和UICollectionViewLayoutAttributes已经默认实现了这个接口,所以这里我们直接把需要模拟重力的UIView添加到UIGravityBehavior里就行了。把配置好的UIGravityBehavior添加到animator中。
strong持有一下animator,避免当前scope结束被ARC释放掉(后果当然就是UIView在哪儿傻站着不掉)
UIDynamic提供了以下几种物理仿真行为
UIGravityBehavior:重力行为
UICollisionBehavior:碰撞行为
UISnapBehavior:捕捉行为
UIPushBehavior:推动行为
UIAttachmentBehavior:附着行为
UIDynamicItemBehavior:动力元素行为
- 添加碰撞的动画效果源码:
-
UILabel *aView = [[UILabelalloc] initWithFrame:CGRectMake(0,0, 100,100)];
[aViewsetText:@"123"];
aView.backgroundColor = [UIColorlightGrayColor];
aView.transform =CGAffineTransformRotate(aView.transform,45);
[self.viewaddSubview:aView];
UIDynamicAnimator* animator = [[UIDynamicAnimatoralloc] initWithReferenceView:self.view];
UIGravityBehavior* gravityBeahvior = [[UIGravityBehavioralloc] initWithItems:@[aView]];
[animatoraddBehavior:gravityBeahvior];
UICollisionBehavior* collisionBehavior = [[UICollisionBehavioralloc] initWithItems:@[aView]];
collisionBehavior.translatesReferenceBoundsIntoBoundary =YES;
[animatoraddBehavior:collisionBehavior];
//添加一个椭圆为碰撞边界
UIBezierPath *path = [UIBezierPathbezierPathWithOvalInRect:CGRectMake(0,0, 320,320)];
[collisionBehavioraddBoundaryWithIdentifier:@"circle"forPath:path];
// collisionBehavior.collisionDelegate = self;
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavioralloc] initWithItems:@[aView]];
[itemBehaviorsetElasticity:0.6];
[animatoraddBehavior:itemBehavior];
self.animator = animator;