UIDatePicker at bottom of a modal, in iOS5 & iOS6 - objective-c

In my app, I show to my users a modal with an UIDatePicker at the bottom so they can select a date. My modal has to work in portrait and in landscape. Also, my DAtePicker has to be smaller in landscape than in portrait, or it takes nearly all the screen. I'm using the following code when the screen is rotating.
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
datePicker.frame = CGRectMake(datePicker.frame.origin.x, myView.frame.size.width - 216.0, datePicker.frame.size.width, 216);
}
else {
datePicker.frame = CGRectMake(datePicker.frame.origin.x, myView.frame.size.height - 160.0, datePicker.frame.size.width, 160);
}
It does work great on iOS6 : the DatePicker is always where I want it to be. But in iOS5, the same DatePicker is in the middle of the screen on portrait mode, and off screen in the landscape mode.
Do you know a solution which works on iOS 5 and iOS 6?

Autorotation mechanism has changed in iOS 6.
From iOS 6.0 Release Notes:
The willRotateToInterfaceOrientation:duration:,
willAnimateRotationToInterfaceOrientation:duration:, and
didRotateFromInterfaceOrientation: methods are no longer called on any
view controller that makes a full-screen presentation over itself—for
example, presentViewController:animated:completion:. You should make
sure that your apps are not using these methods to manage the layout
of any subviews. Instead, they should use the view controller’s
viewWillLayoutSubviews method and adjust the layout using the view’s
bounds rectangle.
I think you should implement the iOS 5 specific methods to make it work.

Related

Unable to add UIScrollView to UITableView

