- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想以模态方式显示 UIViewController
并且能够看到呈现它的 View 的模糊版本。
下面是一些类似的问题,例如:
iOS 7 Translucent Modal View Controller
我已将背景添加到我的 Controller View 中,该 View 基于呈现 Controller 的捕获 View 。我面临的问题是我的应用程序支持多个方向,当呈现和旋转模态视图时,底层背景图像不再匹配。
我尝试在模态视图 Controller 的 didRotateFromInterfaceOrientation:
中获取呈现 View Controller 的新快照,但呈现 View Controller 的 UI 似乎没有更新,生成的图像仍然是错误的方向。有什么方法可以强制重绘被模态视图隐藏的 View 吗?
最佳答案
经过长时间的考虑,我想出了一个可以接受的处理方式。它的工作效果在一定程度上取决于您在呈现 viewController
中的内容类型。
总体思路是在呈现新的 viewController
之前截取两张屏幕截图,一张用于纵向,一张用于横向。这是通过更改顶部 viewController
和导航栏(如果适用)的框架以模拟不同的方向,获取结果的屏幕截图并将其更改回来来实现的。用户永远不会在设备上看到这种变化,但屏幕抓取仍然显示新的方向。
确切的代码将取决于您从何处调用它,但主要逻辑是相同的。我的实现从 AppDelegate
运行,因为它被 UIViewController
的几个子类重用。
以下是获取相应屏幕截图的代码。
// get references to the views you need a screenshot of
// this may very depending on your app hierarchy
UIView *container = [self.window.subviews lastObject]; // UILayoutContainerView
UIView *subview = container.subviews[0]; // UINavigationTransitionView
UIView *navbar = container.subviews[1]; // UINavigationBar
CGSize originalSubviewSize = subview.frame.size;
CGSize originalNavbarSize = navbar.frame.size;
// compose the current view of the navbar and subview
UIImage *currentComposed = [self composeForeground:navbar withBackground:subview];
// rotate the navbar and subview
subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.height, originalSubviewSize.width);
// the navbar has to match the width of the subview, height remains the same
navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalSubviewSize.height, originalNavbarSize.height);
// compose the rotated view
UIImage *rotatedComposed = [self composeForeground:navbar withBackground:subview];
// change the frames back to normal
subview.frame = CGRectMake(subview.frame.origin.x, subview.frame.origin.y, originalSubviewSize.width, originalSubviewSize.height);
navbar.frame = CGRectMake(navbar.frame.origin.x, navbar.frame.origin.y, originalNavbarSize.width, originalNavbarSize.height);
// assign the variables depending on actual orientations
UIImage *landscape; UIImage *portrait;
if (originalSubviewSize.height > originalSubviewSize.width) {
// current orientation is portrait
portrait = currentComposed;
landscape = rotatedComposed;
} else {
// current orientation is landscape
portrait = rotatedComposed;
landscape = currentComposed;
}
CustomTranslucentViewController *vc = [CustomTranslucentViewController new];
vc.backgroundSnap = portrait;
vc.backgroundSnapLandscape = landscape;
[rooVC presentViewController:vc animated:YES completion:nil];
composeForeground:withBackground:
方法是一种基于两个输入 View (导航栏 + View Controller )生成适当背景图像的便捷方法。除了将两个 View 组合在一起之外,在旋转呈现的 viewController
时,它还可以使结果看起来更自然。具体来说,它将屏幕截图扩展到 1024x1024 正方形,并用合成图像的镜像副本填充额外空间。在许多情况下,一旦模糊,这看起来就足够了,因为针对方向更改重新绘制 View 的动画不可用。
- (UIImage *)composeForeground:(UIView *)frontView withBackground:(UIView *)backView {
UIGraphicsBeginImageContextWithOptions(backView.frame.size, 0, 0);
[backView.layer renderInContext:UIGraphicsGetCurrentContext()];
// translation is necessary to account for the extra 20 taken up by the status bar
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), frontView.frame.origin.x, frontView.frame.origin.y);
[frontView.layer renderInContext:UIGraphicsGetCurrentContext()];
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -frontView.frame.origin.x, -frontView.frame.origin.y);
// this is the core image, would have left it at this if we did not need to use fancy mirrored tiling
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// add mirrored sections
CGFloat addition = 256; // 1024 - 768
if (newImage.size.height > newImage.size.width) {
// portrait, add a mirrored image on the right
UIImage *horizMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationUpMirrored];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width+addition, newImage.size.height), 0, 0);
[horizMirror drawAtPoint:CGPointMake(newImage.size.width, 0)];
} else {
// landscape, add a mirrored image at the bottom
UIImage *vertMirror = [[UIImage alloc] initWithCGImage:newImage.CGImage scale:newImage.scale orientation:UIImageOrientationDownMirrored];
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height+addition), 0, 0);
[vertMirror drawAtPoint:CGPointMake(0, newImage.size.height)];
}
// combine the mirrored extension with the original image
[newImage drawAtPoint:CGPointZero];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// for ios 6, crop off the top 20px
if (SYSTEM_VERSION_LESS_THAN(@"7")) {
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newImage.size.width, newImage.size.height-20), NO, 0);
[newImage drawAtPoint:CGPointMake(0, -20)];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return newImage;
}
生成的横向和纵向图像可以根据需要进行模糊和着色,并设置为呈现的 viewController
的背景。使用此 viewController
的 willRotateToInterfaceOrientation:duration:
方法选择适当的图像。
注意:我已尝试尽可能减少对图像和图形上下文所做的工作量,但在生成背景时仍然存在轻微延迟(大约 30-90 毫秒/composeForeground:withBackground:
迭代,取决于内容,在老式慢速 iPad 2 上。如果您知道进一步优化或简化上述解决方案的方法,请分享!
关于ios - 半透明模态 ViewController - 如何处理旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22413606/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!