Get correct bounds for navigationItem.titleView layoutSubviews - iphone

I have a subclass of UIView that I've added to as the titleView of a navigationItem using the following line of code:
self.navigationItem.titleView = tempview;
Easy enough. That works fine. My problem is that this navigationItem sometimes has the rightBarButton updated (sometimes there is no button, sometimes there is one standard sized button, sometimes there is a larger button).
I figured that I could simply use the layoutSubviews method of the tempview class that I've added as the titleView so I put this in:
-(void)layoutSubviews {
[super layoutSubviews];
self.mylabel.frame = self.bounds;
}
This does not seem to work, as it does not correctly resize the titleview when the rightBarButton item is updated.
I've noticed also that the bounds do not grow once they gotten smaller, they simply change the position.
I've tried using setNeedsLayout and layoutIfNeeded but those simply "resize" the view with the incorrect bounds.
I've also made sure that the rightBarButton item is set to nil, but the view still does not correctly expand once shrunk.
Thanks for any help!

configure your view with
[self setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth];
(probably in the initWithFrame)
then implement
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[self setFrame:[newSuperview bounds]];
}
now you have your view matching the size of the container, and resizing automatically.

By default, layoutSubviews does nothing. You also never change the size of the titleView, so unless a navbar does that for you, it's no surprise that nothing is changing.
Since you're only changing the size of one of the subviews, I don't think autoresize will work, as I'm pretty sure it's triggered when the superview (the one with autoresizesubviews enabled) changes size. I would suggest recalculating the size of the titleview when you change the rightbutton. If it automatically fits when you add it the first time, you could remove and readd it, but I know that's a pretty ugly hack.

Instead of overriding -layoutSubviews have you tried setting the autoresizingMask property?
tempView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Related

Storyboard UIScrollView contentSize?

I feel like I have touched on every single possible cause for stopping this, but I have a UIScrollView in my Storyboard hooked up with an outlet and in the viewDidLoad I set the contentSize so that I can scroll (yes bigger than my frame size)!
However, whatever I change, I just can't scroll! I have a couple of textfields in my scrollview and bouncing enabled so I can see that when testing its moves up and down with my subviews in it but whatever I set the contentSize to I just can't scroll.
Anything I might be missing/should check? Is this a known issue with UIScrollView being used in a storyboard?
Whats even stranger is, I can do something like this:
[scrollView setBackgroundColor:[UIColor blueColor]]; and I have a blue scroll view! But setting content size fails.
Edit
My only code (otherwise scrollview is just dropped into storyboard view controller):
-(void)viewDidAppear:(BOOL)animated
{
[scrollView setContentSize:CGSizeMake(320, 640)];
}
Logged frame, comes out as expected:
width: 320.00
height: 504.00
Edit 2
Turns out that removing any subviews of the scroll view in my storyboard lets it scroll just fine. If I add any subview to it at all via the storyboard, even a blank brand new UIButton it just won't apply the contentSize/allow scrolling.
use ViewDidLayoutSubview
- (void)viewDidLayoutSubviews
{
[_scrollView setContentSize:CGSizeMake(320, 500)];
}
UIViewController's method invoke sequence is as below
awakeFromNib
viewDidLoad
viewWillAppear
viewWillLayoutSubviews
viewDidLayoutSubviews
viewDidAppear
viewDidLoad is not a good place to put code that relies on frame sizes of IB objects. If you log the contentSize of your scroll view in viewDidLoad, you will see that it's (0,0). Move the code (where you set the content size) to viewDidAppear, and it will work properly.
Check these
User Interaction enabled
Outlet connected
Included contentsize greater than bounds
scrolling Enabled
eg
scrollView.contentSize = CGSizeMake(320, 640);
My storyboard looks like this for scrollview [working]
I had exactly the same line of code in viewDidAppear and it did not work
Moved it to viewDidLayoutSubviews and it worked correctly.
[scrollView setContentSize:CGSizeMake(320, 500)];
Thanks trick14 for the answer.
The issue is most probably with Auto Layout. UIScrollView needs special attention when using AutoLayout.
Quick-fix - bind one of the scroll's subviews to the top AND bottom space of it's superview (the scroll view).
Long story:
Questions on SO:
UIScrollView not scrolling regardless of large contentSize,
UIScrollView will not scroll, even after content size set,
UIScrollView doesn't use autolayout constraints
Apple's Documentation:
https://developer.apple.com/library/ios/technotes/tn2154/_index.html
Trip14's answer worked for me. In swift I coded it as:
override func viewDidLayoutSubviews() {
(self.view as! UIScrollView).contentSize = CGSizeMake(600, 600)
}
This seems to be a similar issue. Other Story
It might be an issue with auto layout or constraints in the storyboard.
the best way with the storyboard.:

