<iOS 组件与框架> -- UIKit Dynamics
UIKit Dynamics
结合 『iOS 组件与框架 』一书.总结的知识点与demo
demo 地址: GitHub地址
一.概述
1.UIKit Dynamics 是 iOS 7 新增的内容.其 目的
就是为了可以让 UIView能够模拟逼真的物理效果
.
2.通过使用 UIDynamicItem协议
及 支持它的动态物体(dynamic item),可极大的改善用户体验.现在,给界面添加重力、碰撞、弹簧和吸附 (snap)
等效果易如反掌,这些效果让应用给人耳目一新之感.
3.下面会结合示例来讲解.(真机运行效果会更好)
二.UIKit Dynamics 简介
1.UIKit Dynamics 是 iOS 7 新增的一组类和方法
,可赋予 UIView 逼真的行为和特征,让开发人员能够轻松的改善应用的用户体验.简单的说就是,UIKit Dynamics 是个基本的 UIKit 物理引擎,但不像传统物理引擎那样用于开发游戏.
2.要实现动态行为,可创建一个力学动画生成器 UIDynamicAnimator
.每个力学动画生成器,都可以使用各种属性和行为进行定制.如重力,碰撞检测,密度,摩擦力
等等.
3.共有 6 个可用于定制 UIDynamicAnimator 的类.以下这些类都支持定制,他们赋予相关联的 UIView 逼真的行为和动画.
- UIAttchmentBehavior
- UICollisionBehavior
- UIDynamicItemBehavior
- UIGravityBehavior
- UIPushBehavior
- UISnapBehavior
三.实现 UIKit Dynamics
力学动画生成器 (UIDynamicAnimator) 注意点
- 每个 UIDynamicAnimator 都是独立的,多个 UIDynamicAnimator 可同时运行.
- 如果要想让 UIDynamicAnimator 持续运行,必须有指向它的有效引用.
- 相关的物体都处于静止状态后, UIDynamicAnimator 将暂停.不再执行任何计算.但对于未用的 UIDynamicAnimator,,建议将其删除.
1.重力
1.重力是最容易实现,也是最实用的动态行为.效果图
2.实现步骤
- 首先创建一个
力学动画生成器 UIDynamicAniamtor
.并对其强引用.其参考视图设置为当期控制器的view - 创建
动力行为对象 UIGravityBehavior
.并使用数组来初始化它,该数组包含的是要应用重力效果的视图(注意: 动态物体必须是参考视图的子视图,否则力学动画生成器将不会生成任何动态效果). - 设置重力行为.通过
setAngle: magnitude:
方法 - 将重力行为加到力学动画生成器中
3.代码示例
// 1.创建力学动画生成器
// self.view 为力学动画生成器的参考视图
- (UIDynamicAnimator *)dynamicAnimator {
if (nil == _dynamicAnimator) {
_dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
}
return _dynamicAnimator;
}
// 2. 创建重力行为对象
// @[self.gravityEffectView]是用于展示重力行为的视图.自己创建的
- (UIGravityBehavior *)gravityBehavior {
if (nil == _gravityBehavior) {
_gravityBehavior = [[UIGravityBehavior alloc] initWithItems:@[self.gravityEffectView]];
}
return _gravityBehavior;
}
// 3.设置重力行为
[self.gravityBehavior setAngle:M_PI_2 magnitude:0.3f];
4.方法解析
- (void)setAngle:(CGFloat)angle magnitude:(CGFloat)magnitude;
- 主要用来: 设置重力行为的矢量角度和大小
- 参数 angle : 重力矢量的弧度,使用标准的 UIKit 几何.如果指定值 M_PI_2 ,也就是90°,那么就是创建一个力,将重力展示视图向下拖动到参考视图的底部.如果是M_PI_4,就是以45°来拖动.
- 参数 magnitude: 重力的大小.1.0则表示加速度为 1000 点/秒
5.其他说明
- UIKit Dynamics 使用自己的力学系统,被戏称为 UIKit 牛顿定律.(相当接近)
- magnitude的大小,1.0相当于地球引力.带来的加速度为 9.80655 m/s².
- 要指定大约1/10的地球引力.可将作用了设置为0.1
- 如果将 angle,设置为负值的话,那么就会向上拖动
- 本例向下设置,因为没有设置边界碰撞.这个物体不会与别的东西碰撞而停止下落,而是不断往下落
2.碰撞
因为如果只有重力效果的话,那么到达底部的时候,不会停止.而是继续下落.
1.效果图
- 物体只与物体碰撞效果
- 物体只与边界碰撞效果
- 所有东西都可以碰撞(这种的话,两个视图要同时放在一个重力行为中,和一个碰撞行为中,重力和碰撞行为要放在一个力学动画生成器中.)
2.实现步骤
- 创建力学动画生成器 UIDynamicAnimator
- 创建重力行为对象.并设置其 item
- 创建碰撞行为对象,并设置其 item | collisionMode | 定义边界状态 | 代理
3.方法分析
1.碰撞行为模式一共有三种
- UICollisionBehaviorModeItems // 只能物体间碰撞
- UICollisionBehaviorModeBoundaries // 只能与边界碰撞,不能与物体碰撞
- UICollisionBehaviorModeEverything // 与所有东西都可以碰撞
2.如果让物体与边界碰撞,必须定义边界.
// 可以使用这个方法,激活边界
_collisionBehavior.translatesReferenceBoundsIntoBoundary = YES;
3.代理方法有4个
/**
碰撞开始时调用.并指出了边界及接触点
@param behavior 碰撞行为
@param item 发生碰撞行为的视图
@param identifier 接触的边界的标识
@param p 接触点
*/
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p {
}
/**
碰撞开始的时候调用,没有指出边界
@param behavior 碰撞行为
@param item1 发生碰撞的视图1
@param item2 发生碰撞的视图2
@param p 接触点
*/
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item1 withItem:(id<UIDynamicItem>)item2 atPoint:(CGPoint)p {
}
/**
碰撞结束时调用,没有指出边界
@param behavior 碰撞行为
@param item1 发生碰撞的视图1
@param item2 发生碰撞的视图2
*/
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id<UIDynamicItem>)item1 withItem:(id<UIDynamicItem>)item2 {
}
/**
碰撞结束时调用,指出边界
@param behavior 碰撞行为
@param item 发生碰撞的视图1
@param identifier 边界的标识
*/
- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier {
}
3.连接
1.概念
- 连接(attachment)指定了两个物体之间的动态连接.让一个物体的行为和移动受制于另一个物体的移动.
- 默认情况下, UIAttachmentBehaviors 将物体的中心指定为连接点,但可将任何点指定为连接点
2.效果图
4.弹簧效果
弹簧效果是对连接行为的扩展.如下看效果图.
1.UIKitDynamics 让您能够修改 UIAttachmentBehavior 的其他属性,如振动频率和阻尼.
2.创建 UIAttachmentBehavior
对象后可设置了3个属性.
- 设置振动频率
setFrequency
- 熨平动画的峰值
setDamping
- 调整了连接的长度,使其不再是两个图像视图最初的距离.
setLength
3.为更好的延时这些行为,还添加了重力效果.
4.方法解析
/*
* 方法目的 : 初始化动态项的中心附加到指定锚点的行为
* 此方法创建的行为就像一个实心杆,将该项连接到指定的锚点。该项目可以自由地围绕锚点旋转,但它的距离锚定点仍然是固定的。
* item : 动态项
* point : 锚点
*/
- (instancetype)initWithItem:(id<UIDynamicItem>)item attachedToAnchor:(CGPoint)point;
5.弹簧效果与连接不同之处在于,三个设置选项
- (UIAttachmentBehavior *)attachmentBehavior {
if (nil == _attachmentBehavior) {
_attachmentBehavior = [[UIAttachmentBehavior alloc] initWithItem:self.imageView_second attachedToAnchor:CGPointMake(self.imageView_first.center.x, self.imageView_first.center.y)];
[_attachmentBehavior setFrequency:1.0f]; // 设置振动频率
[_attachmentBehavior setDamping:0.1f]; // 熨平动画的峰值
[_attachmentBehavior setLength:100.0f]; // 设置连接的长度
}
return _attachmentBehavior;
}
5.吸附
吸附(snap)行为非常简单,它让物体动态地移到屏幕的另一个地方.
在示例应用中,这种行为是由轻按手势触发的.无论用户再屏幕的什么地方轻按,指定的视图都会跳到指定的地方.每个 UISnapBehavior 都只与一个物体相关联.初始化 UISnapBehavior 时必须指定物体的移动重点.还可指定属性 damping,它决定了物体被吸附时的弹跳粒度
.
1.效果图
2.注意点
如果要想达到如效果图那般连续的吸附行为,必须将之前的吸附行为从力学动画器中移除,然后再添加.否则不会有此效果
3.代码示意
// 轻按手势监听方法
- (void)tapMethod:(UITapGestureRecognizer *)tap {
CGPoint point = [tap locationInView:self.view];
UISnapBehavior *snapBehavior = [[UISnapBehavior alloc] initWithItem:self.imageView_first snapToPoint:point];
snapBehavior.damping = 0.75f;
[self.dynamicAnimator removeAllBehaviors]; // 如果要进行连续的吸附行为,那么就必须把之前的吸附行为从力学动画器中移除
[self.dynamicAnimator addBehavior:snapBehavior];
}
6.推力
UIPushBehavior 使用其来要较之前的复杂一些.但与其他物理引擎相比还是非常容易的.
这里依然使用 collisionBehavior 行为,确保执行推力效果时图像视图始终在屏幕内.
1.效果图
2.计算
这里计算就较为复杂一些,用到一些函数
// 1.计算以 x 为底数的 y 次幂
double pow(double x, double y)
// 2.功能与 pow 一致.只是输入与输出皆为浮点数
float powf(float x, float y)
// 3.开平方
double sqrt (double)
// 4.反正切(整圆值),结果介于[-PI,PI]
double atan2(double, double)
3.点按手势监听代码
- (void)tapMethod:(UITapGestureRecognizer *)tap {
CGPoint locationPoint = [tap locationInView:self.view];
// 参考点
CGPoint oriPoint = CGPointMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds));
// 勾股定理求出距离
CGFloat distance = sqrt(powf(locationPoint.x - oriPoint.x, 2.0) + powf(locationPoint.y - oriPoint.y, 2.0));
// 根据参考点求出角度.从而确定推力的方向
CGFloat angle = atan2(locationPoint.y - oriPoint.y, locationPoint.x - oriPoint.x);
distance = MIN(distance, 100.0);
[self.pushBehavior setMagnitude:distance / 100.0];
[self.pushBehavior setAngle:angle];
[self.pushBehavior setActive:YES];
}
7.物体属性
动态物体有很多默认的属性,我们可以对这些属性进行配置.以定制物理引擎对动态物体的影响.
1.效果图
2.各属性含义
- (UIDynamicItemBehavior *)dynamicItemBehavior {
if (nil == _dynamicItemBehavior) {
_dynamicItemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.imageView_first]];
_dynamicItemBehavior.elasticity // 与其他物体碰撞时的弹性.(0.0~1.0).0.0表示没有弹性.1.0表示反弹的力与作用力一样
= 1.0f;
_dynamicItemBehavior.allowsRotation = NO; // 指定物体在受力时是否旋转
_dynamicItemBehavior.angularResistance = 0.0f; // 指定旋转阻力,值越大,旋转速度下降越快
_dynamicItemBehavior.density = 3.0f; // 物体的密度.调整密度影响重力和碰撞效果
_dynamicItemBehavior.friction = 0.5f; // 物体之间的滑动阻力.0.0表示无摩擦力.1.0表示摩擦力很大.可以超过1.0
_dynamicItemBehavior.resistance = 0.5f; // 空气阻力.(0.0~CGFLOAT_MAX).0.0表示没有空气阻力.1.0表示一旦其他作用力消失,物体就会停止
}
return _dynamicItemBehavior;
}
<iOS 组件与框架> -- UIKit Dynamics的更多相关文章
- iOS 力学动画生成器UIKit Dynamics 之碰撞效果解说
UIKit Dynamic是iOS7 新增的一组类和方法.可赋予UIView逼真的行为和特征,不须要写动画效果那些繁琐的代码,让开发者可以轻松地改善应用的用户体验.一共同拥有6个可用于定制UIDyna ...
- iOS 力学动画生成器UIKit Dynamics 之碰撞效果讲解
UIKit Dynamic是iOS7 新增的一组类和方法,可赋予UIView逼真的行为和特征,不需要写动画效果那些繁琐的代码,让开发人员能够轻松地改善应用的用户体验.一共有6个可用于定制UIDynam ...
- iOS UIKit Dynamics入门 UIKit动力学,实现重力、连接、碰撞、悬挂等动画效果
本文为转载文章 版权归原文所有 什么是UIKit动力学(UIKit Dynamics) 其实就是UIKit的一套动画和交互体系.我们现在进行UI动画基本都是使用CoreAnimation或者UIVie ...
- iOS 组件化路由框架 WisdomRouterKit 的应用
[前言] 大家好,写作是为了和读者沟通交流,欢迎各位开发者一起了解 WisdomRouterKit SDK 的功能. 关于 iOS 组件化路由方案框架: WisdomRouterKit 的功能介绍,之 ...
- iOS 的基本框架
在iOS中框架是一个目录,包含了共享资源库,用于访问该资源库中储存的代码的头文件,以及图像.声音文件等其他资源.共享资源库定义应用程序可以调用的函数和方法. iOS为应用程序开发提供了许多可使用 ...
- ios开发——实用技术篇OC篇&iOS的主要框架
iOS的主要框架 阅读目录 Foundation框架为所有的应用程序提供基本系统服务 UIKit框架提供创建基于触摸用户界面的类 Core Data框架管着理应用程序数据模型 Core ...
- 【iOS】系统框架学习
iOS的系统架构分为四个层次:核心操作系统层(Core OS layer).核心服务层(Core Services layer).媒体层(Media layer)和可触摸层(Cocoa Touch l ...
- [转载]iOS 10 UserNotifications 框架解析
活久见的重构 - iOS 10 UserNotifications 框架解析 TL;DR iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifica ...
- iOS组件化思路 <转>
随着应用需求逐步迭代,应用的代码体积将会越来越大,为了更好的管理应用工程,我们开始借助CocoaPods版本管理工具对原有应用工程进行拆分.但是仅仅完成代码拆分还不足以解决业务之间的代码耦合,为了更好 ...
随机推荐
- 从源码角度入手实现RecyclerView的Item点击事件
RecyclerView 作为 ListView 和 GridView 的替代产物,相信在Android界已广为流传. RecyclerView 本是不会有类似 ListView 的那种点击事件,但是 ...
- 页面性能优化的利器 — Timeline
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 陈泽钦,腾讯移动客户端工程师,目前就职于腾讯MIG移动互联网事业群,负责腾讯浏览服务TBS的X5内核业务. 1 ...
- 原生JS-----论数据类型检测
常见的数据类型检测的方法: 一.最为基础的typeof 二.不可不知的instanceof 三.比instanceof更好的constructor 四.检测值或者表达式的结果是否为NaN 五.易用的j ...
- 取消关联svn
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN] @= ...
- JS执行效率与性能提升方案
如果是追加字符串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr.如果要连接多个字符串,应该少使用+=,如 s+=a;s+=b;s+=c;应该写成s+=a + b + ...
- 阿里的dubbo 到底是用来干嘛的?
Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时 ...
- 解决window.navigator.geolocation.getCurrentPosition在IOS10系统中无法进行地理定位问题
昨天接到用户通知说在点击"看场地"时无法获取地理位置信息. 在接到通知时,首先想到的是排查机型问题.由于客户多为IOS用户,所以最先看的是在安卓是有没有此问题的发生,调查结果为安卓 ...
- zepto全选按钮之全选会根据按钮是否被全部选中更改状态
在做手机端二次开发购物车的时候,发现zepto全选,没找到,或者功能不是自己想要的 后来做好,分享给需要的人 //全选或多选处理 var CheckAll = $('#items_check ...
- call和apply的小结
call和apply的区别: 1.call函数和apply方法的第一个参数都是要传入给当前对象的对象,即函数内部的this.后面的参数都是传递给当前对象的参数. 2.俩者的格式和参数定义: call的 ...
- sendemail 发送成功Email was sent successfully!邮箱却收不到邮件
在测试sendemail的时候,发现好多次明明提示已经发送成功了,但是邮箱却一直收不到邮件. 查询了好多资料,主要原因有两个 1.如果Linux是sentos的话,主要是防火墙iptables和sel ...