Camera Shutter shows up in front of custom UIView? - objective-c

I have a custom UIView that I have created to display my custom buttons and toolBar. When I first called for it to show, the bar is on top of the Shutter (which is good). But after the camera is loaded, the shutter comes in front of it, then opens.
If you look at the native camera.app, it doesn't do this. The toolbar stays there the whole time. Here is my code:
// .h
UIImagePickerController *theCamera;
#property (nonatomic, retain) UIImagePickerController *theCamera;
// .m
theCamera = [[UIImagePickerController alloc] init];
theCamera.delegate = self;
theCamera.sourceType = UIImagePickerControllerSourceTypeCamera;
theCamera.showsCameraControls = NO;
theCamera.toolbar.alpha = 0;
theCamera.navigationBarHidden = YES;
theCamera.toolbarHidden = YES;
theCamera.wantsFullScreenLayout = YES;
theCamera.cameraViewTransform = CGAffineTransformMakeScale(1.25, 1.25);
UIImageView *tabBarBack = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"tab_bar_back.png"]];
tabBarBack.frame = CGRectMake(0, 422, 320, 58);
[customView addSubview:tabBarBack];
theCamera.cameraOverlayView = customView;
[self presentModalViewController:theCamera animated:YES];
Obviously there are more buttons I add to the customView, but you get the concept.

Subscribe to:
AVCaptureSessionDidStartRunningNotification
This is when the iris open animation begins. If you add a cameraOverlayView during this time, it will be properly covered up by the iris. It is posted at the same time as that PL… private notification. This is a documented approach that does not risk app rejection.

AFAIK there is no direct way to do this. If you use cameraOverlay, you will get shutter for the complete screen.
How ever there are some alternate methods (playing around with the view hierarchy) that will help you in making your preview screen as parent view. I am not sure if this approach is correct as per app store guidelines.
have a look at Hide/Show iPhone Camera Iris/Shutter animation for better understanding on how to achieve this.

On iOS 6+, if you've added your controller as the delegate for the UIImagePickerController, this code should ensure that the shutter stays behind your cameraOverlayView:
- (void) navigationController:(UINavigationController*) navigationController willShowViewController:(UIViewController*) viewController animated:(BOOL) animated {
self.imagePickerController.cameraOverlayView = ...; // your camera overlay view
}
I haven't tested on versions of iOS prior to iOS 6 though.

Related

How to resize Window to dimension in VIew Controller for a OSX app?

I'm fairly new to Mac OSX Apps, but I'm trying to build an app with no status bar, and the dimensions are smaller. So what I did in my AppDelegate.m is:
-(void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.mainViewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
[self.window.contentView addSubview:self.mainViewController.view];
[self.window setOpaque:NO];
[self.window setStyleMask:NSBorderlessWindowMask];
[self.window setBackgroundColor:[NSColor clearColor]];
self.mainViewController.view.frame = ((NSView*)self.window.contentView).bounds;
}
Now, what I really want to do, is to get my window to look like, what I've built in my interface builder (can't post pictures yet). I've tried shutting off all the autosizing elements but when I run the simulator I get a clipped version of my interface (the size changes every run). It seem like the frame size is getting miscalculated, but I've done everything from the interface builder. I can programmatically set the shapes of the view, but is there a way to shut off all resizing and simply portray the xib file as what I see in the interface builder?
There are two ways you could approach this problem.
You add an AutoresizingMask to your ViewController:
[self.mainViewController setAutoresizingMask:NSViewAutoresizingFlexibleWidth|NSViewAutoresizingFlexibleHeigt];
You disable window resizing in the Interface builder like by setting its minimum and maximum size. This can also be done in code.
Edit: Thanks to trojanfoe for pointing out that you can also uncheck Resize in the Attributes Inspector.
You can easily resize your window programatically. Here's how:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
NSRect frame;
frame.size.height = 200;
frame.size.width = 200;
[window setFrame:frame display:YES animate:YES];
}

Custom UIProgressView in iOS7 not possible?