UIScrollView made in storyboard has frame value of zero

I made a scrollview in my storyboard which contains severals UIImageView.
The problem is, the frame of that scrollview is equal to {0, 0, 0, 0} and I don't know why. The scrollview is visible on my screen, but I'm not able to scroll it.
I already try to set a content size, and a frame, but without success.
Fixed it out !
In fact, I develop the app on iOS 6.0 and I had to uncheck the "use autolayout" checkbox on storyboard properties...
Thanks to all anyway !
I was getting this problem too but I need to use auto layout.
I was trying to set an UIImageView as a subview then do some calcs to work out the minimum, maximum zoom scales and set the zoomScale.
The problem was that I was trying to set zoomScale to zero as the scroll views frame was zero which was giving me this error:
<Error>: CGAffineTransformInvert: singular matrix.
So I setup the image and imageView in viewDidLoad / viewWillAppear (and hide the imageView) and then set the zoomScale in viewDidAppear (then unhide imageView).
This seems to work well, although I can't say for sure why. I guess it gives the scroll view a chance to set its bounds correctly.
The issue here is AutoLayout, as some of the other answers have indicated. Specifically, the issue is that autolayout does not occur until after viewWillAppear, and if you put your code in viewDidAppear, you will get funky display artifacts as you change things on the screen while the user is watching...
If you need AutoLayout enabled, the best place to put your frame dependent code is in:
- (void)viewDidLayoutSubviews
Keep in mind that this gets called again and again though, so if you only want some initialization code run once, when the view is displayed, then you can create a BOOL property that stores whether the initial layout has already been done.
#property (assign, nonatomic) BOOL initialLayoutComplete;
And then you can write your viewDidLayoutSubviews this way:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if (!self.initialLayoutComplete) {
// frame dependent code here...
}
}
As I mentioned in this answer: The frame of the scrollview will not be initialised until you are in the viewWillAppear method.
This seems to be a new behaviour in iOS 6, not sure if it's a bug or an intentional change.
You should be able to use auto layout without worrying about this.
Did you connect IBOutlet?
Did you init scrollView with this code:
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 280, 360)];
self.scrollView.contentSize = CGSizeMake(500, 360);
//values are of course only example values
How you add UIImageView to scrollView?
I think one clarification is in place to Enrico comment below.
The frame size will have the right values at viewDidAppear (and in viewWillAppear the value will be set, but they are still zero in that method)

Problem with UIScrollView inside another UIView

I have this UIScrollView inside another UIView, not occuping the entire area (all this is initialized via nib file). I added some content to the scroll view, but whenever I scroll it, the UIScrollView content area moves outside the ScrollView frame, over the UIView area not designated for displaying it.
Shouldn't it remain inside its frame even when I scroll it?
It may be that the clipsToBounds property of your UIScrollView is set to NO. Check the setting in IB, or you can set it in code like so:
scrollView.clipsToBounds = YES;
Failing that, double check that your UIScrollView has exactly the bounds you think it does. Is there any autoresizing flag stuff going on that might be changing the scroll view's bounds?
try to set the clipsToBounds to YES, it may be that:
yourViewController.clipsToBounds = YES;
if not... fbreto is right, post your code...
Make sure you have setContentSize. And also set the frame size of the uiviews inside the uiscrollview correctly when you add them.
Here is a sample code of it http://developer.apple.com/library/ios/#samplecode/Scrolling/Introduction/Intro.html

