Move UILabel using Autolayout constrains in XIB only? - ios

Possible a duplicate, but I tried could not make it work so came here.
I (new to autolayout) have two UILabel place one below each other with fixed height space.Both can increase with as per text with in it.
When First UILabel hides bottom should move to First place. How to do it using constraints in view only? I know how to do by creating IBOutlet connection of constraints for second UILabel.
EDIT:
Given question is about more about content hugging related, where as my question is add constrains to move to first UILabel position when first hides.

The only way to achieve what you want with AutoLayout is to set constant of all related constraints to zero. And remember NEVER try to set frame or bounds of your view if you are using AutoLayout(unless you override layoutSubviews and do the stuff in that method, which you rarely need to).
You can check out this tiny project: https://github.com/neevek/UIView-Visibility, I bet that is what you want :-)

Related

iOS Auto layout problems with spacing

I'm trying to place UIImage, UITextView and UIView one after another vertically.
I've set all constraints and spaces between views. But it says that it need constraints for Y position or height for UIView and UITextView.
What have I done wrong?
Here is screenshot: http://s019.radikal.ru/i616/1509/63/f18ed2a349f3.png
Generally these problems arise from putting a UIImageView itself with constraints. Your best bet is to put in a view and embed the image inside the view. This should make your life a lot easier. Just reset constraints and then click add missing constraints on the whole controller. :-)

iOS: Getting height of views with programatically added constraints as only indicator