I know this was already asked about a hundred times here, but I couldn´t find a suitable answer in the other questions.
My problem is the height of my UIProgressView. While everything worked as expected in iOS6, now in iOS7 nothing goes right.
I tried the following:
1.Setting the custom layout in the drawRect-Method:
Works like a charm in iOS6, but in iOS7 the progress is set to 100% from the beginning or the bar is very thin.
2.Setting the layout with the progressImage and trackImage property of the UIProgressView appearance
Also not working under iOS7. Here the bar progress is set to 100% from the beginning, too. Some people write that it should be possible this way, but I can not confirm that for iOS7.
3.Using initWithProgressStyle for initialization and then setting the frame of the progress view
Not working for me under iOS6 and iOS7. In iOS7 the bars are just very slim.
For me right now it is pretty frustrating because the bars are either at 100% or they are mega-slim. Can anyone give me a suggestion to reach the old layout of my progress views. I think it has to be possible because if I look at my Spotify app on the iPhone (iOS7 installed), the progress view looks like before.
Thank you very much!
Well, the problem is seams that iOS6 UIProgressView and iOS7 UIProgressView have different internal subviews structure. iOS6 progress view is a single view without child view (or some minor view), iOS7 progress view have few additional subview for drawing progress bar and background.
If you remove all subview of UIProgressView on iOS7 than you drawRect: method will work the same as before on iOS6, but you will be totally responsible about drawing your progress view content including progress bar and background.
- (id) initWithCoder: (NSCoder*)aDecoder
{
if(self=[super initWithCoder: aDecoder])
{
// Also you can setup height of your progress here
// self.frame = CGRectMake(0,0,100,yourHeight);
NSArray *subViews = self.subviews;
for(UIView *view in subViews)
{
[view removeFromSuperview];
}
}
return self;
}
I made kind of a workaround for this problem. I hope somebody can give a nice answer for a normal UIProgressView though.
I wrote a UIView subclass with round corners and a view inside of it which changes its size depending on the given progress. I only use colors for the background, but images would be possible too. Here´s the code:
#import "CustomProgressView.h"
#import <QuartzCore/QuartzCore.h>
#interface CustomProgressView ()
#property (nonatomic, retain) UIView *progressView;
#end
#implementation CustomProgressView
#synthesize progressColor,trackColor,progressView,progress;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.layer.cornerRadius = 5;
// clipsToBounds is important to stop the progressView from covering the original view and its round corners
self.clipsToBounds = YES;
self.progressView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, frame.size.height)];
[self addSubview:self.progressView];
}
return self;
}
-(void)setProgressColor:(UIColor *)theProgressColor {
self.progressView.backgroundColor = theProgressColor;
progressColor = theProgressColor;
}
-(void)setTrackColor:(UIColor *)theTrackColor {
self.backgroundColor = theTrackColor;
trackColor = theTrackColor;
}
-(void)setProgress:(float)theProgress {
progress = theProgress;
CGRect theFrame = self.progressView.frame;
theFrame.size.width = self.frame.size.width * theProgress;
self.progressView.frame = theFrame;
}
#end
I had a custom UIProgressView with it's own drawRect being updated from a background process.
In iOS6 all was working while in iOS7 the progressbar just did not update.
I have added layoutSublayersOfLayer right after the setProgress like this
[self.loadingProgress setProgress:pv.floatValue];
[self.loadingProgress layoutSublayersOfLayer:self.loadingProgress.layer];
and it worked like a charm.
I hope this helps someone.
Avoid a headache and use this excellent library:
YLProgressBar
Copy YLProgressBar.h and YLProgressBar.m from the YLProgressBar folder.
#import "YLProgressBar.h" in the file(s) you want to use the progress bar
Add your progress bar either by code or by xib
progressBar.type = YLProgressBarTypeRounded;
progressBar.progressTintColor = [UIColor greenColor];
progressBar.stripesOrientation = YLProgressBarStripesOrientationVertical;
progressBar.stripesDirection = YLProgressBarStripesDirectionLeft;
You have a nice, fully functional progress bar that supports width, height, modifications.

Prevent shutter animation from appearing full screen when using cameraOverlayView [duplicate]

