当存在UIAlertView
时,我需要获取我的应用的屏幕截图。
在iOS7中我使用
[[self getMainWindow] drawViewHierarchyInRect:[[UIScreen mainScreen] bounds] afterScreenUpdates:NO];
问题是图像变成了尴尬的颜色和奇怪的行为。我得到的图像很糟糕 - 以下是我的形象。
我尝试了很多不同的事情,但没有成功地获得正确的颜色和图像。
在iOS6中,我找不到捕获UIAlertView
的方法。实现这一目标的最佳方式是什么?
谢谢!
编辑:
实际上,问题与renderInContext
之前的drawViewHierarchyInRect
有关。
如果我将其删除,则图像属于警报视图本身,而下方没有视图。如果我在它之前保留渲染,那么图像就是结果。任何想法都将受到高度赞赏。
答案 0 :(得分:4)
我无法在屏幕截图中捕获UIAlertview和键盘。
我创建了一个有助于捕获窗口所有元素的屏幕截图的函数。
在这里!
- (UIImage *)screenshot
{
UIWindow *win = appDelegate.window;
// Also checking for version directly for 3.2(.x) since UIGraphicsBeginImageContextWithOptions appears to exist
// but can't be used.
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
if (systemVersion >= 4.0f)
{
UIGraphicsBeginImageContextWithOptions(win.frame.size, NO, 0);
} else {
UIGraphicsBeginImageContext(win.frame.size);
}
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
//NSInteger count = 0;
NSMutableArray *arrAllWindow = [[NSMutableArray alloc] init];
[arrAllWindow addObjectsFromArray:[[UIApplication sharedApplication] windows]]; // This will allow keyboard capturing
//below code will allow UIAlertview capturing
if (IS_Ios8)
{
if ([[[UIApplication sharedApplication].keyWindow description] hasPrefix:@"<_UIAlertControllerShimPresenterWin"])
{
[arrAllWindow addObject:[UIApplication sharedApplication].keyWindow];
}
}
else
{
if ([[[UIApplication sharedApplication].keyWindow description] hasPrefix:@"<_UIModalItemHostingWin"])
{
[arrAllWindow addObject:[UIApplication sharedApplication].keyWindow];
}
}
for (int i=0;i<arrAllWindow.count; i++)
{
UIWindow *window = [arrAllWindow objectAtIndex:i];
// -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]);
// Y-offset for the status bar (if it's showing)
NSInteger yOffset = [UIApplication sharedApplication].statusBarHidden ? 0 : -20;
// 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 + yOffset);
[window drawViewHierarchyInRect:win.frame afterScreenUpdates:YES];
// Restore the context
CGContextRestoreGState(context);
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
答案 1 :(得分:2)
我设法通过捕获UIAlertView
窗口本身来实现它。
我忽略drawViewHierarchyInRect
支持renderInContext
并使用不同的方法呈现UIAlertView
窗口:
CGContextSaveGState(UIGraphicsGetCurrentContext());
// Center the context around the window's anchor point
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), [alertView center].x, [alertView center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(UIGraphicsGetCurrentContext(), [alertView transform]);
// Y-offset for the status bar (if it's showing)
NSInteger yOffset = 0;
if (![UIApplication sharedApplication].statusBarHidden && !isIOS7)
yOffset = -20;
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(UIGraphicsGetCurrentContext(),
-[alertView bounds].size.width * [[alertView layer] anchorPoint].x,
-[alertView bounds].size.height * [[alertView layer] anchorPoint].y + yOffset);
// Restore the context
[[alertView layer] renderInContext:UIGraphicsGetCurrentContext()];
CGContextRestoreGState(UIGraphicsGetCurrentContext());
我通过注册到UIWindowDidBecomeVisibleNotification
并根据获取提醒窗口的窗口前缀 - 在IOS6
和IOS7
之间获得了正确的窗口。
另一个重要问题是主窗口。显然,在IOS7
显示UIAlertView
时,它会成为主窗口,因此在尝试渲染主窗口时,您只能获得没有其下方视图的警报视图。因此,为了获得正确的主窗口,我修改了我的getMainWindow方法以符合这种情况:
- (UIWindow *)getMainWindow
{
UIWindow *topWndow = [UIApplication sharedApplication].keyWindow;
UIViewController *topController = topWndow.rootViewController;
if (topController == nil || [[topWndow description] hasPrefix:@"<_UIModalItemHostingWin"])
{
// The windows in the array are ordered from back to front by window level; thus,
// the last window in the array is on top of all other app windows.
for (UIWindow *aWndow in [[UIApplication sharedApplication].windows reverseObjectEnumerator])
{
if (![[aWndow description] hasPrefix:@"<_UIModalItemHostingWin"])
{
topController = aWndow.rootViewController;
if (topController)
return aWndow;
}
}
}
return topWndow;
}
现在我有一个适用于ios6 / 7
的警报视图的截图答案 2 :(得分:0)
我不知道您是想要图像还是快照视图,但如果是后者,则会拍摄屏幕快照以获取警报视图和背景。作为测试,在创建快照之后,我解除了警报并将快照视图添加为子视图,并且从“实时”警报切换到快照视图是无缝的。
@interface ViewController ()
@property (strong,nonatomic) UIAlertView *alert;
@property (strong,nonatomic) UIView *aView;
@end
@implementation ViewController
- (IBAction)showAlert:(UIButton *)sender {
self.alert = [[UIAlertView alloc] initWithTitle:@"Title" message:@"This is my message to test the alert view" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
[self.alert show];
}
-(void)didPresentAlertView:(UIAlertView *)alertView {
self.aView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:YES];
[self.alert dismissWithClickedButtonIndex:0 animated:NO];
[self.view addSubview:self.aView];
}