两个 UIViews 之间的自定义过渡 [英] Custom transition between two UIViews

查看:18
本文介绍了两个 UIViews 之间的自定义过渡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个视图A"和B".A 浮动在窗口中间(它不是全屏).B,将取代 A 的视图是全屏的.我想编写一个自定义过渡,翻转 A 以在背面显示 B,但同时缩放翻转矩形,以便翻转完成后,B 全屏显示.

我尝试过使用 transitionFromView:toView:duration:options:completion 提供的翻转过渡,但我只能让它翻转整个屏幕,而不是从 A 的帧开始翻转并以 B 的帧结束.

我知道我可以对视图的层进行类似 3D 的转换,但我不确定应该使用哪组动画 API 来完成此操作.我尝试过的一件事是在 transitionWithView:duration:options:animations:completion: 的动画块中修改视图的图层属性,但这不起作用,因为它似乎只支持视图属性修改.

有人能指出我正确的方向吗?我将不胜感激.

更新:这是我迄今为止针对此效果的代码.您可以在此处观看有关其功能的视频:http://www.youtube.com/watch?v=-xNMD2fGRwg

<代码>

CGRect frame = [[UIApplication easybookDelegate] rootViewController].view.bounds ;float statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height ;frame.origin.y = statusHeight ;frame.size.height -= statusHeight ;self.view.frame = 框架;//self.view 是视图B"//将快照作为我们视图的最顶层视图UIImageView *imageView = [[UIImageView alloc] initWithImage:image] ;//图像是视图A"的快照imageView.frame = self.view.bounds ;[self.view addSubview:imageView] ;[self.view bringSubviewToFront:imageView] ;//预转换我们的视图 (s=target/current, d=target-current)CGAffineTransform 变换 = CGAffineTransformIdentity ;//翻译我们的视图CGPoint center = CGPointMake(screenOrigin.x + (image.size.width/2.0), screenOrigin.y + (image.size.height/2.0)) ;float dX = center.x - self.view.center.x ;浮动 dY = center.y - self.view.center.y ;NSLog( @"dx: %f, dy: %f" , dX, dY ) ;变换 = CGAffineTransformTranslate(transform, dX, dY) ;//缩放我们的视图float scaleWFactor = image.size.width/self.view.frame.size.width ;float scaleHFactor = image.size.height/self.view.frame.size.height ;变换 = CGAffineTransformScale(transform,scaleWFactor, scaleHFactor);self.view.transform = 变换;[[[UIApplication easybookDelegate] rootViewController].view addSubview:self.view] ;//由于隐式动画似乎不起作用,因此稍后执行动画//查看B"刚刚被添加到上面并且没有机会变得可见.现在//这只是用于调试目的的计时器.它可能会被转移到其他地方,可能//查看 "B" 的 -didMoveToSuperview双延迟InSeconds = 0.3;dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);dispatch_after(popTime, dispatch_get_main_queue(), ^(void){[UIView transitionWithView:self.view duration:3 options:UIViewAnimationOptionTransitionFlipFromRight|UIViewAnimationOptionCurveEaseOut 动画:^(void){[imageView removeFromSuperview] ;self.view.transform = CGAffineTransformIdentity ;}完成:^(布尔完成){[self.view removeFromSuperview] ;[navController presentModalViewController:self 动画:NO] ;}];});[图片查看发布];

解决方案