Set the height of a UITextView from a UIViewController's viewWillAppear event

I'm trying to set the height of a UITextView from a UIViewController's viewWillAppear event, here's the code:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
textView.text = blah blah...
textView.frame = CGRectMake(textView.frame.origin.x, textView.frame.origin.y,
textView.frame.size.width, textView.frame.size.height-20);
}
However, it seems to ignore my sizing, it's as though after this event is called, the textview is resized by something else.
What am i doing wrong? Is there some good way to do this?
Thanks
-edit-
Got it working by putting the code in my viewDidAppear instead of the viewWillAppear.
So it works now.
Although i'm puzzled why i need to do this (remove 20 pixels from the bottom) - i mean shouldn't it resize to fill automatically? Why is it resizing to 20px too long? There's a tab bar at the bottom and a nav bar up the top. Is that confusing it?
Simple but obvious question, does the text change, in other words, is the outlet hooked up in IB?
JUSTA TIP: Look at using the helper functions for CGRect such as:
textView.frame = CGRectInset(textView.frame, 0, 20);
In an app with just this code and a single TextView the resizing occurs as expected. So..it's definitely something else in your app.
Are you maybe referencing the contentsize property or something else in your viewDidAppear?
Got it working by putting the code in my viewDidAppear instead of the viewWillAppear.
So it works now.
Although i'm puzzled why i need to do this (remove 20 pixels from the bottom) - i mean shouldn't it resize to fill automatically? Why is it resizing to 20px too long? There's a tab bar at the bottom and a nav bar up the top.

UIView Subview Does not autoresize on orientation change

In my iPhone app, I have a view controller with two views (essentially, a front & back view). The front view is the main UIView, and the back view is a secondary UIView which is added as a subview using [self.view addSubview:backView] when showing the back and [backView removeFromSuperview] when hiding it. However, when the orientation changes, I have the following issue: the main UIView (frontView) rotates & all of its elements resize properly, but the secondary/subview UIView (backView) does not rotate & all of its elements do not resize properly. Does anyone have suggestions on how to make the secondary UIView autoresize properly according to the rules I have set in Interface Builder?
In the end, the solution I found was simply to separate my UIViews into separate UIViewControllers, and make sure that any views that I wanted to be able to rotate only had one UIView.
If I understand correctly, at the time of rotation 'backView' has been removed from it's superview, yeah? If so, that's the cause of the problem. The autoresize property determines how the view resizes relative to it's superview. If it doesn't have a superview it won't resize.
Perhaps using [backView setHidden:YES] instead of [backView removeFromSuperview] will be sufficient for your needs.
I had the same problem, here is how I fixed it based on imaginaryboy's
suggestions (thanks!)
Add the backview to the viewcontroller at viewDidLoad and hide it at the same time. Show it when needed, Hide it again. Set the resizing of the backview to UIViewAutoresizingFlexibleWidth in IB (or code I guess, I used IB)
Not that this is the same problem, but I found a similar problem when adding 2 subviews in my application:didFinishLaunchingWithOptions method. Since your reference above is using [self.view addSubview:view], I would understand that to mean that self is not your UIWindow. When adding an additional view controller to your App Delegate window (UIWindow), the second view controller will NOT receive any rotation events and will never rotate. Only the first view controller added to UIWindow will rotate. See:Technical Q&A QA1688 I believe this also affects views added after the first view where the first view is later removed from the superview.
I ended up following the suggestion I read elsewhere to use separate views for each orientation, thereby eliminating the need to worry about resizing behavior. As always, YMMV.
Or; if you want to avoid an additional controller, you can achieve the same effect by setting view.frame in willRotateToInterfaceOrientation:: like so
if(UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ;//set stubborn view.frame for landscape orientation
else ; //set stubborn view.frame for portrait orientation
Although it feels like a hack; it's simple.