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

转发:http://my.oschina.net/u/1378445/blog/335014

iOS UIKit动力学 Dynamics UIAttachmentBehavior 实现iMessage风格

目录[-]

由于博客迁移至www.coderyi.com,文章请看http://www.coderyi.com/archives/426

UIkit动力学是UIkit框架中模拟真实世界的一些特性。

UIDynamicAnimator

主要有UIDynamicAnimator类,通过这个类中的不同行为来实现一些动态特性。

它一般有两种初始化方法,先讲常见的第一种

?


1

animator= [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

动态特性的实现主要依靠它所添加的行为,通过以下方法进行添加和移除,

?


1

2

 [animator addBehavior:attachmentBehavior];

  [animator removeAllBehaviors];

接下来介绍五个不同的行为,UIAttachmentBehavior(吸附),UICollisionBehavior(碰撞),UIGravityBehavior(重力),UIPushBehavior(推动),UISnapBehavior(捕捉)。另外还有一个辅助的行为UIDynamicItemBehavior,用来在item层级设定一些参数,比如item的摩擦,阻力,角阻力,弹性密度和可允许的旋转等等。

UIAttachmentBehavior(吸附)

先讲吸附行为,

它的初始化方法

?


1

2

3

attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:iv

                                                                offsetFromCenter:centerOffset

                                                                attachedToAnchor:location];

item是实现UIDynamicItem协议的id类型,这里设置吸附一个UIImageView的实例iv。offset可以设置吸附的偏移,anchor是设置锚点。

UIAttachmentBehavior有几个属性,例如damping,frequency。damping是阻尼数值,frequency是震动频率

直接上代码,实现一个pan手势,让一个image跟着手势跑

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

-(void)gesture:(UIPanGestureRecognizer *)gesture{

    CGPoint location = [gesture locationInView:self.view];

    CGPoint boxLocation = [gesture locationInView:iv];

    

    switch (gesture.state) {

        case UIGestureRecognizerStateBegan:{

            NSLog(@"you touch started position %@",NSStringFromCGPoint(location));

            NSLog(@"location in image started is %@",NSStringFromCGPoint(boxLocation));

            

            [animator removeAllBehaviors];

            

            // Create an attachment binding the anchor point (the finger‘s current location)

            // to a certain position on the view (the offset)

            

            UIOffset centerOffset = UIOffsetMake(boxLocation.x - CGRectGetMidX(iv.bounds),

                                                 boxLocation.y - CGRectGetMidY(iv.bounds));

            attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:iv

                                                                offsetFromCenter:centerOffset

                                                                attachedToAnchor:location];

        

            attachmentBehavior.damping=0.5;

            attachmentBehavior.frequency=0.8;

            

            

            // Tell the animator to use this attachment behavior

            [animator addBehavior:attachmentBehavior];

            break;

        }

        case UIGestureRecognizerStateEnded: {

               [animator removeBehavior:attachmentBehavior];

           

            break;

        }

        default:

              [attachmentBehavior setAnchorPoint:[gesture locationInView:self.view]];

            break;

    }

}

 

UIPushBehavior(推动)

UIPushBehavior 可以为一个UIView施加一个力的作用,这个力可以是持续的,也可以只是一个冲量。我们可以指定力的大小,方向和作用点等等信息。 

?


1

2

3

   pushBehavior = [[UIPushBehavior alloc]

                                                initWithItems:@[iv]

                                                mode:UIPushBehaviorModeInstantaneous];

UIPushBehavior 有pushDirection、magnitude等属性,

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

