XBPageCurl 是一个免费的、开源的 iOS 视图页面卷曲动画/过渡实现,旨在模拟类似于 iBooks 和 GoogleMaps for iOS 等应用程序中的页面行为。
它使用 OpenGL ES 2.0 绘制变形的三角形网格。从概念上讲,它将网格顶点投影到一个虚拟的圆柱上,该圆柱在视图中滚动。您可以移动、旋转圆柱,并改变其半径,是否有动画均可。网格随着圆柱的移动而移动。网格变形在疯狂顶点着色器中执行,使其非常快。
这个页面卷曲效果背后的概念是一个虚拟圆柱,它在页面上方滑动,圆柱右侧的所有内容都绕其卷曲,直到圆柱顶部,然后再在一个水平平面上继续,因此显示出页面的背面。圆柱可以移动和旋转,其半径可以改变。圆柱的位置实际上是其在 xy-平面上的轴的任意点,因此同一轴上的任意点结果为相同的圆柱。
基本上,XBPageCurl 可以以两种不同的方式使用。它可以用来卷曲一个视图并显示它背后的另一个视图,用户可以与其元素交互然后展开视图,类似于 Google Maps 应用(简单的卷曲示例)。它还可以用来像在 iBooks 中翻页,用户可以拖动页面的边缘并释放来翻页或取消翻页(页面卷曲示例)。
XBCurlView 是一个低级类,用于执行视图卷曲的实际工作。它有方法用于在其三个页面中绘制视图或图像(卷曲页面的前面和背面以及下一页)和用于控制在卷曲视图上方移动的圆柱。它可以用来像在 Google Maps 中那样卷曲一个视图并显示其背后的另一个视图,或用于进行其他定制的视图卷曲过渡。
使用它之前,您需要使用最符合您需求的初始化器初始化一个实例。`initWithFrame:`初始化器是一个不错的选择,它将创建一个与框架大小成比例的网格网格,这对半径超过20的圆柱体来说效果良好。`initWithFrame:antialiasing:`允许您指定是否要将OpenGL ES多抽样抗锯齿设置为开启,以获得更平滑的边缘。`initWithFrame:horizontalResolution:verticalResolution:antialiasing`允许您选择网格分辨率(网格网格上的行数和列数),您应尽量保持其与框架大小的比例,以获得正方形的网格,而不是矩形网格。您只有在开始看到网格卷曲部分的三角形形状时,才应该担心网格分辨率,这些可以通过增加分辨率来平滑。
将任意视图卷曲的一种简单方法是通过调用辅助方法`-[XBCurlView curlView:cylinderPosition:cylinderAngle:cylinderRadius:animatedWithDuration:]`和`-[XBCurlView uncurlAnimatedWithDuration:]`,这样可以完成所有工作,包括将XBCurlView实例作为子视图添加,并将要卷曲的视图从其父视图中删除,然后在解卷曲动画之后将其再次添加。它的用法很简单,您可以在示例应用程序的RootViewController的按钮操作方法中看到它的一个示例。
如果您想要更多控制,您必须自己处理设置过程,这通常类似于在`-[XBCurlView curlView:cylinderPosition:cylinderAngle:cylinderRadius:animatedWithDuration:]`和`-[XBCurlView uncurlAnimatedWithDuration:]`方法中采取的步骤。初始化XBCurlView实例后,您应该使用`drawViewOnFrontOfPage:`或`drawImageOnFrontOfPage:`在这些网格前方绘制您希望卷曲的视图或图像,这将绘制将要卷曲的网格前方的视图或图像。您还应该将XBCurlView实例的`opaque`设置为NO,这样在页面不覆盖的区域就可以透过它看到,这允许您看到XBCurlView后面的视图并与它们交互。
要解卷曲视图,只需通过动画将圆柱体位置、方向和半径设置回初始状态,并为其其中之一分配一个完成块,使原始视图再次添加,从其父视图中删除XBCurlView实例,并调用停止动画以停止OpenGL ES渲染循环。
//Initializing a XBCurlView instance in viewDidLoad in the root view controller
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect r = CGRectZero;
r.size = self.view.bounds.size;
self.curlView = [[[XBCurlView alloc] initWithFrame:r] autorelease];
[self.curlView drawViewOnFrontOfPage:self.messyView];
self.curlView.opaque = NO;
}
每次您想要卷曲视图时,首先在页面上再次绘制它以更新卷曲网格上的图像,设置初始的圆柱体属性,然后通过动画设置最终属性,将XBCurlView实例添加为将要卷曲的视图的父视图的子视图,使其位于该视图之上,并将另一个视图从其父视图中删除,使该视图后面的视图出现。最后,您必须对XBCurlView实例调用`startAnimating`以开始渲染OpenGL ES内容。动画完成后,您可以使用`stopAnimating`停止动画(使用动画完成块这样做)。
GRect frame = self.view.frame;
double angle = M_PI/2.5;
//Reset cylinder properties, positioning it on the right side, oriented vertically
self.curlView.cylinderPosition = CGPointMake(frame.size.width, frame.size.height/2);
self.curlView.cylinderAngle = M_PI_2;
self.curlView.cylinderRadius = 20;
//Update the view drawn on the front of the curling page
[self.curlView drawViewOnFrontOfPage:self.messyView];
//Start the cylinder animation
[self.curlView setCylinderPosition:CGPointMake(frame.size.width/6, frame.size.height/2) animatedWithDuration:kDuration];
[self.curlView setCylinderDirection:CGPointMake(cos(angle), sin(angle)) animatedWithDuration:kDuration];
[self.curlView setCylinderRadius:UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPad? 160: 70 animatedWithDuration:kDuration completion:^{
[self stopAnimating]; //Stop the OpenGL animation loop after these animations are finished
}];
//Setup the view hierarchy
[self.view addSubview:self.curlView];
[self.messyView removeFromSuperview];
//Start the rendering loop
[self.curlView startAnimating];
要解卷曲视图,只需通过动画将圆柱体位置、方向和半径设置回初始状态,并为其其中之一分配一个完成块,以添加原始视图、从其父视图中删除XBCurlView实例并调用停止动画以停止渲染循环。
CGRect frame = self.view.frame;
//Animate the cylinder back to its start position at the right side of the screen, oriented vertically
[self.curlView setCylinderPosition:CGPointMake(frame.size.width, frame.size.height/2) animatedWithDuration:kDuration];
[self.curlView setCylinderDirection:CGPointMake(0,1) animatedWithDuration:kDuration];
[self.curlView setCylinderRadius:20 animatedWithDuration:kDuration completion:^(void) {
//Setup the view hierarchy properly after the animation is finished
[self.view addSubview:self.messyView];
[self.curlView removeFromSuperview];
//Stop the rendering loop since the curlView won't appear at the moment
[self.curlView stopAnimating];
}];
//Start the rendering loop
[self.curlView startAnimating];
您可以在`-[XBCurlView curlView:cylinderPosition:cylinderAngle:cylinderRadius:animatedWithDuration:]`和`-[XBCurlView uncurlAnimatedWithDuration:]`方法中找到一个实现这些步骤的工作实例。
请注意,XBCurlView在渲染时不受框架更改的支持。因此,在进行界面方向更改时要小心。
XBPageCurlView 是一种支持像翻书一样用手指拖动页面的视图。它是 XBCurlView 的子类,为它添加了触摸处理功能。它控制圆柱形页面,使页面角能够跟随用户的手指移动。它还支持粘性点(XBSnappingPoint 类),圆柱可以粘附在粘性点上,并在粘附前后通过协议通知其代理。其使用方式与 XBCurlView 几乎相同。
XBPageDragView 是一种视图,当在视图上拖动手指时,会自动创建和动画化 XBPageCurlView。只需创建其实例一个(在 Interface Builder 中或通过程序),设置其在 viewToCurl
属性中的卷曲视图,然后您就配置好了。由于页面网格依赖于卷曲视图的大小,因此每当该视图的框架发生变化时,您都应该调用 -[XBPageDragView refreshPageCurlView]
。查看 PageCurlViewController* 获取详细信息。