iOS - screenshot of a hidden UIView - ios

I have a hidden UIView that I need to take a full screenshot of. I don't want to .hidden = NO * take screenshot * .hidden = YES. The reason is because that causes an inverted looking screenshot sometimes.
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
This is my code, it does nothing if the UIView is hidden.
Take a snapshot of a hidden UIView -- Doesn't work
I've googled around and haven't found an answer. Please respond with code in Objective-C.

from your given link, the another view should ONLY cover your view and then set hidden to false/NO fro your view meaning your view should be visible behind the cover view. That's working perfectly. keep your view you want to draw at bottom in view hierarchy and the cover view covering your view.

Related

Screenshot the top most layer/view

I have a UIView which contains another UIView with an UIImage.
dView=[[drawView alloc]initWithFrame:myUIView.frame];
[dView newMaskWithColor:[UIColor colorWithPatternImage:chosenImage]];
[myUIView addSubview:dView];
And by using this code, I erased a part of it, and it looks like this now:
and now I added a layer behind this view, and presented another image in that layer.
[myUIView.layer insertSublayer:_videoPreviewLayer below:dView.layer];
and now it looks like this: (this is the screenshot manually taken on device)
When I try to screenshot the above view programmatically, the result is:
I dont why the newly added videopreview layer doesnt appeared in the screenshot.Here is my screenshot method.
-(void)takeSnapShot{
UIView *topView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject]; //tried this too
//capture the screenshot of the uiimageview and save it in camera roll
UIGraphicsBeginImageContext(self.myUIView.frame.size);
[self.myUIView.layer renderInContext:UIGraphicsGetCurrentContext()]; // tried this
[self.dView.layer renderInContext:UIGraphicsGetCurrentContext()]; //tried this
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; //tried this
[topView.layer renderInContext:UIGraphicsGetCurrentContext()]; //tried this
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
}
I am calling this method on a button click in my view controller.
I even tried capturing the window that is suggested from this answer, still I dont get the result I get from screenhotting manually.
Is there any way to capture the top most view that is shown to user ?
Check out this post: Why don't added sublayers show up in screenshot?
Seems that sublayers aren't handled by the renderInContext method.
When you want to capture a screenshot try storing a frame from the preview layer in a UIImageView then you should be able to manually put that frame underneath your mask and just screenshot the superview.

iOS : Cropping Image from Rotated ImageView

How to crop a rectangle(red square in screen shot) of UIImage which is rotated as well as zoomed using UIScrollView.
The edges of UIImageView are hidden because of rotation(UIImageView Transformation). Please help.
Well, you can do all the complicated core graphics things or do a simple UIView screenshot. I vote for the easy solution: What you have to do is create a new view with the frame same as where that small rect lies. Then add the whole image view to that small view converting its frame so it looks the same. Then take the screenshot of the small view. After you are done simply put the image view back the way it was and remove the small view.
As this is still easier said then done here is some code to chew on (I did NOT test this so please correct the bugs if any after you succeed).
- (UIImage *)getScreenshotInRect:(CGRect)frame {
UIImageView *theImageView; //your original image view
UIView *backupSuperView = theImageView.superview; //backup original superview
CGRect backupFrame = theImageView.frame; //backup original frame
UIView *frameView = [[UIView alloc] initWithFrame:frame]; //create new view where the image should be taken at
frameView.clipsToBounds = YES; //not really necessery but can be usefull for cases like using corner radius
[self addSubview:frameView];
theImageView.frame = [theImageView.superview convertRect:theImageView.frame toView:frameView]; //set the new frame for the image view
[frameView addSubview:theImageView];
UIImage *toReturn = [self imageFromView:frameView]; //get the screenshot
theImageView.frame = backupFrame; //reset the image view frame
[backupSuperView addSubview:theImageView]; //reset the image view's superview
[frameView removeFromSuperview];
frameView = nil;
return toReturn;
}
- (UIImage *)imageFromView:(UIView *)view {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, .0f);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
I do hope this doesn't break because you have rotations. If that is the case I suggest you create another view on which the rotated image view lies and add this view to the small view.

How to create a UIImage from whatever is in the background

