How does UIViewController's automaticallyAdjustsScrollViewInsets work anyway? - objective-c

self.automaticallyAdjustsScrollViewInsets = YES;
I set that to yes. I think it's yes by default.
Then when I check the inset this is what I got:
NSStringFromUIEdgeInsets(self.tableView.contentInset): {0, 0, 0, 0}
I thought it should be set up in a way that incorporate the navigationBar and statusbar. So what happened?

From what I know
automaticallyAdjustsScrollViewInsets
allows the view controller to adjust its scroll view insets in
response to the screen areas consumed by the status bar, navigation
bar, and toolbar or tab bar
works on the view which is direct subview (someone says it must be
the first subview) of the View Controller 's view
this view must be a ScrollView subclass
the View Controller is embedded in Navigation Controller or TabBar
Controller
edgesForExtendedLayout is UIEdgeRectTop (if you want the ScrollView
subclass view to be behind the top bar), UIEdgeRectBottom (if you want
the ScrollView subclass view to be behind the bottom bar)
The code below replicates what automaticallyAdjustsScrollViewInsets does when edgesForExtendedLayout = UIEdgeRectTop
self.scrollView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
self.scrollView.contentOffset = CGPointMake(0, -self.topLayoutGuide.length);

I think it depends on your UIVIewController's edgesForExtendedLayout value. If you want content to appear AFTER top, set edgesForExtendedLayout' = UIRectEdgeNone (or UIRectEdgeRight | UIRectEdgeLeft | UIRectEdgeBottom, you just don't want to includeUIRectEdgeTop`)

Related

Custom View Controller Transition clips views to bounds

I have two view controllers with a custom flip animation as the transition. This is the guide I followed for the transitions: http://www.objc.io/issue-5/view-controller-transitions.html. This works fine, except the view clipped to the bounds that constrain the view while stationary. During the animation, the view exceeds these bounds to simulate some perspective.
What I have found is that there is a UINavigationTransitionView added to the subview tree during the animation. This has clipsToBounds set to YES, which I don't want.
I can intercept this view and change clipsToBounds to NO by placing this at the top of the navigation controller delegate method navigationController:animationControllerForOperation:fromViewController:toViewController:
UIView *firstSubview = [view.subviews firstObject];
firstSubview.clipsToBounds = NO;
But this is very hacky at best. Is there a setting to disable clipsToBounds during the view controller transition?

UITableView not showing through Navigation Bar

I have a UITableView as a subview of my custom UIViewController. I want to position it beneath the navigation bar, and when I scroll it I want it to be visibile in a translucent way through the navigation bar. To do this I should set the y of the table view to zero and set the property edgesForExtendedLayout to UIRectEdgeAll; in this way the things should work, because the UITableView should be set right beneath the navigation bar.
I have a big problem: if I set the y position to zero, the table view is positioned under the navigation bar, and the first part is partially hidden below the translucent bar. Also, if I set the y position to the height of the navigation bar, the table view could never be visibile through the navigation bar, because it starts from beneath the navigation bar.
Actually things work for UICollectionView, the y position is set to zero and when scrolling I can see the UICollectionView through the navigation bar.
Any suggestion about the problem? Is this an iOS 7 bug?
set the origin of the UITableView to 0 as you had and then its contentInset using the topLayoutGuide of the UIViewController.
That will probably look like this
self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);
self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, 0, 0);

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!

How do you determine the size/frame of a custom UINavigationItem.titleView?

After creating a custom view and assigning it to the navigationItem.titleView property it is displayed like this
with the custom view filling the space between the two buttons. Therefore, the custom view is not centered on the navigation bar. How do I determine the frame of the view in the .titleView property? I want to center some text in the navigation bar, say under the time stamp.
If you really want to get titleView's frame (in your top-level view's coordinate space), you can do this:
[self.navBar layoutIfNeeded];
CGRect titleViewFrameInTopLevelViewSpace = [self.navigationItem.titleView
convertRect:self.navigationItem.titleView.bounds
toView:self.view];
You need to do layoutIfNeeded if you have just assigned titleView, because by default the navigation bar won't lay out its subviews until the next pass through the run loop.
That said, the titleView will be centered automatically, if it fits. I think you are setting the frame (or bounds) of your custom view too large. I tested this two ways:
I set up the titleView directly in the XIB. I simply dragged a View from the Object library onto the center of the navigation bar:
It sized the view to 128x33 automatically. The resize handles let me adjust the size. It stays centered until it overlaps the Categorize button. Then it shifts left.
I set the titleView property in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 50, 33)];
customView.backgroundColor = [UIColor greenColor];
self.navItem.titleView = customView;
}
The result looks like this:
You could get the width of the leftBarButtonItem and the rightBarButtonItem after you've set them, and then use that to determine how to centre within the view you supply to titleView. That might do what you want?

Present UIView modally that nots full screen

I have a view 200 x 150 px which i would like to present on the tap of a button. If i use addSubview: then the view shows up in the correct position, but i can still tap other buttons on the superview, which is behaviour i don't want.
If i use presentModalViewController then the view takes up the whole screen, which is what i don't want either... this happens even if i set wantsFullScreenLayout to NO.
How can i present the view so that the user can only interact with controls on the presented view?
Thanks
Make the view the size of the screen (taking the status bar into account). That view should have a translucent background color (or clear). Have the 200x150 view be on the bottom of that view to have the appearance of a UIActionSheet, where the background dims and the user cannot interact with other elements on the screen.
Then, you can use presentModalViewController to present the view.
Addition
In the view controller's .m file, define awakeFromNib:
-(void)awakeFromNib
{
self.view.backgroundColor = [UIColor clearColor];
}