UPDATED -- I have an iPad app that was originally designed and written for portrait mode only; I now want to add a UIScrollView so it will scroll in landscape mode. Auto Layout is checked and the different scenes are built using Storyboard. (I am following this tutorial). The major problem is when switching from portrait to landscape, the bounds of the frame change drastically, thereby causing problems with the logic of the scroll.
This is the image of the first scene (UIView) I am trying to add a UIScrollView to:
This is what it looks like in landscape mode (w/o scrolling):
This is my code in the -viewDidLoad method for that scene:
// create UIScrollView
UIScrollView *scroll = [[UIScrollView alloc]initWithFrame:CGRectMake(0,0,self.bookDetailView.frame.size.width, self.bookDetailView.frame.size.height)];
scroll.delegate = self;
scroll.pagingEnabled = YES;
scroll.scrollEnabled = YES;
scroll.showsVerticalScrollIndicator = YES;
CGSize scrollableSize = CGSizeMake(768, 1024); // size of portrait mode
scroll.contentSize = scrollableSize;
[self.view addSubview: scroll];
The scroll bar (as thin as it is) now shows, BUT although it moves like it should, the UIView doesn't move. Portrait mode works fine (no scrolling needed) but landscape mode doesn't scroll at all (even tho' the vertical scroll bar does move). I'm wondrering if I should abandon the idea of using scrolling for landscape mode and create separate scenes for landscape mode instead.
Is there any reason why you need a separate UIScrollView ? UITableView is already a scroll view. My guess is that the touch events from the UIScrollView you created are interfering with those of the UITableView.

iOS9 covering status bar with custom uiwindow - wrong position

I am trying to cover status bar with my own view and to do that I calculcate frame for my view by doing something like that (also after rotation):
UIScreen *screen = [UIScreen mainScreen];
CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame;
For iOS8+ (because since ios8 UIScreen is orientantion-dependant):
CGRect frame = [screen.coordinateSpace convertRect:statusBarFrame toCoordinateSpace:screen.fixedCoordinateSpace];
[self setFrame:frame];
For iOS7:
[self setFrame:statusBarFrame];
It works just fine for iOS8 and below but when building my app with Xcode 7 beta 4 and iOS 9 SDK something is wrong when starting app in landscape or upsidedown (it works fine if app starts in portrait) ...
ie. when I start the app while Upsidedown the custom uiwindow which should cover status bar will always end up at the bottom side of screen, any ideas what might be wrong?
Without additional information, the best solution would be to simply hide the status bar. If you still want the "status bar" for animation purposes or some other reason, the typical solution in this scenario is to simulate it by calling
- (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates on UIScreen
and use the returned view as the background for whatever view/window you're presenting. As of iOS 9, there's no public method that'll allow you to get the specific behavior you specified.

UIBarButtonItem with portrait and landscape images may show portrait image for landscape orientation

In iOS 7, I am showing a UIBarButtonItem in the navigation bar of a UINavigationController. The UIBarButtonItem has an image for portrait orientation and another image for landscape orientation:
// "self" refers to the UINavigationController
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:portraitImage landscapeImagePhone:landscapeImage style:UIBarButtonItemStylePlain target:nil action:NULL];
If you just rotate the interface, the correct image is used for the interface orientation. However, if the view for the UINavigationController first appears in landscape orientation (say, by presenting it in landscape orientation or by dismissing a view controller that is covering it up in landscape orientation), the portrait image is used instead! Why is this happening? Is this a framework bug? If so, is there a way to work around this, so the landscape image will always be shown for landscape orientation?
I'm having this same problem.
I found a solution over at UIBarButtonItem with separate portrait and landscape images - layoutSubviews not called when popping a view controller from UINavigationController that sounded really promising, but it doesn't work for me. I'm going to go with changing the image on orientation change instead. Please post your solution if you find something better.
The landscape image works all of the time on UIToolbar, but not UINavigationBar. With UINavigationBar, I get the problem you state. I also had the problem that if I tapped the button in landscape, it would change to its portrait version.

Hiding Nav Bar moves view "up"

The usual story -- I'm making an iOS 5/6 app run under iOS 7 and the navigation bar behavior change is causing a problem.
The app already worked like the iOS 7 default with a full-screen view and a translucent nav bar "over" of the view. The problem is that hiding/un-hiding the nav bar causes different behavior in iOS 7. On iOS 5/6 hiding/un-hiding the nav bar does not change the view. On iOS 7, hiding the bar visually moves the view up leaving a blank bar at the bottom of the screen and un-hiding the bar moves the view back down to occupy the full screen (with the nav bar on top, of course).
I need to continue to support iOS 5 so I don't use auto layout, but I do use the full screen.
I have a view in which I'm viewing a zoomable image -- so the view controller has a fullscreen view containing a scrollView which contains an imageView.
The status bar is always hidden.
I get to the view controller via a navigation controller so there is a (black, translucent) navigation bar which lies over the top of my fullscreen view/scrollView/imageView.
After a brief delay some overlaying labels fade and the navigation bar is hidden
A single tap restores the overlay labels and un-hides the navigation bar.
This works on iOS 5/6 -- the navigation bar slides off the top of the screen uncovering the top of the view/image.
On iOS 7, when the navigation bar slides off the top of the screen the entire view visually moves up a corresponding amount (i.e. 44 points) leaving a black bar at the bottom of the screen. I can see this by setting a background color on the top-level view and resizing the scrollview enough to see the background; the top of the view does indeed move offscreen and the background color is not drawn over the bottom (44 points) of the screen.
BUT, self.view.frame doesn't change and remains at {0, 0} 320 x height.
When I single-tap to restore the overlay info and navigation bar the view moves back down to occupy the full screen and the translucent nav bar is over the top of the view/image.
Nothing I've tried changes the behavior:
Changing the IB view controller layout controls (Under top bars, Under bottom bars, Adjust scroll view insets). Building for 5.1, 6.1, and 7.0 all produce the same result when run under 7.0.
self.edgesForExtendedLayout = UIRectEdgeNone
does nothing. Using the layout delta values doesn't do anything. In IB the view looks the same when "viewed as" iOS 7 and iOS 6 and earlier. I print out a lot of debug info but nothing about the view (or scroll view) seems to change when the view moves "off screen".
The code that shows the overlay info (run when the view is first shown and on single-taps) is:
- (void) showOverlayInfo {
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
[[[self navigationController] navigationBar] setTranslucent:YES];
[[self navigationController] setNavigationBarHidden:NO animated:NO];
overlayInfoHidden = NO;
overlayInfoFading = NO;
self.infoButton.hidden = NO;
self.infoButton.alpha = 1;
self.descriptionLabel.hidden = NO;
self.descriptionLabel.alpha = 1;
}
The code that hides the overlay info is:
- (void) hideOverlayInfo {
overlayInfoHidden = YES;
overlayInfoFading = NO;
self.infoButton.hidden = YES;
self.descriptionLabel.hidden = YES;
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}
So can anybody tell me what (presumably simple) thing I'm missing?
I finally found my problem.
The key fact is that the image-viewer view controller was in a UIPageViewController,
so what I was looking at and experimenting with was really "inside" another view controller.
Although I had disabled the view controller setting Adjust Scroll View Insets for the image viewer VC, I hadn't done it for the containing VC that created the UIPageViewController and the UIPageViewController presents the pages in some subclass of a UIScrollView. When I changed them for the parent VC, the problem vanished.
So I think the moral of the story is to:
Think about the problem more globally when local doesn't work because maybe you're missing some important context.
If you don't want to use the iOS 7 behavior, change the settings for every single view controller you have!

Autoresizing UINavigationBar in AnnotationView

In my app I have a TabbarController. One of the tabs opens a View which starts the iPhone camera. This CameraView is part of a SDK which is developed by another company. So I can't modify the class of this CameraView.
My problem is that I have to implement a UINavigationBar in this CameraView. I've solved this through a annotationView (this navigationbar is not handled by a navigationcontroller):
[self.annotationView addSubview:navbar];
All works well except the autoresizing matter. If I turn the phone to landscape mode the navigationbar is too short.
I have already tried to set Autoresizingmask but that doesn't help.
Do you have any ideas how I can force the navigationbar to autoresize?
Thanks in advance
Try to adjust the frame of the navigationbar manually, instead of using autorotation.
-willRotateFromInterfaceOrientation:(UIInterfaceOrientation)fio toInterfaceOrientation:(UIInterfaceOrientation)tio
{
if(tio == UIInterfaceOrientationLandscape)
//set navbar frame
else
//...
}