//1

            CGPoint velocity = [gesture velocityInView:self.view];

            CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));

            

            if (magnitude > ThrowingThreshold) {

                //2

                pushBehavior = [[UIPushBehavior alloc]

                                                initWithItems:@[iv]

                                                mode:UIPushBehaviorModeInstantaneous];

                pushBehavior.pushDirection = CGVectorMake((velocity.x / 10) , (velocity.y / 10));

                pushBehavior.magnitude = magnitude / ThrowingvelocityPadding;

                

              

                [animator addBehavior:pushBehavior];

                

                //3

//                UIDynamicItemBehavior 其实是一个辅助的行为,用来在item层级设定一些参数,比如item的摩擦,阻力,角阻力,弹性密度和可允许的旋转等等

                NSInteger angle = arc4random_uniform(20) - 10;

                

                itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[iv]];

                itemBehavior.friction = 0.2;

                itemBehavior.allowsRotation = YES;

                [itemBehavior addAngularVelocity:angle forItem:iv];

                [animator addBehavior:itemBehavior];

                

                //4

                [self performSelector:@selector(resetDemo) withObject:nil afterDelay:0.4];

            }

UIGravityBehavior(重力)

直接上代码,实现随机掉落一张图片的代码

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

 // Set up

    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    

    self.gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:nil];

    

  

    

    

    [self.animator addBehavior:self.gravityBeahvior];

 

 

- (void)tapped:(UITapGestureRecognizer *)gesture {

    

    NSUInteger num = arc4random() % 40 + 1;

    NSString *filename = [NSString stringWithFormat:@"m%lu", (unsigned long)num];

    UIImage *image = [UIImage imageNamed:filename];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

    [self.view addSubview:imageView];

    

    CGPoint tappedPos = [gesture locationInView:gesture.view];

    imageView.center = tappedPos;

    

    [self.gravityBeahvior addItem:imageView];

 

}

 

UICollisionBehavior(碰撞)

继续上面的代码,当图片快掉落出边界的时候有 碰撞效果,这个就是UICollisionBehavior实现的。

 

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

// Set up

    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];

    

    self.gravityBeahvior = [[UIGravityBehavior alloc] initWithItems:nil];

    

    self.collisionBehavior = [[UICollisionBehavior alloc] initWithItems:nil];

    self.collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;

    

    self.itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:nil];

    self.itemBehavior.elasticity = 0.6;

    self.itemBehavior.friction = 0.5;

    self.itemBehavior.resistance = 0.5;

    

    

    [self.animator addBehavior:self.gravityBeahvior];

    [self.animator addBehavior:self.collisionBehavior];

    [self.animator addBehavior:self.itemBehavior];

 

 

 

- (void)tapped:(UITapGestureRecognizer *)gesture {

    

    NSUInteger num = arc4random() % 40 + 1;

    NSString *filename = [NSString stringWithFormat:@"m%lu", (unsigned long)num];

    UIImage *image = [UIImage imageNamed:filename];

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

    [self.view addSubview:imageView];

    

    CGPoint tappedPos = [gesture locationInView:gesture.view];

    imageView.center = tappedPos;

    

    [self.gravityBeahvior addItem:imageView];

    [self.collisionBehavior addItem:imageView];

    [self.itemBehavior addItem:imageView];

}

另外,UICollisionBehavior有它的代理,其中列举两个方法,它们表示行为开始和结束的时候的代理。

?


1

2

- (void)collisionBehavior:(UICollisionBehavior*)behavior beganContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier atPoint:(CGPoint)p;

- (void)collisionBehavior:(UICollisionBehavior*)behavior endedContactForItem:(id <UIDynamicItem>)item withBoundaryIdentifier:(id <NSCopying>)identifier;

 

UISnapBehavior(捕捉)

UISnapBehavior 将UIView通过动画吸附到某个点上。

?


1

2

3

4

5

6

7

8

9

10

- (void) handleTap:(UITapGestureRecognizer *)paramTap{

    CGPoint tapPoint = [paramTap locationInView:self.view];

    

    if (self.snapBehavior != nil){

        [self.animator removeBehavior:self.snapBehavior];

    }

    self.snapBehavior = [[UISnapBehavior alloc] initWithItem:self.squareView snapToPoint:tapPoint];

    self.snapBehavior.damping = 0.5f;  //剧列程度

    [self.animator addBehavior:self.snapBehavior];

}

UICollectionView与UIDynamicAnimator

文章开头说到UIDynamicAnimator有两种初始化方法,这里介绍它与UICollectionView的完美结合,让UICollectionView产生各种动态特性的行为。

