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
Related
In this application starting onwards Portrait mode.
.
code snippet
NSInteger heightOne;
NSInteger heightTwo;
NSInteger imgV;
CGRect Bounds = [[UIScreen mainScreen] bounds];
if (Bounds.size.height == 568) {
// code for 4-inch screen
heightOne = 480+38;
heightTwo = 240+38;//370
imgV = 360;
} else {
// code for 3.5-inch screen
heightOne = 480;
heightTwo = 240;//330
imgV = 310;
}
UIView *firstView = [[UIView alloc] initWithFrame:CGRectMake(00, 00,320,heightOne)];
firstView.opaque = NO;
firstView.tag = 1000;
firstView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f];
[self.view addSubview:firstView];
UIImageView *img = [[UIImageView alloc]initWithFrame:CGRectMake(250,imgV,50,50)];
img.image = [UIImage imageNamed:#"Zoom.jpg"];
[firstView addSubview:img];
UIView *secondView= [[UIView alloc] initWithFrame:CGRectMake(0,0,320,heightOne)];
[secondView setBackgroundColor:[UIColor clearColor]];
[firstView addSubview:secondView];
UIView *thirdView = [[UIView alloc] initWithFrame:CGRectMake(15,60,290,heightTwo)];//30
[thirdView setBackgroundColor:[UIColor whiteColor]];
thirdView.layer.cornerRadius = 2.0f;
thirdView.layer.borderWidth = 4.0f;
thirdView.layer.borderColor = [UIColor colorWithRed:0.0/255.0 green:100.0/255.0 blue:0.0/255.0 alpha:1.0].CGColor;
[secondView insertSubview:thirdView atIndex:0];
///////////////////////////// Creating custom close button ////////////////////////////////
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(287,48,30,30)];//24
[button setBackgroundImage:[UIImage imageNamed:#"Close-Gr.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(dismissOverViewController) forControlEvents:UIControlEventTouchUpInside];
button.backgroundColor = [UIColor clearColor];
[secondView insertSubview:button aboveSubview:thirdView];
secondView.frame = CGRectMake(0,0,320,480);
[UIView animateWithDuration:0.3
animations:^{
secondView.frame = CGRectMake(0,0,320,480);
}];
[thirdView setBackgroundColor:[UIColor grayColor]];
}
here i need only popup rotation .Any Ref link or suggestion ,it's really appreciated.
Return NO from
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
Handle device rotation via Local Notifications :-
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
And rotate the view as you want :-
self.theView.transform = CGAffineTransformIdentity;
self.theView.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
May this help you.
Please register for rotation notifications in viewdidlod
(void)viewDidLoad
{
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (currentOrientation == UIInterfaceOrientationLandscapeLeft || currentOrientation == UIInterfaceOrientationLandscapeRight)
[self willRotateToLandscape];
else
[self willRotateToPortrait];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willRotateToLandscape) name:#"Interface will rotate to landscape" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(willRotateToPortrait) name:#"Interface will rotate to portrait" object:nil];
}
//then adjust the popup view size in the following functions.
- (void)willRotateToLandscape
{
}
- (void)willRotateToPortrait
{
}
I am developing one app which is based on tabbarcontroller.In one view Controller i want to hidden the tabbarController instead of that i want to show toolbar for that purpose i wrote the following code
//tabBAr hidden
[self.tabBarController.tabBar setHidden:YES];
//creation of tool bar
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
tb = [[UIToolbar alloc] init];
//[tb setBackgroundImage:[UIImage imageNamed:#"tabbar.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
tb.tintColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
if ([[UIDevice currentDevice]userInterfaceIdiom]==UIUserInterfaceIdiomPhone)
{
tb.frame = CGRectMake(0, delegate.window.frame.size.height-50, 320, 44);
}
else
{
tb.frame = CGRectMake(0, delegate.window.frame.size.height-70, 768, 44);
}
[delegate.window addSubview:tb];
But problem is in iPad i want to change orientation of toolbar but it does not change it always takes portrait width and height.
Use notification to detect the device orientation like the following.
// Start Orientation //
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{
//NSLog(#"Vertical");
}
else if (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
//NSLog(#"Horizontal");
}
}
// End Orientation //
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
Somebody has kindly written this notification code somewhere. I didn't write it.
use viewWillLayoutSubViews method and add code to setFrame of toolbar in that method
ex:
- (void) viewWillLayoutSubviews
{
[toolBar setFrmae:CGRectMake(self.view.bounds.origin.x, self.view.bounds.size.height - 44, self.view.bounds.size.width, 44)];
}
iOS documentation says "The UIImagePickerController class supports portrait mode only". Any alternatives to this if I want to display the photo library in landscape mode?
may be this will help you out .You can use ALAssetsLibrary and asset class to get the pictures in your device and you can use them to display in landscape mode and in portrait mode same like uiimagepicker.
- (void)viewDidLoad
{
[super viewDidLoad];
[activity startAnimating];
appObj=(ImagePickerAppDelegate *)[[UIApplication sharedApplication]delegate];
void (^assetEnumerator)(struct ALAsset *, NSUInteger, BOOL *) = ^(ALAsset *result, NSUInteger index, BOOL *stop)
{
if(result != NULL)
{
//assets is a mutualable array...for storing the images that are in the device..
[assets addObject:result];
}
};
void (^assetGroupEnumerator)(struct ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
if(group != nil)
{
[group enumerateAssetsUsingBlock:assetEnumerator];
}
//meth is a user defined method..
[self meth];
[activity stopAnimating];
[activity setHidden:YES];
};
assets = [[NSMutableArray alloc] init];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library enumerateGroupsWithTypes:ALAssetsGroupAlbum usingBlock:assetGroupEnumerator
failureBlock: ^(NSError *error) { NSLog(#"Failure");}];
}
-(void)meth
{
NSLog(#"%i",[assets count]);
if(userOrientation==UIInterfaceOrientationPortrait || userOrientation==UIInterfaceOrientationPortraitUpsideDown)
{
NSLog(#"haii");
[scrollView removeFromSuperview];
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)];
scrollView.backgroundColor=[UIColor whiteColor];
NSLog(#"%i",[assets count]);
for (int i = 0; i < [assets count]; i++)
{
imgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[imgBtn setFrame:CGRectMake((i%4*80)+2,(i/4*80)+2,75,75)];
imgBtn.tag=i;
[imgBtn addTarget:self action:#selector(imageClicked:) forControlEvents:UIControlEventTouchUpInside];
ALAsset *asset=[assets objectAtIndex:i];
[imgBtn setImage:[UIImage imageWithCGImage:[asset thumbnail]] forState:UIControlStateNormal];
[scrollView addSubview:imgBtn];
}
scrollView.contentSize = CGSizeMake(320,(([assets count]/4)+1)*300 );
}
if(userOrientation==UIInterfaceOrientationLandscapeRight || userOrientation==UIInterfaceOrientationLandscapeLeft)
{
[scrollView removeFromSuperview];
scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 480,320)];
for (int i = 0; i < [assets count]; i++)
{
imgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[imgBtn setFrame:CGRectMake((i%6*80)+2,(i/6*80)+2,75,75)];
imgBtn.tag=i;
[imgBtn addTarget:self action:#selector(imageClicked:) forControlEvents:UIControlEventTouchUpInside];
ALAsset *asset=[assets objectAtIndex:i];
[imgBtn setImage:[UIImage imageWithCGImage:[asset thumbnail]] forState:UIControlStateNormal];
[scrollView addSubview:imgBtn];
}
scrollView.contentSize = CGSizeMake(480,(([assets count]/4)+1)*300);
}
[self.view addSubview:scrollView];
}
-(void)imageClicked:(UIButton *)sender
{
//for picking the images that the user has selected we are using other array "selectedImages" i.e declared in the app delegate
ALAsset *asset=[assets objectAtIndex:sender.tag];
[appObj.selectedImages addObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]]];
NSLog(#"%i",[appObj.selectedImages count]);
[self.navigationController popViewControllerAnimated:YES ];
}
I haven't checked whether this is illegal, but it worked for me. If you want the UIImagePickerController to start(and stay) in Landscape orientation code:
//Initialize picker
UIImagePickerController * picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
//set Device to Landscape. This will give you a warning. I ignored it.
//warning: 'UIDevice' may not respond to '-setOrientation:'
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
//Set Notifications so that when user rotates phone, the orientation is reset to landscape.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
//Refer to the method didRotate:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification" object:nil];
//Set the picker source as the camera
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
//Bring in the picker view
[self presentModalViewController:picker animated:YES];
The method didRotate:
- (void) didRotate:(NSNotification *)notification
{
//Maintain the camera in Landscape orientation
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(dragger.frame.origin.x, dragger.frame.origin.y,dragger.frame.size.width, dragger.frame.size.height)] ;
imgView.image = dragger.image;
overlayView = [[UIView alloc] initWithFrame:CGRectMake(dragger.frame.origin.x,dragger.frame.origin.y,dragger.frame.size.width, dragger.frame.size.height)];
[overlayView addSubview:imgView];
//open the camera
self.picker = [[UIImagePickerController alloc] init];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.picker.cameraOverlayView=overlayView;
[self.navigationController presentModalViewController:self.picker animated:YES];
This works fine in portrait mode but the overlay image does not change while in the landscape mode.
How can i achieve this as I need help on this?
you need to register for change in orientation... like this
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
and then write this function in the same class....
- (void) orientationChanged:(NSNotification *)notification{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
//do stuff
if (orientation==UIDeviceOrientationPortrait) {
imagePickerController.cameraOverlayView = portraitImageView;
}
else if(orientation==UIDeviceOrientationLandscapeLeft)
{
imagePickerController.cameraOverlayView = landscapeImageView;
}
}
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