Present UIView modally that nots full screen - objective-c

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];
}

Related

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!

Force Subview to fill parent

I have some subviews that I place inside each of my tab bar's view controllers. Right now I'm sizing it with a pixel count but it only works on the iPhone 4 and 4s and not the iPhone 5 because of the longer screen size. I could check for the device and then size it that way but I feel like there has to be an easier way to do this.
viewController1.view.frame = CGRectMake(0, 0, 320, 460);
I colored the subview yellow so it's easier to see.
You should NOT change frame of tabbar's content view controller's view. UITabBar takes itself care of sizing the child view controller's frame properly.
If you want to add subview to content view controller (controller under some tab) and make that view to always automatically resize with the controllers main view (self.view), you can use combination of superviews frame and autoresizing.
Example code (you can do this in - (void)viewDidLoad for example):
UIView *view = [[UIView alloc] initWithFrame:self.view.bounds];
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:view];
If you want to do this by setting frame than DO this:
[childView setFrame:childView.superview.bounds];
The master view in your view controller should already be the size of the usable space on the sceen. In general, if you want a view to be the same size as it's parent, you can use view.frame = view.superview.frame, though I doubt that would be a good idea to call on the view controller's view.

How to use NSScrollview?

I can't figure out how to actually use NSScrollview. I dragged the scroll view object onto an NSWindow in the interface builder. I then dragged some NSButtons onto the scroll view. My question is:
How do I actually make it scroll down, for example, 2x the original height?
Of course the user can scroll automatically using their UI. I assume what you want to do is to scroll programmatically.
A bit of background: An NSScrollView has a documentView, which is the underlying view that the scroll view shows a part of, and a clipView, which is the view that is shown on the screen. So the clip view is like a window into the document view. To scroll programmatically you tell the document view to scroll itself in the clip view.
You have two options on how to scroll programmatically:
- (void)scrollPoint:(NSPoint)aPoint –– This scrolls the document so the given point is at the origin of the clip view that encloses it.
- (BOOL)scrollRectToVisible:(NSRect)aRect –– This scrolls the document the minimum distance so the entire rectangle is visible. Note: This may not need to scroll at all in which case it returns NO.
So, for example, here is an example from Apple's Scroll View Programming Guide on how to scroll to the bottom of the document view. Assuming you have an IBOutlet called scrollView connected up to the NSScrollView in your nib file you can do the following:
- (void)scrollToBottom
{
NSPoint newScrollOrigin;
if ([[scrollview documentView] isFlipped]) {
newScrollOrigin = NSMakePoint(0.0,NSMaxY([[scrollview documentView] frame])
-NSHeight([[scrollview contentView] bounds]));
} else {
newScrollOrigin = NSMakePoint(0.0,0.0);
}
[[scrollview documentView] scrollPoint:newScrollOrigin];
}

Rotating UITabBarController Icon

I have an UITabBar in my application. One of the tab bar icons looks like a loading symbol. When the user presses the loading button I want the icon to spin/rotate until the loading is done. Should I use UIImageView to animate or something else? How should I make this happen?
Jacos, unfortunately you cannot do that with the UITabBarController and manipulate the tabBarController's tabBar properties. My best bet would be that you use a UIToolBar and assign a black color and make it appear like a tabBar and have buttons added in them as a subView so that they look like tabBarItems.
Its much more customizable, and you can even provide a scrolling experience and add more buttons to it.
I know this question is 4 years old but I had the same problem and managed to fix it by reading the tutorial in here:
https://medium.com/#werry_paxman/bring-your-uitabbar-to-life-animating-uitabbaritem-images-with-swift-and-coregraphics-d3be75eb8d4d#.bjfpbdnut
The main point is to get the view for desired UITabBarItem and the get the UIImageView from it in viewDidLoad:
UIView *plusView = self.tabBar.subviews[1];
self.plusImageView = plusView.subviews.firstObject;
self.plusImageView.contentMode = UIViewContentModeCenter;
Then in didSelectItem method you can do this:
[UIView animateWithDuration:0.4 animations:^{
[self.plusImageView setTransform:CGAffineTransformMakeRotation(M_PI/4)];
}];
My code only rotate the image view for 45 degrees but you can change as you wish.
I guess you could change the UITabBarItem's icon on a timer, but that seems pretty kludgey. You would have to pre-render each frame of your "loading" icon rather than rotate an ImageView.
Another hackey solution would be to add your ImageView to the UIWindow and move it on top of the TabBarController's TabBar (adding it to the TabBar itself is asking for trouble).
You shouldn't try to animate the actual UIImageView within the UITabBarController. I would take this approach:
Set the image for the relevant tab to nil or a blank image.
Create a UIActivityIndicatorView and add it over the tab bar. Position it over the correct tab.
[self.tabBarController.tabBar addSubview:activityIndicatorView];
When your loading task has completed, restore the normal image to the tab and remove the activityIndicator from the tab bar.

I would like to implement a half UITableView half MapView UIView with a button in the middle

Well, this is what I want to do in my app: I would like to implment a UIView with a map on the top half of the screen and a tableview on the other half with two buttons in the middle. If I press one of the buttons the map will get fullscreen and if I press the other one the tableView will fit all the screen.
Any suggestion?
In one view controller like a UINavigationController create an MKMapView with a frame the size of the top half of the view and add it as subview of your view controller. Then I would create a UIToolbar to hold your buttons and make the top of it's frame line up with bottom of the MKMapView. Finally create a UITableView with it's frame just below the others (make sure you hook up it's delegates).
Then assign the target of your UIBarButtonItem that makes the map go fullscreen to a method that animates the frames of all three views like this:
[UIView animateWithDuration:0.24
delay:0.0
options:UIViewAnimationCurveEaseOut
animations:(void (^)(void)) ^{
self.toolbar.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN, 320, TOOLBAR_HEIGHT);
self.mapView.frame = CGRectMake(0,0,320,MAP_HEIGHT_FULLSCREEN);
self.tableView.frame = CGRectMake(0, MAP_HEIGHT_FULLSCREEN+TOOLBAR_HEIGHT, 320, MAP_HEIGHT_FULLSCREEN-MAP_HEIGHT);
}
completion:^ (BOOL finished){}
];
Create both views how you are planning, On one button click, change the frame of one view to fit the full screen, if you click the other button, do the same thing to the other view.