你是否记得iOS系统中信息应用中的附有弹性的消息列表,他就是加入了UIAttachmentBehavior吸附行为,这里通过一个UICollectionView实现类似效果。

主要是复写UICollectionViewFlowLayout,在layout中为每一个布局属性元素加上吸附行为就可以了。

关于复写layout,可以参考onevcat的博客

http://www.onevcat.com/2012/08/advanced-collection-view/

下面就直接上代码了

首先遍历每个 collection view layout attribute 来创建和添加新的 dynamic animator

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

-(void)prepareLayout {

    [super prepareLayout];

    

    if (!_animator) {

        _animator = [[UIDynamicAnimator alloc] initWithCollectionViewLayout:self];

        CGSize contentSize = [self collectionViewContentSize];

        NSArray *items = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, contentSize.height)];

        

        for (UICollectionViewLayoutAttributes *item in items) {

            UIAttachmentBehavior *attachment = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:item.center];

            

            attachment.length = 0;

            attachment.damping = self.damping;

            attachment.frequency = self.frequency;

            

            [_animator addBehavior:attachment];

        }

    }

}

接下来我们现在需要实现 layoutAttributesForElementsInRect: 和 layoutAttributesForItemAtIndexPath: 这两个方法,UIKit 会调用它们来询问 collection view 每一个 item 的布局信息。我们写的代码会把这些查询交给专门做这些事的 dynamic animator

?


1

2

3

4

5

6

7

-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {

    return [_animator itemsInRect:rect];

}

 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {

    return [_animator layoutAttributesForCellAtIndexPath:indexPath];

}

然后是响应滚动事件的方法

这个方法会在 collection view 的 bound 发生改变的时候被调用,根据最新的 content offset 调整我们的 dynamic animator 中的 behaviors 的参数。在重新调整这些 behavior 的 item 之后,我们在这个方法中返回 NO;因为 dynamic animator 会关心 layout 的无效问题,所以在这种情况下,它不需要去主动使其无效

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {

    UIScrollView *scrollView = self.collectionView;

    CGFloat scrollDelta = newBounds.origin.y - scrollView.bounds.origin.y;

    NSLog(@" %f   %f",newBounds.origin.y,scrollView.bounds.origin.y);

    CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView];

    

    for (UIAttachmentBehavior *behavior in _animator.behaviors) {

        

        CGPoint anchorPoint = behavior.anchorPoint;

        CGFloat distanceFromTouch = fabsf(touchLocation.y - anchorPoint.y);

        CGFloat scrollResistance = distanceFromTouch / self.resistanceFactor;

        

        UICollectionViewLayoutAttributes *item = [behavior.items firstObject];

        CGPoint center = item.center;

        center.y += (scrollDelta > 0) ? MIN(scrollDelta, scrollDelta * scrollResistance)

        : MAX(scrollDelta, scrollDelta * scrollResistance);

        item.center = center;

        

        [_animator updateItemUsingCurrentState:item];

    }

    return NO;

}

让我们仔细查看这个代码的细节。首先我们得到了这个 scroll view(就是我们的 collection view ),然后计算它的 content offset 中 y 的变化(在这个例子中,我们的 collection view 是垂直滑动的)。一旦我们得到这个增量,我们需要得到用户接触的位置。这是非常重要的,因为我们希望离接触位置比较近的那些物体能移动地更迅速些,而离接触位置比较远的那些物体则应该滞后些。

对于 dynamic animator 中的每个 behavior,我们将接触点到该 behavior 物体的  y 的距离除以 500。分母越小,这个 collection view 的的交互就越有弹簧的感觉。

时间: 2024-12-09 14:49:14

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

iOS开发概述UIkit动力学

