Objective C: Adaptive Toolbar On Orientation Change - objective-c

I am having a problem with my toolbar when i change the orientation of my iPad.
i set my nib file into landscape and everything is all right but when i turned it to portrait my toolbar still has the width from the landscape orientation.
how will i make my toolbar adaptive to the orientation change to portrait?
Landscape:
Portrait:
thanks!

Try adding UIViewAutoresizingFlexibleWidth to the toolbar autoresizingMask like so:
myToolbar.autoresizingMask |= UIViewAutoresizingFlexibleWidth
Or, if your doing this in the Interface Builder, make sure this horizontal bar is selected (others may be selected as well, which is fine):
More from the UIView Class Reference about autoresizingMask:
When a view’s bounds change, that view automatically resizes its
subviews according to each subview’s autoresizing mask. You specify
the value of this mask by combining the constants described in
UIViewAutoresizing using the C bitwise OR operator. Combining these
constants lets you specify which dimensions of the view should grow or
shrink relative to the superview. The default value of this property
is UIViewAutoresizingNone, which indicates that the view should not be
resized at all.
When more than one option along the same axis is set, the default
behavior is to distribute the size difference proportionally among the
flexible portions. The larger the flexible portion, relative to the
other flexible portions, the more it is likely to grow. For example,
suppose this property includes the UIViewAutoresizingFlexibleWidth and
UIViewAutoresizingFlexibleRightMargin constants but does not include
the UIViewAutoresizingFlexibleLeftMargin constant, thus indicating
that the width of the view’s left margin is fixed but that the view’s
width and right margin may change. Thus, the view appears anchored to
the left side of its superview while both the view width and the gap
to the right of the view increase.
If the autoresizing behaviors do not offer the precise layout that you
need for your views, you can use a custom container view and override
its layoutSubviews method to position your subviews more precisely.

In addition to adjusting the flexible width of your toolbar you could create 2 arrays of toolbar items. One for portrait and one for landscape. Fortunately you only have to create the toolbar items once and just add them to the appropriate array(s).
Then during the orientation change you can set the toolbar's items array to the appropriate one.
Good Luck

Related

Circle shaped, dynamic view with AutoLayout

Before AutoLayout I could do a view cut to a circle shape with setting .layer.cornerRadius to half of the view's height.
Now, using AutoLayout how can I achieve, to my view keep look like a circle?
I have already tried and failed:
using KVO to find out when frame changes. It gets called, but at that point setting cornerRadius on the view does not have any effect
calling -setNeedsLayout to have frame values before I set cornerRadius (does not work either)
You need to set the property masksToBounds on the layer.
xyz.layer.masksToBounds = YES;
Further, the reason why this actually won't affect Auto Layout is because the view's frame will remain the same regardless of its corner radius.

How do I resize a UIView and force its subviews to resize