I am applying blur to various sections of my app using the UIImage+ImageEffects.h sample code that was provided in one of the apps from the WWDC in 2013. It works well and I'm able to recreate the iOS7 effects for any UIImage.
However, I would like to recreate the effect of the UINavigationBar blurred transparency but using any view that I choose. Similar to the screenshot shown below.
For instance, say that I have a UITableView that takes up half of the screen. I also have a UIImageView background as a separate view behind it that occupies the entire screen. I would only like to blur the UIImageView background for just that section of the screen that's under the tableview.
Here's my question. How do I create create a UIImage by taking a "screenshot" of whatever is behind a UIView that is displayed? Is this even possible?
Here is my screen hierarchy. Nothing complex. I would like the "Blurred Image View" to contain a blurred image of the section of the "Image View" that is sitting as the main UIImageView in the hierarchy.
If you are deploing only on iOS7 you can use the new api, that are a lot faster than -renderInContext and use the ImageEffects category on that image taken from the view. Add this a a category on UIView
#interface UIView (RenderView)
- (UIImage *) imageByRenderingView;
- (UIImage *) imageByRenderingViewOpaque:(BOOL) yesOrNO;
#end
#implementation UIView (RenderView)
- (UIImage *) imageByRenderingViewOpaque:(BOOL) yesOrNO {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, yesOrNO, 0);
if ([self respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
}
else {
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
}
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
- (UIImage *) imageByRenderingView{
return [self imageByRenderingViewOpaque:NO];
}
This snippet is a UIView category ok also for system lower than iOS7. It takes an image on a view and its subviews.
Use the below piece of code for iOS < 7
#import <QuartzCore/QuartzCore.h>
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

Blurring a UIView that contains the keyboard with content beneath it (iOS 7)

I have a UIView with a UITableView the extends beneath the keyboard. The content in the table view is bright enough, making it clear that content sits behind the keyboard. I'm attempting to take a screenshot of the entire view in order to blur it using the following code:
- (UIImage *)screenshotFromView:(UIView *)view;
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
However, the image that is returned does not create a transparent keyboard. This presents an odd transition when going from the non-blurred view to the blurred view, since there is clearly content behind the keyboard before the transition to the blurred image.
Is it possible to take a screenshot of the entire screen, without use of private APIs, while still keeping the transparency of the keyboard + the status bar?
I got the exact problem as you these days, so I exactly know what you want. I wanted the whole UI blurred behind a message including the keyboard, which is not included with any regular screenshot method. My cure is the following code:
- (UIImage*)screenShotWithKeyboard:(UIView *)viewToShoot
{
UIWindow *keyboard = nil;
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if ([[window description] hasPrefix:#"<UITextEffectsWin"])
{
keyboard = window;
break;
}
}
// Define the dimensions of the screenshot you want to take (the entire screen in this case)
CGSize size = [[UIScreen mainScreen] bounds].size;
// Create the screenshot
UIGraphicsBeginImageContext(size);
CGContextRef context=UIGraphicsGetCurrentContext();
// delete following line if you only want the keyboard
[[viewToShoot layer] renderInContext:context];
if(keyboard!=nil)
[[keyboard layer] renderInContext:context];
UIImage *screenImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenImg;
}
I got the idea from an article of Aran Balkan I broke it down to one method and testet it for iOS 7 which seems to work for me. The article worth reading as he explain the tricks behind a little. As you only want the actual keyboard as image, you can comment out the line I marked in the code. With that image keyboard you can do your blur stuff yourself.
The code is far from perfect, but I think you got the idea.
Two thinks at the end:
I am a freshman to objective c and iOS development. If you find any problematic bugs, a comment is very welcome to improve this answer.
Second, I wrote this code today in my app and I do not know yet if I violate any developer rules for iOS. At the moment I do not see any problems, but I will investigate this further as I want to release my app with that graphic trick. I will keeping this post updated. Until than, as with point one, I would highly appreciate any comment regarding this issue.
Have you considered using UIKeyboardAppearanceDark? Currently the default value of keyboardAppearance corresponds to UIKeyboardAppearanceLight, so it may not be suited to your use case.

Render layer of UIView which is not in the View Hierarchy

What i want to achieve is to take an image of an UIView which has not been added as a subview, present and do stuff with the image and afterwards add the view to the view hierarchy.
I've searched and tried now for a while and believe, that it is simply not possible.
Obviously the problem is, that the view hasn't been drawn (called drawRect: i guess) if it hasn't been added as a subview.
Actually i thought renderInContext: would call drawRect/layer on its own.
It isn't even enough to add it as subview right before draw it to an imageContext because it won't be rendered immediately.
I take the screenshot with renderInContext: with the layer of the view, see my code here:
[self.view addSubView:view];
UIGraphicsBeginImageContextWithOptions(view.frame.size, YES, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);
[view.layer renderInContext:context];
UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
So my question is, has anybody managed to render a not visible UIView and if how?
Well this is awkward.
After a mail conversation with a very kind apple dev support, we reviewed my code and we noticed that i simply set the hidden property to YES. - Just don't do that.
So it is straight forward to make a screenshot of a view which is not in the view hierarchy.
It was total my fault why it didn't work.
Try to addd UIView to hierarchy but keep it hidden.
- (void)takeScreenSnapshot {
UIView *capturedView = self.view;
UIView *hiddenView = self.hiddeniew; // hidden view which is
// a part of capturedView
hiddenView.hidden = NO;
BOOL retina = [self isRetinaDisplay];
UIImage *image = [capturedView captureImageWithScale:(retina) ? 2.f : 1.f];
hiddenView.hidden = YES;
}

Resources