I have a transparent view with a rectangle drawn onto it using CoreGraphics.
When the camera launches the custom overlay view is above the shutter animation.
What you see is the standard camera shutter with the custom rectangle above it.
How do I get it to go in the right place, underneath the shutter animation? I've looked at other sample code but it's for OS 3.1 and doesn't seem to do anything differently.
Here's my code:
-(IBAction)cameraButton{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerCameraDeviceRear]){
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Add the OverlayView with the custom Rectangle
CGRect overlayFrame = CGRectMake(0.0f, 0.0f, 320.0f, 480.0f);
OverlayView *overlayView = [[OverlayView alloc]initWithFrame:overlayFrame];
picker.cameraOverlayView = overlayView;
[overlayView release];
[self presentModalViewController:picker animated:YES];
[picker release];
}
}
On the iPad this problem doesn't exist, and the overlay view is behind the shutter animation by default. But on the iPhone, the overlay appears at front.
I've found a solution that worked for me.
You have to set your overlay view as a subview in this method:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (!viewController)
return;
UIView* controllerViewHolder = viewController.view;
UIView* controllerCameraView = [[controllerViewHolder subviews] objectAtIndex:0];
UIView* controllerPreview = [[controllerCameraView subviews] objectAtIndex:0];
[controllerCameraView insertSubview:self.overlayView aboveSubview:controllerPreview];
}
Hope it helps
Original source:
http://www.alexcurylo.com/blog/2009/06/18/uiimagepickercontroller-in-3-0/
You may not do anything else other than what you're already doing; if iOS decides to put your overlay view over the shutter, you'll just have to live with it (unless you want to risk getting rejected from the app store).
As an imperfect workaround, you could start your overlay with alpha=0 and then set alpha to 1 a second or two later. But there is no set time period that the shutter appears for before 'opening' (I think it depends on how long it takes to initialize the camera hardware), so sometimes your interface might not appear until late and sometimes might appear too early.
As of 4.3.3, the shutter animation is broken because elements are displayed on top, and then snap underneath when the animation starts. I've filed this as a Radar: http://openradar.appspot.com/radar?id=1204401
I answered a similar question here. What worked for me (in iOS 6) was setting the cameraOverlayView in navigationController:willShowViewController:animated.
- (void) navigationController:(UINavigationController*) navigationController willShowViewController:(UIViewController*) viewController animated:(BOOL) animated {
self.imagePickerController.cameraOverlayView = ...; // your camera overlay view
}

UIScrollView adding UIViewController as a sub view? with UIPageControl

I am currently working on my application and would like to have a UIScrollView and UIPageControl which would allow the user to swipe the screen left and right to get to different view controllers.
I have this working so far, so that I can swipe left and right to see either view controller however I am finding that when one of my UIViewControllers needs to access it delegate nothing happens, for example UITableViewDelegate.
This is the code i have so far in my scrollViewController
CGRect frame2;
frame2.origin.x = self.scrollView.frame.size.width * 1;
frame2.origin.y =30;
frame2.size = self.scrollView.frame.size;
myViewController *vc3 = [[myViewController alloc] initWithNibName:#"myViewController" bundle:nil];
vc3.view.frame = frame2;
[self.scrollView addSubview:vc3.view];
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 2, self.scrollView.frame.size.height);
One thing I am not able to do also is release [vc3 release]; after adding it to the scrollView the app will just crash.
Any help would be great, also please let me know if I am going about this the wrong way.
Thanks Aaron
By adding v3.view , v3's retain count wont increase. So you cant release v3. you can
[v3.view release];

UISplitViewController: remove divider line

