UIImagePickerController using addSubView leaves white margin at the top of view - iphone

I need to add UIImagePickerController in camera mode using addSubView. I have written code for it but it leaves white space at the top of the view.
-(void)viewDidAppear:(BOOL)animated{
NSLog(#"ViewDidAppear");
OverlayView *overlay = [[OverlayView alloc]
initWithFrame:CGRectMake(0,0,SCREEN_WIDTH,SCREEN_HEIGTH)];
//create a new image picker instance
picker = [[UIImagePickerController alloc]init];
self.picker.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
//set source to video!
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//hide all controls
picker.showsCameraControls = NO;
picker.navigationBarHidden = NO;
picker.toolbarHidden = YES;
picker.editing = NO;
//make the video preview full size
picker.wantsFullScreenLayout = YES;
slider.value = 1;
picker.cameraViewTransform = CGAffineTransformScale(picker.cameraViewTransform,slider.value, slider.value);
//set our custom overlay view
picker.cameraOverlayView = overlay;
[picker.view addSubview:slider];
//show picker
[picker.view addSubview:capture];
[picker.view addSubview:library];
//[picker.view addSubview:multicapture];
[capture addTarget:self action:#selector(takepicture) forControlEvents:UIControlEventTouchUpInside];
[library addTarget:self action:#selector(goToLibrary) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:picker.view];
[picker viewWillAppear:YES];
[picker viewDidAppear:YES];
}else{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Test Text" message:#"Camera is Not Availble" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
[overlay release];
}
Can anyone please help me.
Thanks.

As kante0 says, that white margin is the status bar disappeared. If you want to show the status bar, use kante0's solution:
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
[self.view addSubview:picker.view];
If you don't want to show the status bar (typically when you show the camera preview), use this piece of code:
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
[self.view setFrame: [[UIScreen mainScreen] bounds]];
// Place your overlay view here
[self.view addSubview:picker.view];
But you have to remember that when the pickerview is removed, if you want to show again the status bar, you'll need to do this:
[picker.view removeFromSuperview];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[self.view setFrame: [[UIScreen mainScreen] applicationFrame]];
// If you need to place elements programmatically, do it here

Look into NSScreen for getting accurate dimensions. Double check that you have the height value correct. For example, you could do this:
int width = [[NSScreen mainScreen] frame].size.width;
int height = [[NSScreen mainScreen] frame].size.height;

Is not a white margin, is status bar disappearing.
I solved the problem with:
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];

Related

Viewing Activity Indicator in fullscreen

I am trying to display an activity indicator in full screen so the user cannot press any button in the screen till the activity indicator is turned off as the alert view process. I have called the [activityView startAnimating] but I can push the buttons in the back. Is there way to prevent that?
Thanks from now.
You can use MBProgressHUD for such loading indictators. It's a great MIT-licensed class that extends well if you want to customize it further.
you can try this
UIAlertView *alert= [[[UIAlertView alloc] initWithTitle:#"Loading\nPlease Wait..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] autorelease];
[alert show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.center = CGPointMake(150, 100);
[indicator startAnimating];
[alert addSubview:indicator];
[indicator release];
and add this line where you want remove your alert
[alert dismissWithClickedButtonIndex:0 animated:YES];
I'll suggest a best way will be displaying an alertView with activity indicator on the screen.
You can use the following code for this:
declare property for UIAlertView like:
#property (nonatomic, strong) UIAlertView *sendAlert;
self.sendAlert = [[UIAlertView alloc] initWithTitle:#"Loading" message:#"" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
UIActivityIndicatorView *act = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
act setFrame:CGRectMake(115, 60, 50, 50)];
[act startAnimating];
[sendAlert addSubview:act];
act = nil;
[sendAlert show];
When you want to remove alert you can use:
[sendAlert dismissWithClickedButtonIndex:0 animated:YES];
sendAlert = nil;
Another alternative, you can add the activity indicator to your view itself and set the userInteraction of backbutton to false. When you finish the task set to True. But It won't be a nice way.
hey for your this requirement use the bellow code which you can access in your every view use..
add this bellow code and object in AppDelegate.h file like bellow..
UIView *activityView;
UIView *loadingView;
UILabel *lblLoad;
and paste this bellow code in AppDelegate.m file
#pragma mark - Loading View
-(void) showLoadingView {
//NSLog(#"show loading view called");
if (loadingView == nil)
{
loadingView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 60.0, 320.0, 420.0)];
loadingView.opaque = NO;
loadingView.backgroundColor = [UIColor darkGrayColor];
loadingView.alpha = 0.5;
UIView *subloadview=[[UIView alloc] initWithFrame:CGRectMake(84.0, 190.0,150.0 ,50.0)];
subloadview.backgroundColor=[UIColor blackColor];
subloadview.opaque=NO;
subloadview.alpha=0.8;
subloadview.layer.masksToBounds = YES;
subloadview.layer.cornerRadius = 6.0;
lblLoad=[[UILabel alloc]initWithFrame:CGRectMake(50.0, 7.0,80.0, 33.0)];
lblLoad.text=#"LoadingView";
lblLoad.backgroundColor=[UIColor clearColor];
lblLoad.textColor=[UIColor whiteColor];
[subloadview addSubview:lblLoad];
UIActivityIndicatorView *spinningWheel = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(10.0, 11.0, 25.0, 25.0)];
[spinningWheel startAnimating];
spinningWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
[subloadview addSubview:spinningWheel];
[loadingView addSubview:subloadview];
[spinningWheel release];
}
[self.window addSubview:loadingView];
//[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];
}
-(void) hideLoadingView {
if (loadingView) {
[loadingView removeFromSuperview];
[loadingView release];
loadingView = nil;
}
}
and call this method when you want in any class , just like bellow..
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate showLoadingView];
Add a UIView above your current view when activity indicator starts :
UIView *overlayView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[self.navigationController.view addSubview:overlayView];

How to add an Subview to a Fullscreen MPMoviePlayer

I want to add a Logo (UIImageView) to a fullscreen MPMoviePlayerController.
It works fine when the MPMoviePlayerController is not in fullscreen Mode. When i switch to full screen all added views on the MPMoviePlayerController removed(hidden).
Here is my code:
- (void)setupMPMoviePlayer{
[self.moviePlayer.view removeFromSuperview];
[self removeNotifications];
self.moviePlayer = nil;
self.moviePlayer = [[MPMoviePlayerController alloc] init];
[self addNotifications];
[self.moviePlayer.view setFrame:self.view.bounds];
self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.moviePlayer.fullscreen = NO;
[self.view addSubview:self.moviePlayer.view];
if ([self.moviePlayer respondsToSelector:#selector(setAllowsAirPlay:)])
[self.moviePlayer setAllowsAirPlay:YES];
[self.moviePlayer setContentURL:[NSURL URLWithString:urlString]];
[self.moviePlayer setFullscreen:YES animated:YES];
[self addLogoViewAtView:self.moviePlayer.view];
}
- (void)addLogoViewAtView:(UIView *)view{
UIView *theView = [view viewWithTag:101];
if (theView.superview) {
[theView removeFromSuperview];
}
UIImageView *logoView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"logo_weiss.png"]];
logoView.tag = 101;
logoView.frame = CGRectMake( logoView.image.size.width - 100.0,
100.0,
logoView.image.size.width,
logoView.image.size.height);
logoView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin;
[view addSubview:logoView];
[view bringSubviewToFront:logoView];
}
Now my question is there an alternate way to add an subview to MPMoviePlayerController?
I can add the logo to the application's window but this ist not so clean.
Anyone have any idea on how I could do this?
Most propably fullscreen mode add MPMoviePlayerController view at keyWindow for an application or present a modal view controller above. So, you can try looking for the view in window.subviews or modal view controllers for moviePlayer.

UIView cameraOverlayView in Augmented Reality starts in portrait mode

I'm doing a bit of AR work here and one of the biggest problem right now is one of my UIView will not respond to any frame settings I make to it.
The code is very similar to this. I've made a few major changes to incorporate into my project:
nurse.site11.com/JaredCrawford-iWVU-632a9a0/Libraries/ARKit/AugmentedRealityController.m
"displayView" is used as a custom UIView that is passed to UIImagePickerController's setCameraOverlayView: method.
Now in the initWithViewController method of that AugmentedRealityController.m file, I have tried setting the displayView = [[UIView alloc] initWithFrame:CGRectMakeFrame(0, 0, 480, 320)];
The problem is, even if I set it to displayView = [[UIView alloc] initWithFrame:CGRectMakeFrame(0, 0, 100, 100)]; the view still remains full screen 320 x 480 BUT only for the first time the Augmented Reality view appeared. Subsequent times that the AR view appears, the code works.
I am not sure what the heck is going on and why setting the frame of the displayView not affecting the view at all FOR THE FIRST TIME it is shown.
I'm hoping someone else has experienced this problem before and possibly solved it.
This is my code:
- (id)initWithViewController:(UIViewController *)vc
{
coordinates = [[NSMutableArray alloc] init];
coordinateViews = [[NSMutableArray alloc] init];
latestHeading = -1.0f;
debugView = nil;
[self setRootViewController: vc];
[self setDebugMode:NO];
[self setMaximumScaleDistance: 0.0];
[self setMinimumScaleFactor: 1.0];
[self setScaleViewsBasedOnDistance: YES];
[self setRotateViewsBasedOnPerspective: YES];
[self setMaximumRotationAngle: M_PI / 6.0];
//CGRect screenRect = [[UIScreen mainScreen] bounds];
NSLog(#"inside initWithViewController");
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIDeviceOrientationPortrait)
{
NSLog(#"Orientation portrait");
}
else if(orientation == UIDeviceOrientationLandscapeRight)
{
NSLog(#"orientation right");
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
[self setCurrentOrientation:UIDeviceOrientationLandscapeRight];
}
else if(orientation == UIDeviceOrientationPortraitUpsideDown)
{
NSLog(#"orientation upsidedown");
}
else if(orientation == UIDeviceOrientationLandscapeLeft){
NSLog(#"orientation left");
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
[self setCurrentOrientation:UIDeviceOrientationLandscapeLeft];
}
//[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];
//NSLog(#"In AR view, device orientation = %#", [[UIDevice currentDevice] orientation]);
//[self setDisplayView: [[UIView alloc] initWithFrame: screenRect]];
//[self setCurrentOrientation:UIDeviceOrientationLandscapeRight];
displayView = [[UIView alloc] initWithFrame:CGRectMake(-80, 80, 480, 320)];
[displayView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5]];
NSLog(#"displayView x = %f", displayView.frame.origin.x);
NSLog(#"displayView y = %f", displayView.frame.origin.y);
NSLog(#"displayView width = %f", displayView.frame.size.width);
NSLog(#"displayView height = %f", displayView.frame.size.height);
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:) name: UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[self rootViewController] setView:displayView];
//[[self rootViewController] setView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 480, 320)]];
//[[rootViewController view] setBackgroundColor:[UIColor blueColor]];
CLLocation *newCenter = [[CLLocation alloc] initWithLatitude:37.41711 longitude:-122.02528];
[self setCenterLocation: newCenter];
[newCenter release];
[self startListening];
[self deviceOrientationUpdate];
startLocation = nil;
i = 0;
objImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
//[objImageView setBackgroundColor:[UIColor blueColor]];
blnHasRotated = NO;
return self;
}
The full code can be seen here: pastebin.com/g0eXJaPq

UIPopoverController presented from a UIButton does not hide?

I have a UIPopoverController that is presented from a button on my UIViewController but when I tap on any part of the view that is not the popover it is not hiding?
The buttons that present this popover are created dynamically, you'll see that referenced in the code below:
-(IBAction)showModifiers:(id)sender{
[self.popoverController dismissPopoverAnimated:YES];
UIView *theSuperview = self.view;
CGPoint touchPointInSuperview = [sender locationInView:theSuperview];
UIView *touchedView = [theSuperview hitTest:touchPointInSuperview withEvent:nil];
currentPopoverTag = [touchedView tag];
NSLog(#"Show Modifiers %i %i", [touchedView tag], currentPopoverTag);
RepZioCoreDataAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
if (appDelegate.popoverController)
[appDelegate.popoverController dismissPopoverAnimated:YES];
self.modifierListPopoverViewController = nil;
ModifierListCollection *collection = [self.modifierLists objectAtIndex:[touchedView tag]-100];
ModifierList *modifierList = [self getModifierList:collection.ModifierListID];
self.modifierListPopoverViewController =
[[[ModifierListPopoverViewController alloc] initWithModifierList:modifierList withManufacturerID: self.manufacturerID] autorelease];
self.modifierListPopoverViewController.delegate = self;
self.popoverController = [[[UIPopoverController alloc] initWithContentViewController:modifierListPopoverViewController] autorelease];
[self.popoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
I realize it's unlikely, but does your ModifierListPopoverViewController class set its modalInPopover property to YES? (the default is NO, which should give you the behavior you're looking for).
It seems that some view tackles the touch event.

View controller not getting -shouldAutorotateToInterfaceOrientation: messages on second load?

I have a UIViewController that I'm using to control a "pop-up" view for viewing images throughout my application. It supports autorotation, as it automatically sizes the image to fit properly regardless of orientation. This works perfectly, but only the first time I initialize and display the view controller. When it closes, I am removing the UIView from my view hierarchy and releasing the view controller - but the next time I instantiate and add it to my view hierarchy, it stops receiving the -shouldAutorotateToInterfaceOrientation messages when the phone is rotated.
This is how I instantiate and display it:
popupVC = [[PopupVC alloc] init];
[popupVC viewWillAppear:NO];
[[[UIApplication sharedApplication] keyWindow] addSubview:popupVC.view];
[popupVC viewDidAppear:NO];
this is how I remove/release it when it's finished:
[popupVC viewWillDisappear:NO];
[popupVC.view removeFromSuperview];
[popupVC viewDidDisappear:NO];
[popupVC release];
popupVC = nil;
I've tried looping through [[UIApplication sharedApplication] keyWindow] subviews to see if somehow my popup view isn't on top, but it always is. And it has a different address each time so I do know that it's a different instance of the view controller class.
As requested, here is the complete loadView method from PopupVC:
- (void)loadView {
UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
myView.backgroundColor = self.overlayColor;
myView.autoresizesSubviews = NO;
myView.hidden = YES;
myView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.view = myView;
[myView release];
_isVisible = NO;
UIView *myMaskView = [[UIView alloc] initWithFrame:self.view.bounds];
myMaskView.backgroundColor = [UIColor clearColor];
myMaskView.clipsToBounds = YES;
myMaskView.hidden = YES;
myMaskView.autoresizesSubviews = NO;
myMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:myMaskView];
self.imageMaskView = myMaskView;
[myMaskView release];
UIImageView *myImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
myImageView.center = self.view.center;
myImageView.hidden = NO;
myImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
[self.imageMaskView addSubview:myImageView];
self.imageView = myImageView;
[myImageView release];
UIButton *myImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
myImageButton.frame = self.view.frame;
myImageButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
[myImageButton addTarget:self action:#selector(clickImage:) forControlEvents:UIControlEventTouchUpInside];
[self.imageMaskView addSubview:myImageButton];
self.imageButton = myImageButton;
UIActivityIndicatorView *myActivityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
myActivityView.hidden = YES;
[self.view addSubview:myActivityView];
myActivityView.center = self.view.center;
self.activityView = myActivityView;
[myActivityView release];
}
The shouldAutorotateToInterfaceOrientation handler isn't the place for custom code to respond to rotation events. It's purpose is just to tell the OS that your view controller can rotate. If you want to have custom code to handle the rotation events you should overide - didRotateFromInterfaceOrientation or one of the other similar callback methods depending on your needs:
willRotateToInterfaceOrientation:duration:
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
didAnimateFirstHalfOfRotationToInterfaceOrientation:
willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
See Autorotating Views in the developer docs.
I think that might be a bug in the new OS 3.0. A workaround to this would be to use NSNotificationCenter after turning on beginGeneratingDeviceOrientationNotifications.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void) receivedRotate: (NSNotification *) notification {
DebugLog(#"ORIENTATION CHANGE");
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if(interfaceOrientation == UIDeviceOrientationPortrait) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
self.view.bounds = CGRectMake(0, 0, 320, 480);
}
else if(interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0, 0, 480, 320);
}
else if(interfaceOrientation == UIDeviceOrientationLandscapeRight) {
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
self.view.bounds = CGRectMake(0, 0, 480, 320);
}
}
My problem is that I get the rotation event for my rootViewController, but as soon as I launch my second viewController, it won't get any signals except motion (shaking) and touch. Is that the same issue as the original post -- it is certainly similiar??
I followed-up with above recommendation and I don't have the selector coded correctly so it throws an exception as soon as I try to rotate. Meanwhile, I found this other discussion on the web which confirms that the problem was introduced in 3.0.
link text