类似于在iOS 7中打开应用程序的Segue动画:viewcontroller帧不可调整大小
我愿意创建一个类似于在iOS 7中打开应用程序的segue动画。现在我考虑这个方法,但是遇到了一个问题:如果在自定义SeGUE中实现,代码不能调整VIEW控制器的帧大小,这是动画的主要部分。如我所见,它应用viewcontroller的位置,但无法更改其大小。我说的对吗?属性viewcontroller.view.frame不能设置动画,必须保持不变并等于设备屏幕的大小?我已经用类似于在iOS 7中打开应用程序的Segue动画:viewcontroller帧不可调整大小,ios,objective-c,animation,uiviewcontroller,segue,Ios,Objective C,Animation,Uiviewcontroller,Segue,我愿意创建一个类似于在iOS 7中打开应用程序的segue动画。现在我考虑这个方法,但是遇到了一个问题:如果在自定义SeGUE中实现,代码不能调整VIEW控制器的帧大小,这是动画的主要部分。如我所见,它应用viewcontroller的位置,但无法更改其大小。我说的对吗?属性viewcontroller.view.frame不能设置动画,必须保持不变并等于设备屏幕的大小?我已经用CGAffineTransformMakeScale实现了类似的东西,但是它有点奇怪,所以我正在寻找更好的解决方案。下
CGAffineTransformMakeScale
实现了类似的东西,但是它有点奇怪,所以我正在寻找更好的解决方案。下面我将粘贴用于segue的代码
#import "ZoomSegue.h"
#import "MiniMapViewController.h"
#import "InteractiveMapViewController.h"
@implementation ZoomSegue
- (void)perform {
InteractiveMapViewController *sourceViewController = self.sourceViewController;
MiniMapViewController *destinationViewController = self.destinationViewController;
destinationViewController.view.alpha = 0.0f;
destinationViewController.view.hidden = NO;
//Just to check, lets make view really small. Position it to the center we get from the segue.
destinationViewController.view.frame = CGRectMake(_originatingPoint.x, _originatingPoint.y, 60.0f, 60.0f);
[sourceViewController.view addSubview:destinationViewController.view];
float animationDuration = 1.5f;
[UIView animateWithDuration:animationDuration/2.0f animations:^{
destinationViewController.view.alpha = 1.0f;
}];
[UIView animateWithDuration:animationDuration animations:^{
//Just to check, lets make view very big. It does not work, although, the view goes to the upper left corner, so position works, but not the size
CGRect x = CGRectMake(0.0f, 0.0f, 9590.0f, 91366.0f);
destinationViewController.view.frame = x;
}];
}
@end
我不知道你是否正确,但更好的方法是使用快照视图。这段代码在屏幕中央放置一个小快照,然后将其扩展为全尺寸
- (void)perform {
UIView *sourceView = ((UIViewController *)self.sourceViewController).view;
UIView *destinationView = [((UIViewController *)self.destinationViewController).view snapshotViewAfterScreenUpdates:YES];
destinationView.frame = CGRectMake(0, 0, 5, 5);
destinationView.center = CGPointMake(sourceView.center.x, sourceView.center.y);
[sourceView addSubview:destinationView];
[UIView animateWithDuration:1
animations:^{
destinationView.frame = sourceView.frame;
}
completion:^(BOOL finished) {
[[self sourceViewController] presentViewController:[self destinationViewController] animated:NO completion:nil];
}];
}
编辑后:
下面是您提供的链接中的代码翻译,该链接将该动画转换为片段
-(void)perform {
CGFloat duration = .25;
UIViewController *source = self.sourceViewController;
UIView *bg = [source.view snapshotViewAfterScreenUpdates:YES];
bg.frame = UIScreen.mainScreen.bounds;
UIViewController *dest = self.destinationViewController;
UIView *icon = [dest.view snapshotViewAfterScreenUpdates:YES];
icon.frame = self.iconFrame;
icon.alpha = 0.0f;
[source.view addSubview:bg];
[source.view addSubview:icon];
[UIView animateWithDuration:duration animations:^{
icon.alpha = 1.0f;
}];
[UIView animateWithDuration:duration*2 animations:^{
icon.frame = UIScreen.mainScreen.bounds;
bg.frame = [self zoomedRect];
} completion:^(BOOL finished) {
[source presentViewController:dest animated:NO completion:nil];
[bg removeFromSuperview];
[icon removeFromSuperview];
}];
}
- (CGRect)zoomedRect {
float screenWidth = UIScreen.mainScreen.bounds.size.width;
float screenHeight = UIScreen.mainScreen.bounds.size.height;
float size = screenWidth / self.iconFrame.size.width;
float x = screenWidth/2 - (CGRectGetMidX(self.iconFrame) * size);
float y = screenHeight/2 - (CGRectGetMidY(self.iconFrame) * size);
return CGRectMake(x, y, screenWidth * size, screenHeight * size);
}
我在segue的.h文件中有一个CGRect属性iconFrame。我从一个连接到将要展开的图标上的点击手势识别器中执行了这个步骤。您需要将该图标的帧传递给segue,这是我在源代码视图控制器的prepareforsgue方法中执行的操作
-(void)prepareForSegue:(SpringboardSegue *)segue sender:(UITapGestureRecognizer *)sender {
segue.iconFrame = sender.view.frame;
}
我用SWIFT翻译了相同的代码
class CustomOpenSegue: UIStoryboardSegue {
var iconFrame = CGRect()
override func perform(){
var sourceViewController: UIViewController = self.sourceViewController as UIViewController
var bg:UIView = sourceViewController.view.snapshotViewAfterScreenUpdates(true)
bg.frame = UIScreen.mainScreen().bounds
var destinationViewController: UIViewController = self.destinationViewController as UIViewController
var icon:UIView = destinationViewController.view.snapshotViewAfterScreenUpdates(true)
icon.frame = self.iconFrame
icon.alpha = 0.0
sourceViewController.view.addSubview(icon)
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
icon.alpha = 1.0
}, completion: nil )
UIView.animateWithDuration(0.5, delay: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
() -> Void in
icon.frame = UIScreen.mainScreen().bounds
bg.frame = self.zoomedRect
}) { (finished) -> Void in
sourceViewController.navigationController?.pushViewController(destinationViewController, animated: false)
icon.removeFromSuperview()
bg.removeFromSuperview()
}
}
var zoomedRect:CGRect{
var screenWidth = UIScreen.mainScreen().bounds.size.width
var screenHeight = UIScreen.mainScreen().bounds.size.height
var size = screenWidth / self.iconFrame.size.width
var x = screenWidth / 2 - CGRectGetMidX(self.iconFrame) * size
var y = screenHeight / 2 - CGRectGetMidY(self.iconFrame) * size
return CGRectMake(x, y, screenWidth * size, screenHeight * size)
}
}
这就是你所说的:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue is CustomOpenSegue{
let customOpenSegue = segue as CustomOpenSegue
customOpenSegue.iconFrame = self.mapButtonFrame!
}
}
非常感谢。我有这样的想法,但要创建一些“截图”并用作UIImageView。我现在就试试你的想法。它几乎能正常工作。现在我还需要sourceView放大一点,但不影响它的子对象。有可能使这些变换相对于某个静态点吗?@RichardTopchiy,我认为这是不可能的,但请你再解释一下你想要什么。你可以在动画中看到:@RichardTopchiy,不确定你说的不影响孩子是什么意思。在我看来,动画是通过在图标所在的上方添加新视图的小快照来完成的,然后扩展和移动源视图的快照(另一个快照作为子视图),从而使小快照居中并全屏显示。