IOS新版iBooks吸引人的地方除了有干净整洁的界面、方便灵活的操作以及大容量的书籍容量以外。还有其优秀的用户交互,尤其是其动画的使用。打开一本书时书本缓慢放大并打开。关闭一本书后书本关闭并回到原位置。

如今我们来实现这个简单的功能。

效果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzYwNDYxMg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

用到的知识:

1、CAKeyframeAnimation的应用

2、怎样在代理中区分两个不同的动画

3、坐标系转换

思路:

这个动画主要用到的是CAAnimation,而且是CAKeyframeAnimation。当用户点击书本时。设置一个UIImageView(为其加上tag方便以后取)并将其放在选中书本的位置上(使用坐标系转换)。接着通过动画将其放大到全屏,完毕后将其锚点设置为(0,0.5)并让其绕y轴选中π/2角度,将早已放在以下的textView(本app中是自己定义的readView)展示出来。

动画完毕后将UIImageView的透明度设为0。这样就是书本的打开过程。

关闭过程类似,依据tag取出UIImageView并将其旋转,然后设置frame到原来书本的位置(能够用私有变量记录该位置),最后removeFromSuperview就可以。

代码:

首先是“准备阶段”

    //BookReadView是展示textView和顶部底部附加view的自己定义view
CYZBookItemView *itemView = [notification object];
CYZBookReadView *readView = [[CYZBookReadView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height) ItemView:itemView];
//设置delegate是为了当用户从阅读界面返回时做出响应
readView.delegate = self;
//先将其alpha设为0防止用户刚点击书本动画还在进行中时就出现这一界面
readView.alpha = 0.0f;
[self.view addSubview:readView]; //展示动画的UIImageView
UIImageView *showView = [[UIImageView alloc] initWithImage:itemView.bookImage.currentBackgroundImage];
//坐标系转换
_itemPosition = [itemView.superview convertRect:itemView.frame toView:self.view];
showView.frame = _itemPosition;
//设置tag方便以后取出
showView.tag = 1001;
showView.backgroundColor = [UIColor clearColor];
[self.view addSubview:showView];

关于坐标系转换(以矩形为例。point类似):

- (void)convertRect:toView:方法:

格式[被转换者所在的View convertRect:
被转换者的frame或bounds toView:转换到的View];返回在目标View中的rect

比如,将当前视图的子视图viewA中的一个imageView转换到当前视图。

能够例如以下调用:

[viewA convertRect:viewA.imageView.frame toRect:self.view];

或者[imageView.superView convertRect:imageView.frame toRect:self.view];

当中self指控制器。

- (void)convertRect:fromView:方法:

格式[要转换到的View convertRect:
被转换者的frame或bounds fromView:被转换者所在的View];返回在目标View中的rect。

还是上一个样例,能够这样写:

[self.view convertRect:viewA.imageView.frame fromView:viewA];

或者[self.view convertRect:imageView.frame fromView:imageView.superView];

当中self指控制器

接着准备工作完毕了以后就能够開始动画了。

一下是打开动画的部分

    [UIView animateWithDuration:0.5f animations:^{
//将UIImageView放大为全屏
showView.frame = self.view.bounds;
} completion:^(BOOL finished) {
if (finished) {
//展示出readView
readView.alpha = 1.0f; //设置锚点
showView.layer.anchorPoint = CGPointMake(0, 0.5);
#warning 不知道为什么,不加以下这句话showView会显示异常:即仅仅显示一半
showView.frame = CGRectMake(0, 0, showView.width, showView.height); CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
//设置其绕y轴旋转
animation.keyPath = @"transform.rotation.y";
//设置持续时间。能够定义一常量来表示
animation.duration = 0.5f;
animation.speed = 0.55f;
animation.removedOnCompletion = NO;
//旋转π/2度
[animation setValues:[NSArray arrayWithObjects:@0.0f, @-M_PI_2, nil]];
//设置代理便于回调
animation.delegate = self;
//这里必须设置上key,为了接下来区分不同动画
[showView.layer addAnimation:animation forKey:@"rotateToOpenBook"];
}
}];

代码中凝视已经解释得比較具体了,仅仅只是正如warning写得那样。本来我是用showView.layer.transform来实现动画的,这样会省非常多事。比方不用在代理中区分动画、不用记录position来在方法间传值等,只是不知道为什么showView总是仅仅显示一半。求解释╮(╯▽╰)╭

回调中:

[showView setAlpha:0.0f];

将其临时隐藏。关上书时还要用它。

关上书的动画大致类似

#pragma mark - CYZBookViewDelegate

- (void)readViewDidBackWithItem:(CYZBookItemView *)item
{
//取出showView
UIImageView *showView = (UIImageView *)[self.view viewWithTag:1001];
//将其显示出来
showView.alpha = 1.0f;
showView.layer.anchorPoint = CGPointMake(0, 0.5f);
showView.frame = CGRectMake(0, 0, showView.width, showView.height); CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"transform.rotation.y";
animation.duration = 0.5f;
animation.speed = 0.55f;
animation.removedOnCompletion = NO;
//反向旋转
[animation setValues:[NSArray arrayWithObjects:@-M_PI_2, @0, nil]];
animation.delegate = self;
//设置不同的key为了区分动画用
[showView.layer addAnimation:animation forKey:@"rotateToCloseBook"]; }

这里要用一个不同的key来表示这个动画。

该动画的回调:

            [UIView animateWithDuration:0.5f animations:^{
showView.frame = _itemPosition;
} completion:^(BOOL finished) {
[showView removeFromSuperview];
}];

_itemPosition是之前用来记录转换的坐标的私有变量,这几行代码的意思就是让showView回到书本的位置然后令其消失。