UIkit动力学是UIkit框架中模拟真实世界的一些特性. UIDynamicAnimator 主要有UIDynamicAnimator类,通过这个类中的不同行为来实现一些动态特性. 它一般有两种初始化方法,先讲常见的第一种 animator= [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; 动态特性的实现主要依靠它所添加的行为,通过以下方法进行添加和移除,  [animator addBehavior:attachmen

Lesson1 -- IOS开发概述 &amp;&amp; HelloWorld

第一部分:IOS开发概述 1. IOS 系统架构 iOS是基于UNIX的,就系统的稳定性而言,要比其他操作系统好很多,我们完全可以相信这个操作系统! iOS的系统架构分为四个层次: 1)可触摸层 2)媒体服务层 3)核心服务层 4)核心操作系统层 如下图: 2. iOS系统架构中各层次的功能 可触摸层(Cocoa Touch):为应用程序开发提供各种有用的框架,并且大部分均与用户界面有关,本质上来说它负责用户在iOS设备上的触摸交互操作. 媒体服务层(Media Services):负责提供用于

UI基础—iOS开发概述

1.一款app立足的两大要素 * 美观的UI界面 * 实用的功能 2.iOS系统架构 * iOS是基于UNIX系统的,就系统的稳定性而言,我们完全可以相信这个系统. * iOS的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch layer).   --可触摸层(Cocoa Touch):为应用程序开发提供各种有用的框架,并且大部分均与用户界面有关,本质上来说

XE6 &amp; IOS开发之开发者账号、苹果证书(3):关于在XE6中使用苹果证书

网上能找到的关于Delphi XE系列的移动开发的相关文章甚少,本文尽量以详细的图文内容.傻瓜式的表达来告诉你想要的答案. 原创作品,请尊重作者劳动成果,转载请注明出处!!! 1.关于在XE6中使用苹果证书. 注意,以下讨论都是以"合法注册开发者账号并支付年费"为前提,利用无证书生成iPA的请无视本文:--------------------------------------------------------------- 未完待续.

IOS开发——UI进阶篇(十三)UITabBarController简单使用,qq主流框架

一.UITabBarController简单使用 // 程序加载完毕 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 创建窗口 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; // 设置窗口的根控制器 UITabB

iOS开发——UI篇OC篇&amp;UIDynamic详解

iOS开发拓展篇—UIDynamic(简单介绍) 一.简单介绍 1.什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象 如:重力.弹性碰撞等现象 2.物理引擎的价值 广泛用于游戏开发,经典成功案例是“愤怒的小鸟” 让开发人员可以在远离物理学公式的情况下,实现炫酷的物理仿真效果 提高了游戏开发效率,产生更多优秀好玩的物理仿真游戏 3.知名的2D物理引擎 Box2d Chipmunk 二.使用

iOS开发项目篇—12搜索框的封装

iOS开发项目篇—12搜索框的封装 一.在“发现”导航栏中添加搜索框 1.实现代码 1 #import "YYDiscoverViewController.h" 2 3 @interface YYDiscoverViewController () 4 5 @end 6 7 @implementation YYDiscoverViewController 8 9 - (void)viewDidLoad 10 { 11 [super viewDidLoad]; 12 13 //添加搜索框

iOS开发之窥探UICollectionViewController(五) --一款炫酷的图片浏览组件

本篇博客应该算的上CollectionView的高级应用了,从iOS开发之窥探UICollectionViewController(一)到今天的(五),可谓是由浅入深的窥探了一下UICollectionView的用法,这些用法不仅包括SDK中自带的流式布局(UICollectionViewDelegateFlowLayout)而且介绍了如何根据你的需求去自定义属于你自己的CollectionView.自定义的CollectionView可谓是非常灵活,其灵活性也决定了其功能的强大.Collect

ios开发介绍

iOS开发概述 •什么是IOS •什么是IOS开发 •为什么要选择IOS开发 •学习IOS开发的准备 1.什么是iOS •iOS是一款由苹果公司开发的操作系统(OS是Operating System的简称),就像平时在电脑上用的Windows XP.Windows 7,都是操作系统 •那什么是操作系统呢?操作系统其实是一种软件,是直接运行在硬件(电脑.手机等)上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行 •iOS与Win7等操作系统的差异 XP.Win7是PC操作系统,也就