Stop UIToolbar from Disappearing in Landscape Orientation - iPad - objective-c

Not sure why this happens or how to stop it, my UIToolBar on the details viewcontroller is only visible during portrait view. I want it visible at all orientations. How do I do that? Thank you.

I encountered the same problem by just dragging a UIToolBar on to my view and docking it on the top of the window. It showed up in landscape but not portrait. Interface Builder - at least the one embedded in Xcode 4 - doesn't seem to do the right thing with the resize masks.
While Kshitiz's answer above will work, it has a couple of flaws. As coded, it does not support all four orientations. More importantly, it's not resolution independent.
A better solution is briefly described in enamrik's comment, so credit should go to him/her. Here are the steps:
Select the tool bar in Interface Builder.
Open the Size inspector.
In the Autosizing box, select the left, right and top "i-beams" on the exterior of the square. This keeps the position of the toolbar fixed relative to the sides of the view when the view is resized.
Inside the Autosizing square, select the horizontal line with arrows on both ends. This causes the size of the toolbar to change in sync with the parent view.

in your this function of view controller reset view frame bro
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Override to allow orientations other than the default portrait orientation.
if (interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight) {
self.view.frame = CGRectMake(0, 0, 703,768);
} else {
self.view.frame = CGRectMake(0, 0, 768, 1024);
}
return YES;
}
and your tool bar frame too
good luck

Faced the same problem when I add UIPickerView programmatically and add UIToolBar for the PickerView. Just need to add [.flexibleWidth,.flexibleHeight] for the UIPickerView. eg:-
let statTypePicker = UIPickerView()
And then add
self.statTypePicker.autoresizingMask = [.flexibleWidth,.flexibleHeight]

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.

Vertical UIToolBar and also its UIBarButtonItem

In my application i have one UIToolBar. When in portrait mode this toolbar is on top and is horizontal, but when the device is rotated this toolbar should be converted to vertical toolbar and should be place on left side. Also its subviews i.e 5 UIBarButtonItems should also be placed accordingly.
Does any one know the solution for this ?
I have read this for reference, But my tool bar should align itself according to the orientation. I am using iOS 6.
There is no built-in vertical menu feature (yet). There are 2 parts in your question:
Vertical UIToolbar:
You may restrict the device orientation and the toolbar will remain at the same location
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
(this will affect all views)
Or you can listen for orientation changes and rotate your toolbar accordingly using its transform property, e.g.
toolbar.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI/2);
Rotated UIBarButtonItem:
If you have rotated the toolbar (case 2 above), items will rotate too.
If not, you need to rotate your items. Several post shows how to deal with the fact that as UIBarButtonItem does not extend UIView, it has no transform property (see here). In the end you will have again to listen for orientation changes and rotate the subviews of your toolbar, e.g.
for (UIView *view in toolbar.subviews) {
view.transform = CGAffineTransformRotate(CGAffineTransformIdentity, M_PI/2);
}
Of course apply the rotation related to your orientation (M_PI/2 or -M_PI/2).
I ran into this same issue, so I subclassed UIToolbar and made it into exactly what I wanted it to be.
Here's the GitHub link: https://github.com/fennelouski/NKFToolbar

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

Possible to manually rotate UIPopoverController's view?