I have a UIScrollView with a UIView as a subview. The UIView has a bunch of data entry fields arranged vertically - essentially just a fixed format data entry Form.
I want to keep the UIView's vertical size and adjust its horizontal size to match the size of the UIScrollView which changes depending on the orientation of the device. Note that this is all placed in the Detail view of a UISplitViewController.
So the user will have to scroll vertically but not horizontally as all the text fields on the UIView should resize themselves to fit horizontally on the screen.
Currently if I resize the UIView by changing the frame width to match the UIScrollView's frame width then the UIView subviews (the text fields) don't resize themselves according to the constraints setup in IB. The UIView just seems to get clipped. There is no horizontal scrolling so this aspect is working correctly.
I have autoresize subviews set on UIView and on UIScrollView.
Any tips on what to do here ? Also where would I put code to resize the UIView if the device orientation changes ?
Additional information.
I created the UIView in IB as a separate view in the same NIB as the DetailViewController containing the UIScrollView. Because it is much taller than the UIScrollView the only way I can find for creating it in IB is if I set it up as a separate view of the desired width and height. I then create an IBOutlet and add this view as a subview to UIScrollView in the viewDidLoad method. This all seems to work find with the views all displaying correctly, with the exception that the UIView subviews are not resized horizontally.
Any suggestions on what I may be doing wrong here?
Since you are using not putting the view inside scrollview directly from the xib, the IB doesn't provide the options to give constraints that has anything to do with superview. You might have to add the constraints programatically.See here.
EDIT:
Also try using the below on the view (haven't tried, should work according to documentation, but not sure with auto-layout):
self.view.autoresizesSubviews = YES;
Or if you don't want to use auto layout at all then the earlier method of setting the view to expand (horizontal/vertical) in the size inspector would do. For this you have to disable auto-layout. Select xib-> File Inspector -> Uncheck auto-layout checkbox
OK after more discovery I think I have found the right way to do what I am trying to do so i thought I should leave a note regarding this. Remember I am trying to create a scrollable form that resizes its width but not its height so the user only has to scroll up and down to access fields.
To create a large fixed size form that requires scrolling on the device make sure you set the ViewController size to Freeform in IB. Then you can create the view to be whatever size you want in IB and at runtime it will resize to the devices size.
Place the UIScrollView (I call it the scrollView) in the main view and pin it left and right and top and bottom (i.e set constraints using IB)
Place a UIView (I call it the contentView) in scrollView and make it the same size as the scrollView and also pin it on all sides to its superview (the scrollView)
Now add all the labels and text fields are required to the contentView and make sure you add vertical constraints from top to bottom and left to right so that autolayout can figure out the width and height in order to calculate the scrollView.contentSize
Set the contentView width constraint as a fixed size to make it look reasonable in IB. Bear in mind we want the width of contentView to always match the scrollView width so the user does not have to scroll sideways, only up and down. We will set the proper width in code at runtime as I have not found any way of doing this in IB only. Perhaps setting priorities on constraints might achieve this but I think UIScrollView won't do this for you.
Now add a property the ViewController.h file and connect this to the contentView width constrain you created in 5) above.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewWidth;
Finally create a viewDidLayoutSubviews method in ViewController and add the following code to set the contentView width to be the same as the scrollView width.
- (void)viewDidLayoutSubviews
{
self.contentViewWidth.constant = self.scrollView.frame.size.width;
[self.view layoutSubviews];
}
If things don't resize properly check all your constraints are correctly set. IB seems to do some things that seem strange to me. But finally I have it working with what appears to be minimum coding.
You can also resize vertically in the same way as long as you set the constraint priority on subviews in contentView to be lower than 1,000. Also set a greater than or equal to size with a high priority if you don't want it smaller than a certain size.
If anyone can figure out how to set the contentView such that it resizes its width to match the scrollView using only IB constraints I would love to know how.

How to set ContentSize of a UIScrollView which is a sub-view?

I have an iPad app using Storyboards. I have one scene with a UIView, which has an additional UIView on the top half (which I draw on), and a UIScrollView on the bottom half (I needed to keeep them separate). I'm having a hard time figuring out how to address the UIView with this code that I copied from another SO question:
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in scrollView.subviews)
{
scrollViewHeight += view.frame.size.height;
}
[scrollView setContentSize:(CGSizeMake(320, scrollViewHeight))];
The way I read the code above, I'm supposed to use the UIView, but that doesn't make sense, since the UIView covers the entire "scene/window". It makes more sense to me to use the UIScrollView to calculate the ContentSize.
So, what am I supposed to use?
Not completely clear on what you are asking. Once you have a reference to the scroll view, either through tags, properties or some other method, you should set its content size to the width and height of all of its content combined (accounting for overlap, etc). Ex. if you had a single image view that was 600 by 900 points inside the scroll view, you'd set its size to a 600 by 900 CGSize.
That goes through all of the subviews of the scroll view using a for...in loop (aka fast enumeration), adding their heights together, then uses that as the height of the content. I don't think that would be a good way to do it, because that assumes that all the subviews are stacked vertically on top of one another perfectly. It's basically going, "For every subview of my scroll view, add their height to this total and then use that as the content size's height."
The easiest way to manage scroll views is to slap all the content into one UIView, place that in the scroll view, then set the scroll view's content size to the frame of the UIView. If you need a reference to the UIView contained in the scroll view, you can set it to a property or give it a tag and use viewWithTag.

UISplitViewController: How to derive detail view's width in pixels programmatically?

<detailView>.view.frame.size.width returns 768px, which is true for portrait but not landscape. How do I programmatically derive the width of detail view so I can layout its children views appropriately? I don't want to use hard-coded values
I've found out that <DetailViewController>.navigationController.view.frame.size.width works accurately for determining width in landscape mode.

What's the code equivalent to the autoresizing mask anchoring options in IB?

How can I get a NSTextField (or any object) to respect the autoresizing options below via code? I want to add new objects to the view dynamically, but when I increase the height of the view, they are anchored to the bottom left, as opposed to the top left as shown, and so new textfields are dropped on top of the old ones.
Is this even possible via code?
Anything you can do in Interface Builder you can do through code.
[myTextField setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)];
This means that the margin between the right edge of the textView and its superview will be flexible, as will the margin between the bottom edge and its superview. Everything else is static.