iphone阅读模式翻页_Leaves -- iOS上一种图书翻页效果的实现

特性Leaves支持:文本、图像、PDF等任何可被渲染到Graphics Context上的对象通过拖动或点击来翻页支持ipad和iphone大小的显示区域Levels目前不支持以下特性页面上的交互元素轻扫动作类和接口Leaves中主要有三个类:LevelsView、LevelsViewController、LevelsCache:LevelsCache:是一个辅助类,用于缓存显示页。它将显示的内容缓存为图片并保存。LevelsView:是翻页视图,翻页的主要效果便在些实现。它定义了一系列的层对象,并通过操作这些层对象来实现翻页中各种效果。LevelsViewController: LevelsView的控制器类似于UITableView, LevelsView也有一个相关的数据源类(LeaveViewDataSource)与委托类(LeavesViewDelegate),它们分别有两个方法,如下所示复制代码@protocol LeavesViewDataSource - (NSUInteger) numberOfPagesInLeavesView:(LeavesView*)leavesView;- (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx;@end@protocol LeavesViewDelegate @optional- (void) leavesView:(LeavesView *)leavesView willTurnToPageAtIndex:(NSUInteger)pageIndex;- (void) leavesView:(LeavesView *)leavesView didTurnToPageAtIndex:(NSUInteger)pageIndex;@end层树结构LevelsView中的层树结构如下图所示:每一个层(Layer)都有其特殊的用途,或作为内容的显示层,或作为阴影层,具体说明如下:topPage层:显示当前页的内容。topPageOverlay层:在翻页过程中,该层覆盖于topPage层上,且颜色偏暗,从而使topPage未翻转的部分变暗,有阴影的感觉。topPageShadow层:在翻页过程中,该层用于表达topPage被翻转部分所形成的阴影。topPageReverse层:翻页过程中,topPage被翻转部分的反面的容器层。topPageReverseImage层:反面的内容页。在竖屏下,用于显示topPage被翻转部分的内容,这些内容被映射到该层,给人感觉书是透明的。在横屏下,显示的是下一页的内容。topPageReverseOverlay层:该层用于覆盖topPageReverse层,效果与topPageOverlay类似。topPageReverseShading层:该层在topPageReverse层右侧形成一个阴影。bottomPage层:topPage页的下一页所在的层。bottomPageShadow层:该层为在翻页过程中在 bottomPage左侧形成的一个阴影层。leftPage层:该层为横屏模式下左侧页所在的层。leftPageOverlay层:该层覆盖于为 leftPage层,效果与topPageOverlay类似。由上可以看出,层树中的层主要分为三类:内容显示层:topPage、topPageReverseImage、bottomPage、leftPage阴影层:topPageShadow、topPageReverseShading、bottomPageShadow覆盖层:topPageOverlay、topPageReverseOverlay、leftPageOverlay图片缓存Tow Brow在处理不同的内容(文本、图像、PDF)时显示时,所采取的方法是一样的。他将内容缓存为图像,并显示在屏幕上。基本方法是将内容写进CGContextRef中,然后根据CGContextRef中的信息创建图像,具体方法如下:复制代码-(CGImageRef) imageForPageIndex:(NSUInteger)pageIndex {CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(NULL,pageSize.width,pageSize.height,8, /* bits per component*/pageSize.width * 4, /* bytes per row */colorSpace,kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);CGColorSpaceRelease(colorSpace);CGContextClipToRect(context, CGRectMake(0, 0, pageSize.width, pageSize.height));[dataSource renderPageAtIndex:pageIndex inContext:context];CGImageRef image = CGBitmapContextCreateImage(context);CGContextRelease(context);[UIImage imageWithCGImage:image];CGImageRelease(image);return image;}当然程序没有缓存所有页的内容,而是根据横竖屏的不同缓存适当数量的内容。每次翻页时会重新整理缓存中的内容。翻页动画实现在Leaves中,翻页的基本原理其实很简单:翻页过程中,根据手指的划动来不断的调整层树结构中每个层的frame,翻页结束后,重新调整内容显示层所显示的内容。为此,LevelsView中设置了一个leafEdge变量,该变量是手指在屏幕上划动时Touch Point在屏幕x轴上的百分比位置,这个操作在touchesMoved:withEvent中完成:复制代码- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {......UITouch *touch = [event.allTouches anyObject];CGPoint touchPoint = [touch locationInView:self];[CATransaction begin];[CATransaction setValue:[NSNumber numberWithFloat:0.07]forKey:kCATransactionAnimationDuration];self.leafEdge = touchPoint.x / self.bounds.size.width;[CATransaction commit];}而在leafEdge的set方法中,我们根据leafEdge的值来重新设定各个Layer的frame属性复制代码- (void) setLayerFrames {CGRect rightPageBoundsRect = self.layer.bounds;CGRect leftHalf, rightHalf;CGRectDivide(rightPageBoundsRect, &leftHalf, &rightHalf, CGRectGetWidth(rightPageBoundsRect) / 2.0f, CGRectMinXEdge);if (self.mode == LeavesViewModeFacingPages) {rightPageBoundsRect = rightHalf;}topPage.frame = CGRectMake(rightPageBoundsRect.origin.x,rightPageBoundsRect.origin.y,leafEdge * rightPageBoundsRect.size.width,rightPageBoundsRect.size.height);topPageReverse.frame = CGRectMake(rightPageBoundsRect.origin.x + (2*leafEdge-1) * rightPageBoundsRect.size.width,rightPageBoundsRect.origin.y,(1-leafEdge) * rightPageBoundsRect.size.width,rightPageBoundsRect.size.height);......}最后便是当手指离开屏幕时,如何处理翻页结果(将当前页翻过去还是没有翻过去)。这个操作在 这个操作在touchesEnded:withEvent中完成复制代码- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {......UITouch *touch = [event.allTouches anyObject];CGPoint touchPoint = [touch locationInView:self];BOOL dragged = distance(touchPoint, touchBeganPoint) > [self dragThreshold];[CATransaction begin];float duration;if ((dragged && self.leafEdge < 0.5) || (!dragged && [self touchedNextPage])) {[self willTurnToPageAtIndex:currentPageIndex + numberOfVisiblePages];self.leafEdge = 0;duration = leafEdge;......}else {[self willTurnToPageAtIndex:currentPageIndex];self.leafEdge = 1.0;duration = 1 - leafEdge;.......}[CATransaction setValue:[NSNumber numberWithFloat:duration]forKey:kCATransactionAnimationDuration];[CATransaction commit];}如果需要在翻页后执行某些操作(如在屏幕上显示当前页数等),则可以在继承自 LevelsViewController的控制器中实现leavesView:didTurnToPageAtIndex方法。在此需要注意的就是 topPageReverseImage在竖屏时做了如下的变换复制代码topPageReverseImage.contentsGravity = kCAGravityRight;topPageReverseImage.transform = CATransform3DMakeScale(-1, 1, 1);从而使topPageReverseImage显示的内容让人感觉是透过纸张,看到topPage的内容。横屏与竖屏Leaves还有一个特点就是其支持横屏时,能同时看到两页的内容(该效果是由Ole Begemann改进的)。该改进最关键的地方就是增加了leftPage层,同时在横屏显示时将屏幕一分为二,在左侧显示leftPage。同进在翻页的过程中,topPageReverseImage显示的是topPage页下一页的内容。在翻转屏幕时,会根据方向重新调整内容的显示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值