When using UISplitViewController on the iPad there's a black vertical divider line between the root and detail view. Is there any way to remove this line?
Thanks
Excellent answer by #bteapot. I tested this and it works, even gets rid of the line between master/detail nav bars.
You can do this in storyboard by adding the "gutterWidth" key path and the value 0 to the USplitViewController runtime attributes.
Actuly I have some modification to answer of (Dylan)'s answer
in the appDelegate we need to add image in spliteview controller rather then window
self.splitViewController.view.opaque = NO;
imgView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"FullNavBar.png"]];
[imgView setFrame:CGRectMake(0, 0, 1024, 44)];
[[self.splitViewController view] insertSubview:imgView atIndex:0];
[[self.splitViewController view] setBackgroundColor:[UIColor clearColor]];
here self is object of AppDelegate.
now Apply the answer of this thread : iPhoneOS SDK - Remove Corner Rounding from views (iPad problem) answer by (abs)
edit in above post's answer is
-(void) fixRoundedSplitViewCorner {
[self explode:[[UIApplication sharedApplication] keyWindow] level:0];
}
-(void) explode:(id)aView level:(int)level
{
if ([aView isKindOfClass:[UIImageView class]]) {
UIImageView* roundedCornerImage = (UIImageView*)aView;
roundedCornerImage.hidden = YES;
}
if (level < 2) {
for (UIView *subview in [aView subviews]) {
[self explode:subview level:(level + 1)];
}
}
imgView.hidden = FALSE;
}
** make imgView.hidden to FALSE
declare imgView to the AppDelegate.h file**
and dont forget to call this
-(void)didRotateFromInterfaceOrientation:
UIInterfaceOrientation)fromInterfaceOrientation
{
[yourAppDelegate performSelector:#selector(fixRoundedSplitViewCorner)
withObject:NULL afterDelay:0];
}
chintan adatiya answer covers only the corners and the navigation bar, but I found an trick how to cover the line between the Master and the Detail view.
It is not nice but it works like a charm.
First create an image which is 1 px wide and 704 pixels high.
In the didFinishLaunchingWithOptions add the following code:
UIView *coverView = [[UIView alloc] initWithFrame:CGRectMake(320, 44, 1, 704)];
[coverView setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"divider_cover.png"]]];
[splitViewController.view addSubview:coverView];
And done.
When you want a background image which is continues create 3 images:
Master: width: 320, height: 704
Detail: width: 703, height: 704
Divider:width: 1, height: 704
First post here, hi everyone.
I discovered how to do it accidentally... when I tried to find why I had LOST the divider line. Here's how to hide it, if you're still interested:
1) In your Detail (right-side) view, make sure you have a subview that spans the whole view.
2) Offset this subview view to (-1, 0).
3) Make sure that the Detail View has its "Clip Subviews" option unchecked.
Voilà, enjoy.
You can mostly get rid of it by setting another image behind it in the main window's views. This is from the app delegate didFinishLaunchingWithOptions
// Add the split view controller's view to the window and display.
splitViewController.view.opaque = NO;
splitViewController.view.backgroundColor = [UIColor clearColor];
[window addSubview:splitViewController.view];
[window insertSubview:bgImageView belowSubview:splitViewController.view];
[window makeKeyAndVisible];
But it still leaves two visual artifacts at the top and the bottom that appear to be custom drawn by the splitviewcontroller.
Interestingly, In the app that I'm working on I want a black background color for both views in the UISplitViewController. I'd like to change the color of the divider line to white (so that you can see it). Making both background colors black is one way to get rid of (make invisible) the dividing line but that's probably not a solution for most people.
Tested on iOS10 (probably will work on iOS9 too).
splitviewController.view.backgroundColor = UIColor.white
it removes divider. Apparently divider is just a gap between master and detail container.
I looked around for a while, and came to the conclusion that theres no way to do this, other than to create your own custom split view.
Try the MGSplitViewController by Matt Gammell
http://mattgemmell.com/2010/07/31/mgsplitviewcontroller-for-ipad
I may be late here, but I DO have a solution that works. It even works for the iOS 8+ splitViewController.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible; and seamlessly slides in and out when you press the Full Screen toggle button.
Here is the trick :
first Subclass UISplitViewController.m
In the header add the follwing :
#property (strong, nonatomic) UIView *fakeNavBarBGView;
In the viewDidLoad method add the following code :
CGFloat fakeNavBarWidth = 321; // It is important to have it span the width of the master view + 1 because it will not move when the split view slides it's subviews (master and detail)
CGFloat navbarHeight = self.navigationController.navigationBar.frame.size.height + 20;
self.fakeNavBarBGView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, fakeNavBarWidth, navbarHeight)];
self.fakeNavBarBGView.backgroundColor = [UIColor redColor];
// Add Fake navbar to back of view
[self.view insertSubview:self.fakeNavBarBGView atIndex:0];
// SplitView Controller
UISplitViewController *splitViewController = self;
DetailViewController *detailVC = [navigationController.viewControllers lastObject];
detailVC.fakeNavBarSubView = self.fakeNavBarBGView;
detailVC.SVView = self.view;
In the DetailViewController.h add the following :
#property (strong, nonatomic) UIView *SVView;
#property (strong, nonatomic) UIView *fakeNavBarSubView;
Now here is the final trick : in the DetailViewController.m, add the following in the viewDidLoad method (called every time you click the Master table) :
[self.SVView sendSubviewToBack:self.fakeNavBarSubView];
[self.SVView bringSubviewToFront:self.view];
Run it and watch the magic ;-)
Private API (can cause App Store rejection):
[splitViewController setValue:#0.0 forKey:#"gutterWidth"];
I did this accidentally by setting the backgroundColor property of the first viewController's view - possibly to clearColor, I don't remember now.
UIManager.put("SplitPaneDivider.draggingColor", new Color(255, 255, 255, 0));