Hello there fellow iOS programmers. While creating an app I've ran into a problem I can't seem to find an answer to. Let's lay it out:
I'm creating a UIViewController with a UIScrollView as it's only child. Inside this view I have a UIView, and inside of this there is a list of UIViews with UILabels inside them. As you all know you need to specify a contentSize for a UIScrollView.
The problem is that the list needs to be dynamic with it's content, and I therefore have no way to know the views heights beforehand. I'm adding all views with constraints where the height is set to ">=0".
When I later try to set the height of the UIScrollView I need to either get the height of the UIView that the list is inside, or get the origin.y and height of the last view in the list. This of course needs to be ready by the time the view is displayed to the user.
I've currently tried view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize), which returned 0; view.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize), which returned 10000; and view.origin.y + view.frame.height, which also returns 0. It seems to me like the constraints haven't taken effect yet.
I've tried setting both constraints and UIScollView.contentSize from viewDidLoad(). I've also tried to set constraints in viewDidLoad and setting contentSize in viewWillAppear; this yielded the same results. Setting constraints in viewWillAppear and setting contentSize in viewDidLoad only caused a crash.
Bottom-line: When should I set up the UIScrollView.contentSize if I want to get view.height or similar methods to return a correct result, while at the same time be ready by the time the user sees the view?
Btw, I'm making this app in Swift, so answers in this language is preferred, but I'm able to translate from Objective-C to Swift; post in whatever suits you best.
Thank you! :)
You say:
As you all know you need to specify a contentSize for a UIScrollView.
No, as TN2154 says, the constraints between the scroll view and its subviews are "interpreted as the content size of the scroll view" (emphasis added). This is a boon, because you no longer have to mess around with contentSize if doing auto-layout. Just set the constraints for the scroll view's subviews and the content size takes care of itself. This leverages the labels' intrinsic size (and make sure that the label's numberOfLines to zero).
The only trick is that it sometimes cannot figure out the correct width of the labels (because the trailing constraint is to the scroll view's content size, it will sometimes make the scroll view a horizontally scrolling one). You can remedy this by either manually setting preferredMaxLayoutWidth or by setting a width constraint between the label and the scroll view's superview.
Personally, while I understand the inclination to add the UIView containers between the scroll view and the labels, I'd suggest losing them unless you need them for some other reason. IMHO, it simply complicates the constraints unnecessarily. It's hairy enough as it is. Obviously, if these containers bear other utility for you, then go ahead and keep them (and they'll work fine), but if you're doing this simply for the sake of the constraints, you might consider eliminating them.

Why does UIButton resize when I access titleLabel property?

I'm trying to adjust the size of a button to (it's intrinsic size + a little bit more) in order to draw a custom background. However, every time I access self.titleLabel within the button, the size and position resnaps to that of the storyboard. I don't have to do anything with the label to reproduce this, just retrieve it from the button.
I've put logging code all over my button and view controller in order to find where this is happening. It's not coming from a relaying-out of subviews or any other notification I see to get within the view controller. The line before accessing titleLabel, the position and size are correct. The line after, it has snapped back to the storyboard position. Commenting out the access prevents the size/position snapping. Can someone tell me where or why this is happening?
I have no constraints set (that I can tell), but am I fighting against auto-layout here? Should I be doing this a different way like composing controls or something?
Something similar (or the same?) has been asked before at UIButton modifying titlelabel seems to change its frame and UIButton titleLabel resizes on press?, but both were left unanswered or explained away with just "maybe a bug."
If the project has auto-layout enabled, then YES, you're fighting auto-layout. You have two choices, either subclass UIButton so that you can override the intrinsic size calculation, or modify the constraints so that the intrinsic size is not used in any constraint. If you do the latter, then you probably want to create an IBOutlet to the constraint for the width, so that you can adjust the constant property as needed.
This isn't a bug, it's a consequence of auto layout. When using auto layout, you shouldn't set any frames. Instead, you should change the size or position by modifying the constraints. What's happening, is that whenever the view needs to be redrawn, the frame reverts to the frame that's defined by the constraints.

Resizing a UITextView in UIScrollView using Auto Layout issue

I really hate to ask here because I usually try to figure things out on my own. But on this one I've stuck for days and can't find a solution anywhere online.
I have a ScrollView containing multiple subviews. I've got an image view and two labels at the top with fixed heights. Then there is a UITextView and another ImageView (see pictures).
I add the text to the text view programmatically so it should have a dynamic height and the ImageView should move to the bottom so you can scroll. I don't want the TextView to be scrollable in itself but I want all the subviews to move as well.
I know I should be able to solve this issue using constraints. But I feel like I've tried everything and nothing worked yet. It worked when I disabled auto layout and moved the views manually. I'm wondering if there is a better way though.
As you can see I pinned the TextView to the ImageView above with a 1,000 priority and to the ImageView below with a 1,000 priority. The height constraint can not be deleted so I set it to the lowest possible priority. The ImageView on the bottom is pinned to the bottom of the superview with an absolute height. Its height constraint also has low priority. (I can post an image of the ImageView's constraints, if it helps)
I also tried adapting the frame programmatically but this is not working well in combination with auto layout. (If it helps I can of course post the code)
What am I doing wrong? Shall I just disable auto layout and do it manually? This seems unclean to me. Is it even possible to do?
I really appreciate your help :)
Greets,
Jan
Make sure the Scrolling Enabled attribute on the UITextView is unchecked in Interface Builder. I believe that the Auto Layout system takes that into account when it calculates the intrinsic content size.
If somebody is struggling with a similar problem: This is what I ended up doing:
Remove all subviews from the ScrollView in IB
Programmatically add a single UIView to the ScrollView.
Add all the views to the UIView as subviews (move them using setFrame)
Set the Frame of the UIView appropriately to the subviews
Set the ScrollView's contentSize to the size of the UIView.
A little more work but it finally works. This follows Apple's mixed approach guidelines that can be seen here (look for UIScrollView): http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/index.html
The problem is the height setting. You somehow have to try to delete it. If you have added other constraints that are "sufficient", it should become deletable.
At the moment you have one user constraint for the height that is "Greater or equal" and an "Equals" constraint as well. Clearly, those are not working well together.
Maybe there is a conceptual error as well. The lower image view should not be fixed in position, so the distance to the lower image view will not be a "sufficient" constraint to let you delete the fixed height.
I think it should work if
the lower image view has a fixed height and
a fixed distance to the text view above, and
the text view has a minimum height as well as
a fixed distance to the image view above
(which should be fixed in relation to the superview).

How do you override a storyboard element/view on iOS?

I have a UITextView set in my storyboard at a certain position. When the app first loads up, I would like the textView to be at a different position then where it is in the storyboard. I do this programmatically by setting its frame to a different frame with a different origin (later the textView will be animated back to the original position). But no matter how I do it, the app always starts up with the textView in its storyboard assigned position. I can't seem to do this anywhere... viewDidLoad:, viewWillAppear:, nothing works. How can I override it?
One other thing... lets say the textView has a different origin then it does in its storyboard (the frame was reset at some point in the app). If I add a subview to the textview using addSubView:, the textView resets to its original position in the storyboard. Why?! Any way to stop this?
If you want to change the position of the textView when it starts up, I'd suggest that you do not have it in the storyboard and instead add it to the subview with its correct frame.
Especially with Autolayout in effect, having it there already means you would have to modify its constraints and if you're modifying its position programmatically already anyway, you might as well add it to the view programmatically too where you have more control over its constraints programmatically as well.
Under auto layout you can't set frames - well, you can, but as soon as another layout pass takes place, the frame will be reset to that defined by the constraints.
The simplest way to change the size or position of views you've laid out in interface builder using auto layout is to create outlets to the various constraints, and then edit their constant properties. If that doesn't give you enough flexibility, you still need outlets to the constraints, but when you want to move things you'll have to delete those constraints and add new ones.

Resources