- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
出于某些原因,我必须使用 addSubview
和 addChildViewController
来替换 View 而不是推送/弹出 View Controller 。问题是我想在更改 UIViewController
(推送/弹出)时完全伪造动画。这是我的尝试:
在RootViewController.m
// switch controller view
currentController = nextViewController;
[self addChildViewController:currentController];
[self.view addSubview:currentController.view];
// pop - move down
[currentController.view setFrame:CGRectMake(self.view.frame.size.width, 0, currentController.view.frame.size.width, currentController.view.frame.size.height)];
[UIView animateWithDuration:0.5
animations:^{
[currentController.view setFrame:CGRectMake(self.view.frame.size.width, self.view.frame.size.height, currentController.view.frame.size.width, currentController.view.frame.size.height)];
[self addConstrainForView];
}];
//Push - move up
[currentController.view setFrame:CGRectMake(0, self.view.frame.size.height, currentController.view.frame.size.width, currentController.view.frame.size.height)];
[UIView animateWithDuration:0.5
animations:^{
[currentController.view setFrame:CGRectMake(0, 0, currentController.view.frame.size.width, currentController.view.frame.size.height)];
[self addConstrainForView];
}];
此代码不作为方面工作,因为下一个 Controller 从底部移动到顶部(推),并且当它移动时,它后面有一个空白背景(根 Controller 的背景).
所以我需要正确的方法来伪造推送和弹出动画(上拉和下拉)。
如有任何帮助,我们将不胜感激。
最佳答案
我在一个应用程序中使用了这个效果。我想要(并且拥有)嵌入到 iPad 应用程序边缘的 iPhone 系列选择屏幕的外观。因此,用户按下列表中的一个按钮,然后屏幕转换(看起来像 UIViewController 前进)到更多选项,尽管它们都在边缘的窗口中(相关内容会在右侧弹出)。这是我使用的代码:
- (void)advanceLevel
{
UIImageView *screenShot = [self getTableScreenShot];
[self.tableView.superview addSubview:screenShot];
// Put screen shot over the whole thing with mask for iPhone style animation
TableViewMask *mask =
[[TableViewMask alloc] initWithFrame:CGRectMake(0, 0, 1024, 768) withImage:[Util TakeScreenshot]];
[self.tableView.superview addSubview:mask];
tableLevel++;
[self updateData];
[UIView animateWithDuration:.6 animations:^
{
screenShot.frame =
CGRectMake(self.tableView.frame.origin.x-self.tableView.frame.size.width, self.tableView.frame.origin.y,
self.tableView.frame.size.width, self.tableView.frame.size.height);
controller.toolbar.backButton.alpha = (tableLevel>1?1:0);
}
completion:^(BOOL finished)
{
[screenShot removeFromSuperview];
[mask removeFromSuperview];
[self updateUI];
}];
}
- (void)goBackLevel
{
if(tableLevel==1){ return; }
if(tableLevel==3 && isEditing==YES)
{
// Skip this screen if coming from higher screens
tableLevel--;
}
UIImageView *screenShot = [self getTableScreenShot];
[self.tableView.superview addSubview:screenShot];
// Put screen shot over the whole thing with mask for iPhone style animation
TableViewMask *mask = [[TableViewMask alloc] initWithFrame:CGRectMake(0, 0, 1024, 768) withImage:[Util TakeScreenshot]];
[self.tableView.superview addSubview:mask];
tableLevel--;
[self updateData];
[UIView animateWithDuration:.6 animations:^
{
screenShot.frame =
CGRectMake(self.tableView.frame.origin.x+self.tableView.frame.size.width, self.tableView.frame.origin.y,
self.tableView.frame.size.width, self.tableView.frame.size.height);
controller.toolbar.backButton.alpha = (tableLevel>1?1:0);
}
completion:^(BOOL finished)
{
[screenShot removeFromSuperview];
[mask removeFromSuperview];
[self updateUI];
}];
}
...这是截屏者:
+ (UIImage *)TakeScreenshot
{
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:@selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
.. 最后是 TableViewMask:
@implementation TableViewMask
UIImage *screenShotImage;
- (instancetype)initWithFrame:(CGRect)frame withImage:(UIImage *)_screenShotImage
{
self = [super initWithFrame:frame];
if(self)
{
self.backgroundColor = [UIColor clearColor];
screenShotImage = _screenShotImage;
[self setNeedsDisplay];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
[screenShotImage drawInRect:rect];
CGRect intersection = CGRectIntersection( CGRectMake(10.2, 130, 299.6, 600), rect );
if( CGRectIntersectsRect( intersection, rect ) )
{
CGContextFillRect(context, CGRectMake(10, 130, 300, 600));
CGContextClearRect(context, intersection);
CGContextSetFillColorWithColor( context, [UIColor clearColor].CGColor );
CGContextFillRect( context, intersection);
}
}
@end
我留下了一些我独有的东西,因为你可能需要类似的电话。例如 [self updateData] 会考虑系统状态来更新模型并设置任何其他基于状态的调用。当屏幕应该被跳过时也有一个异常(exception)我已经留下了。你可以安全地删除那些,尽管你可能需要类似的变体(因为你并没有真正改变 UIViewController 的)。
对此我唯一要注意的是,除非你有像我这样的极端情况——在 iPad 或类似的东西上的弹出 View 中模仿 iPhone——最好只使用真正的 UIVewController。
关于ios - 替换 UIView 时假的推送和弹出动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29349172/
我是一名优秀的程序员,十分优秀!