The view system in my app is highly customized and uses a number of views that are manually rotated from portrait to landscape based on user interactions (the rotation is done by applying an affine transform to the view/layer).
I want to present a popover inside one of these rotated views, but the orientation of the popover always appears relative to the orientation of the device (i.e., not relative to the view). I'm guessing the answer is no, but just in case someone has a clever idea: is there any way to manually rotate the view that is presented by UIPopoverController?
Sean, I just tested it for kicks, yes it works.
It has to be done (in my case at least) in viewDidAppear (if done in viewWillAppear, it gets knocked back to the original setting.)
This worked just fine (just tested now) to have a popover at a 90 degree angle. i.e in my case my main view is in portrait mode and the popover is turned 90 deg.
self.navigationController.view.superview.superview.transform = CGAffineTransformMakeRotation (M_PI/2.0);
Are you trying to rotate the popover or just the content shown in the popover? You can control some of the former by setting which arrow orientations are possible. I'm interested in the latter, and it seems to work just by grabbing the content view controller. E.g.:
aPopoverController.contentViewController.view.transform = CGAffineTransformMakeRotation(M_PI);
DISCLAIMER: If you're at all interested in trying to get your app into the store, this code is almost certainly grounds for rejection. It dives into UIKit's private API's which is a big no-no as far as apple is concerned.
#RunningPink had the right idea. Depending on how the view hierarchy is set up, the popover may be back up farther than two superviews. The popover itself it an instance of the (private) class _UIPopover (at least in iOS 5). You can find this view by doing:
UIView *possiblePopover = popoverController.contentViewController.view;
while (possiblePopover != nil) {
// Climb up the view hierarchy
possiblePopover = possiblePopover.superview;
if ( [NSStringFromClass([possiblePopover class]) isEqualToString:#"_UIPopoverView"] ) {
// We found the popover, break out of the loop
break;
}
}
if (nil != possiblePopover) {
// Do whatever you want with the popover
}
In doing this, I found that transforming the view often ended up making the popover look blurry. I found the reason was that the popover's superview was an instance of another private class called UIDimmingView which is responsible for accepting touches outside of the popover and causing the popover to dismiss. Performing the rotation on the dimming view removed the blurriness I was seeing in the popover.
However, transforming the dimming can result in weirdness where certain parts of the window are not "covered" by the dimming view so the popover will not dismiss if these parts of the window are tapped. To get around this, I applied the rotation to the dimming view, reset the dimming view's frame to cover the screen, and then translated the popover view into place.
if (nil != possiblePopover) {
// Found the popover view
CGAffineTransform rotation = CGAffineTransformMakeRotation(-M_PI_2);
CGAffineTransform translation = // Whatever translation in necessary here
// Rotate the UIDimming View and reset its frame
[possiblePopover.superview setTransform:rotation];
[possiblePopover.superview setFrame:CGRectMake(0, 0, possiblePopover.superview.frame.size.height, possiblePopover.superview.frame.size.width)];
// Translate the popover view
[possiblePopover setTransform:translation];
}

Why aren't my views being positioned correctly on interfaceOrientation changes?

I have a UIViewController one UIWebView in it. I'd like the UIWebView to be positioned in the centre of the iPad screen in landscape and portrait modes. So, I've implemented it like this
// UIViewController
// InfoGraphicView is the UIWebView
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationPortrait ||
toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
[self layoutPortrait];
} else {
[self layoutLandscape];
}
}
- (void)layoutLandscape {
NSLog(#"Layout Landscape");
infoGraphicView.frame = CGRectMake(100, 100, 936, 700);
}
- (void)layoutPortrait {
NSLog(#"Layout Portrait");
infoGraphicView.frame = CGRectMake(100, 100, 700, 936);
}
However, it's not behaving as I expected. In the above code, I would expectt he UIWebView to be 100px (or points or whatever the unit is) away from the top and the left. But it's not. In Portrait mode it appears flush with the top left of the screen, and in Landscape mode it seems to be partially offscreen in the top left.
If I set the frame as CGRectMake(-100, 100, 700, 936) then I get it positioned in the center of the screen as I'd like it to be, but I've no idea why.
As usual, there's most likely something simple I'm overlooking but I can't figure it out. Any help greatly appreciated as always.
The coordinates you set on infoGraphicView are relative to its superview, not to the screen generally. And views don't necessarily clip their subviews. Furthermore, the shape set automatically to self.view will depend on the scaling flags set in Interface Builder. However, I think that by default it is set to fill the whole screen.
That said, I think the mistake is in your use of willRotateToInterfaceOrientation:duration:. That is called before the rotation begins, so self.view has the old size (ie, it'll still be portrait sized if rotating from portrait to landscape and vice versa). Probably better to hook willAnimateRotationToInterfaceOrientation:duration: — then the correct size has been set and you'll be within the CoreAnimation block so your view will grow/shrink as part of the rotation animation.
It's also worth checking which resizing flags you have set on infoGraphicView. They'll take effect automatically, in addition to any changes you make. So you probably want to disable them all.
This probably is an issue with the view that the web view is in. The coordinate system used is that of the view’s superview. If that view isn’t being resized on rotation, then you’ll see unexpected layout like this. You can access the superview of a view through the superview property; one way to see its frame would be to use its description. Put this line in one of your layout methods:
NSLog(#"Superview: %#", [infoGraphicView superview]);
That should print out a description of the view.
Once you get that figured out, if you want the web view to have the same layout, you can use its autoresizingMask property. If you set it like this:
infoGraphicView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Then the view will automatically change its width and height to keep the top, left, right, and bottom margins the same.