我以前做过这个.这是我如何做到的要点:

  1. 视图 A 在屏幕上
  2. 创建视图 B,给它一个框架使其全屏,但不要将其添加到屏幕
  3. 视图 B 有一个 UIImageView 作为它的最顶层视图
  4. 捕获一个View A的UIImage,并将其设置为View B的image view的图像

    UIGraphicsBeginImageContext(view.bounds.size);[viewA.layer renderInContext:UIGraphicsGetCurrentContext()];UIImage *image = UIGraphicsGetImageFromCurrentImageContext();viewB.imageView.image = 图像;

  5. 设置视图 B 的变换(缩放和平移),使其缩小到视图 A 的大小并位于视图 A 在屏幕上的位置

  6. 将视图 B 添加到屏幕
  7. 此时,用户还没有注意到任何变化,因为视图 ​​B 看起来与视图 A 完全一样
  8. 现在开始一个动画块,在其中你
    • 设置[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:ViewB
    • 将视图 B 的变换设置为 CGAffineTransformIdentity
    • 从视图 B 中移除视图 B 的图像

结果是一个动画,看起来像视图 A 正在翻转并缩放以填充屏幕,而视图 B 作为另一侧.

I have two views "A" and "B". A floats in the middle of the window (it's not full screen). B, the view which will replace A, is full screen. I'd like to write a custom transition that flips A to reveal B on the back side, but simultaneously scales the flipping rectangle so that when the flip is finished, B is full screen.

I've tried using the flip transitions available with transitionFromView:toView:duration:options:completion, but I can only get it to flip the entire screen instead of starting the flip with A's frame and ending with B's frame.

I know I can do 3D-like transforms to the view's layers, but I'm not sure which set of animation APIs I should use to accomplish this. One thing I tried is to modify the view's layer properties in the animations block of transitionWithView:duration:options:animations:completion: but that didn't work as it only seems to honor view property modifications.

Can someone point me in the right direction? I'd much appreciate it.

UPDATE: Here is my code thus far for this effect. You can see a video of what it does here: http://www.youtube.com/watch?v=-xNMD2fGRwg

CGRect frame = [[UIApplication easybookDelegate] rootViewController].view.bounds ;
float statusHeight = [UIApplication sharedApplication].statusBarFrame.size.height ;
frame.origin.y = statusHeight ;
frame.size.height -= statusHeight ;
self.view.frame = frame ; // self.view is view "B"

// Put the snapshot as thet topmost view of our view
UIImageView *imageView = [[UIImageView alloc] initWithImage:image] ; // image is a snapshot of view "A"
imageView.frame = self.view.bounds ;
[self.view addSubview:imageView] ;
[self.view bringSubviewToFront:imageView] ;

// Pre-transform our view (s=target/current, d=target-current)
CGAffineTransform transform = CGAffineTransformIdentity ;

// Translate our view
CGPoint center  = CGPointMake(screenOrigin.x + (image.size.width/2.0), screenOrigin.y + (image.size.height/2.0)) ;
float dX = center.x - self.view.center.x ;
float dY = center.y - self.view.center.y ;
NSLog( @"dx: %f, dy: %f" , dX, dY ) ;

transform = CGAffineTransformTranslate(transform, dX, dY) ;

// Scale our view
float scaleWFactor = image.size.width / self.view.frame.size.width ;
float scaleHFactor = image.size.height / self.view.frame.size.height ;
transform = CGAffineTransformScale(transform,scaleWFactor, scaleHFactor) ;

self.view.transform = transform ;

[[[UIApplication easybookDelegate] rootViewController].view addSubview:self.view] ;

// Perform the animation later since implicit animations don't seem to work due to
// view "B" just being added above and hasn't had a chance to become visible. Right now
// this is just on a timer for debugging purposes. It'll probably be moved elsewhere, probably
// to view "B"'s -didMoveToSuperview
double delayInSeconds = 0.3;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [UIView transitionWithView:self.view duration:3 options:UIViewAnimationOptionTransitionFlipFromRight| UIViewAnimationOptionCurveEaseOut animations:^(void) 
        {
        [imageView removeFromSuperview] ;
        self.view.transform = CGAffineTransformIdentity ;
        } 
        completion:^(BOOL finished){
                [self.view removeFromSuperview] ;
                [navController presentModalViewController:self animated:NO] ;
        }] ;
});

[imageView release];

解决方案

I've done this before. Here's the gist of how I did it:

  1. View A is on screen
  2. Create View B, give it a frame that makes it fullscreen, but don't add it to the screen yet
  3. View B has a UIImageView as it's topmost view
  4. Capture a UIImage of View A, and set it as the image of View B's image view

    UIGraphicsBeginImageContext(view.bounds.size); 
    [viewA.layer renderInContext:UIGraphicsGetCurrentContext()]; 
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    viewB.imageView.image = image;
    

  5. Set View B's transform (scale and translation) so that it is shrunk to the size of View A and is positioned where View A is on the screen

  6. Add View B to the screen
  7. At this point, the user hasn't noticed anything change, because View B looks exactly like View A
  8. Now start an animation block, in which you
    • Set [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:ViewB
    • set View B's transform to CGAffineTransformIdentity
    • remove View B's imageview from View B

The result is an animation that looks like View A is flipping over and zooming to fill the screen with View B as the opposite side.

这篇关于两个 UIViews 之间的自定义过渡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