这里的关键问题在于。两个动画都用到了回调,怎样区分呢?就用我们之前设置的key来区分:

回调的完整代码:

#pragma mark - AnimationDelegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
UIImageView *showView = (UIImageView *)[self.view viewWithTag:1001];
if (flag) {
if (showView && [[showView.layer animationForKey:@"rotateToOpenBook"] isEqual:anim]) {
[showView setAlpha:0.0f];
} else if (showView && [anim isEqual:[showView.layer animationForKey:@"rotateToCloseBook"]]) {
[UIView animateWithDuration:0.5f animations:^{
showView.frame = _itemPosition;
} completion:^(BOOL finished) {
[showView removeFromSuperview];
}];
}
}
}

通过showView所在层layer的方法 animationForKey:获得自己设置的动画,与代理中的anim做比較就可以区分。

另外。在stackOverflow上还看到一种方法:用kvc的方法为animation设值,并在代理中通过kvc的方法依据这个键取出值并进行推断,应该也是能够的。

ios开发——仿新版iBooks书本打开与关闭动画的更多相关文章

  1. iOS开发 仿淘宝,京东商品详情3D动画

    - (void)show { [[UIApplication sharedApplication].windows[0] addSubview:self.projectView]; CGRect fr ...

  2. iOS开发之判断用户是否打开APP通知开关

    一.前言 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是 ...

  3. iOS开发-仿微信图片分享界面实现

    分享功能目前几乎已成为很多app的标配了,其中微信,微博等app的图片分享界面设计的很棒,不仅能够展示缩略图,还可以预览删除.最近我在做一款社交分享app,其中就要实现图文分享功能,于是试着自行实现仿 ...

  4. iOS 开发仿网易云音乐歌词海报

    使用网易云音乐也是一个巧合,我之前一直使用QQ音乐听歌,前几天下 app 手机内存告急.于是就把QQ音乐给卸载掉了,正好晚上朋友圈里有一个朋友用网易云音乐分享了一首歌曲,于是我也就尝试下载了网易云音乐 ...

  5. iOS开发-仿大众点评iPad侧边导航栏

    昨天其实已经写了一篇侧边栏的文章,不过感觉还不是很清晰,这篇文章算是补充吧,iPad上看了大众点评的侧边栏,基本上百分之九十类似,具体效果可参考下图: 对比昨天主要做了两个修改,一个是图片和文字的显示 ...

  6. 【转】【iOS开发】打开另一个APP(URL Scheme与openURL)

    目标 平常我们做iOS开发,会经常遇到打开其他的APP的功能.本篇文章讲的就是打开别人的APP的一些知识.我们的目标是: 打开别人的APP 让别人打开我们的APP iOS9的适配问题 使用URL Sc ...

  7. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...

  8. 分享iOS开发常用(三方类库,工具,高仿APP,实用网站,技术干货)

    一 . JSONModel  (三方类库会有更新,建议大家在线下载) http://pan.baidu.com/s/1i5ybP1z 二.AFNetworkiong http://pan.baidu. ...

  9. iOS开发之多表视图滑动切换示例(仿"头条"客户端)---优化篇

    前几天发布了一篇iOS开发之多表视图滑动切换示例(仿"头条"客户端)的博客,之所以写这篇博客,是因为一位iOS初学者提了一个问题,简单的写了个demo做了个示范,让其在基础上做扩展 ...

随机推荐

  1. shell -Z- d等等代表

    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 [ -a FILE ]   ...

  2. 【轻院热身赛】级数求和、进制转换、candy

    [题目链接:级数求和] Problem A: 级数求和 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 409  Solved: 240 SubmitSt ...

  3. Android UncaughtExceptionHandler,捕获错误

    最近在做个项目,需要在程序出现运行时异常和错误导致程序crash时进行一些操作,找到一个方法 Thread.setDefaultUncaughtExceptionHandler(new Uncaugh ...

  4. ioctl用法详解 (网络)

    本函数影响由fd参数引用的一个打开的文件. #include#include int ioctl( int fd, int request, .../* void *arg */ );返回0:成功   ...

  5. 你所不知道的 URL

    0.说明 第一幕 产品:大叔有用户反映账户不能绑定公众号.大叔:啊咧咧?怎么可能,我看看?大叔:恩?这也没问题啊,魏虾米.大叔:还是没问题啊,挖叉类.大叔:T T,话说产品姐姐是不是Java提供接口的 ...

  6. ArcMap自定义脚本工具制作

    原文 ArcMap自定义脚本工具制作 在制图的前期,一般需要做一些数据的整理,如图层合并.裁剪等工作.虽然在ArcMap中也有提供对应的工具,但使用起来需要点技巧.如批量裁剪,虽然可以实现,但出来的结 ...

  7. mybatis实战教程(mybatis in action)之九:mybatis 代码生成工具的使用

    mybatis 应用程序,需要大量的配置文件,对于一个成百上千的数据库表来说,完全手工配置,这是一个很恐怖的工作量. 所以mybatis 官方也推出了一个mybatis代码生成工具的jar包. 今天花 ...

  8. Dev gridControl 按回车增加一行

    将NewItemRowPosition属性设置为Top或Bottom, 在这样的新行中输入数据后,会自动添加到绑定的数据源中的, 如果你希望在按回车时焦点跳至下一列, 只需要设置GridView的Op ...

  9. 联通光纤上网配置+华为HG8240光猫+TL-WR842N

    最近搬家改用北京联通宽带,光纤入户的那种.联通送的光猫是华为HG8240,没看到天线,应该是不带无线路由.然后自己再买了个TP-Link的TL-WR842N,用来组局域网,也供ipad.kindle. ...

  10. IOS 点击按钮 光环 冲击波效果

    UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:ROUND_WIDTH/2 - ...