Swift Storyboard - Centring an Icon and multi-line text horizontally - ios

I am trying to create an Android-esque Snackbar. All the behaviour is correct but I am left with a layout issue. I have actually broken this out into a test app to simplify things a bit.
The bar is pinned to the bottom of the view and contains an Icon (UIImageView) along with some text (UILabel). This text can be up to 2 lines max.
For example, it should be able to exand out like this:-
However to further complicate things, i need it so that the icon and text are centred within the red bar and then spread out from the centre until such point that it needs to wrap. Note that there is a padding to the start of the icon and end of the text to prevent it touching the sides. An example of centred content would be..
I haven't been able to get the correct layout. I think the issue has been trying to centre the two items whilst simultaneously conforming to a width that doesn't exceed the edge bounds, causing a constraint conflict. I have also tried embedding the icon and label in a horizontal stack view but couldn't seem to find the correct fill option whilst centring everything.
I have even tried using NSAttributed string and adding the image to the text itself but when the text wrapped, the icon was being resized and/or misplaced.
As you can see, i have been doing this in Storyboard but i am more than happy to do this programmatically if it serves this purpose better.

Created this Demo for reference , it's a simple task of making a nested view inside the red view with a centerX constraint of priority 1000 and a leading constraint with 999 priority
Now you have this effect

Related

How to control layout of UIBarButtonItem controls on an iOS toolbar?

On my toolbar I am trying to properly lay out three buttons. One in the middle that should remain centered horizontally, and then one aligned left and one aligned right. But because the text for the left button is longer than either the middle button or the right one, the spacer items won't seem to produce the desired spacing effect. I've tried both fixed and flexible, but of course using the fixed type will not dynamically respond to different screen widths, and the the flexible width ones (UIBarButtonSystemItemFlexibleSpace) will not keep the middle button centered.
I've defined the layout both in Interface Builder and programmatically and I get the same effect, what you see here. For example an iPhone 6s looks like:
and an iPhone 11 Pro looks like:
As you can see the "Mid" button is not centered. By using UIBarButtonSystemItemFixedSpace instead of UIBarButtonSystemItemFlexibleSpace I could define the width of the spacers exactly, but in order to calculate it properly I would need to know the width of each UIBarButtonItem and also the right delegate method to do this in. Is this even possible, or must I do a custom view (or something else) to make this UIToolbar look like I want?
Try adding leading spaces to the Shorter title OR using the following items:
Longer-Text Button, Flexible Space, Mid Button, Flexible Space, Fixed Space, Shorter Button
The fixed space would be a hard coded value to match the width delta between the two buttons.

UILabel scales only for certain text lengths

I have a custom UIView containing a UILabel and a UISwitch. The switch and the label are constrained to be next to each other with their center-y equal and their sides matching the sides of the parent (with a margin). The label is constrained to connect with the top and bottom of its parent (again, plus margin) with its number of lines set to 0 so it can scale as large as it needs to be to fit all the text, using word wrapping as the line break mode. I have a bunch of these custom views below each other in a vertical UIStackView with alignment and distribution set to fill. The stack view itself is positioned inside a scroll view which is constrained to all sides of the root view (which scrolls as expected). Here's a screenshot of the situation that also shows my problem:
I've added a red background to the label in the custom view to show its boundaries. Separator views are added between the custom views. The problem becomes apparent in the second custom view in this screenshot. Its label text is actually WordOne WordTwo WordThree WordFour, but for whatever reason the text is wrapped without the label / parent increasing their size to contain it. Adding an extra word, as in the view below it, suddenly does scale the label to show all of its lines. I've set compression resistance to UILayoutPriorityRequired for both the label and the parent, to no avail. I have a workaround involving a layoutSubviews override with a manual calculation of the label size, but I'd prefer both understanding what's going on and of course avoiding having to use a hack. Can anybody shed some light on this behavior?

Autolayout view dropping down

I’ve built a simple login screen layout. In a vertical direction, there is a logo at the top, followed by 2 text boxes for email and password and then a submit button.
There is an outer container which container 2 more container views, one for the logo and one for the text boxes and button.
With auto layout, I have got the layout displaying correctly in Xcode, with the logo container above the input details container. However, when I launch the app on the simulator or on a device, the logo seems to drop down over the top of the text boxes.
Xcode is telling me I am missing a constraint for containerLayout for y position or height. I’m unsure if this has any impact on the problem.
It would be extremely useful if someone could explain why the logo is dropping down. I will include an image of the constraints in place.
As an absolute minimum, you should:
Add leading, trailing, bottom and top constraints to the logo image view.
Set vertical content hugging priority for the text fields to required (1000).
Add bottom constraint for the sign in button.
You definitely use too much of center X, and equal widths, this obscures entire picture of your layout. If you want to make it simpler and more readable include the following modifications.
Remove center X, center Y and equal widths from the logo image. As you will see it won't break anything but only simplify the layout.
For both text fields, remove center X and equal widths constraints.
For both text fields, add leading and trailing constraints to the superview
Repeat last two points for sign in button.
If you are targeting iOS9 or higher you can use a stack view to layout text fields and buttons. Below you can find the final result. Of course, you can introduce a lot more improvements to this layout but I don't want to reinvent it here.
Update
To configure bottom constraint for the logoDetailsLayout just add it as normal. Sometimes when views are not aligned as they should be Xcode gets lost. In this case, you can double-click this constraint and fix it in the attribute inspector.
This is how I configured it.

Layout constraints are shown in orange color in storyboard

I am creating a quiz app, so there is a table view and there is a cell, and inside the cell there is a full size label and under that four full size buttons.
I have added constraints on all four sides for all the five elements as below
8
|
20 --- ---20
|
8
The color of the constraint lines above and below 8 (single vertical lines in the above example), are showing in orange color, rest constraints are in blue color in the storyboard.
I am not able to make the orange constraints to blue, i have tried a lot of things.
Please suggest what should i try next.
Or
is that even the problem to start with?
My real problem is that multiline title of my buttons are exceeding the limits of the button.
(Ok let me try to explain more, (please picture this), i have put a black border of 1px around the buttons and the title of the button prints outside the border line of the button whenever they are multiline).
Sorry no pics uploaded, not allowed yet.
It is difficult to fully understand without a picture of your Storyboard.
Based on my experience of a typical issue which happens often, probably you initially put the label in the view, then created the four constraints (top/left/right/bottom) and then you moved the label up or down. In such case your vertical constraints don't match with the original one that were set for you by Storyboard. Normally other than the orange lines you should see two orange balloons with the number of the pixel difference between what is expected and what you have.
Also try in XCode the menu Editor --> Risolve Auto Layout issues: this will change the layout to fix the issues and so you can understand the difference. You can see the list of issues also by clicking at the yellow (or red) right arrow put in the top-right corner of your Scene in the storyboard (see attached image).

How to center horizontally two labels?

I have pretty straightforward requirements where two labels must be centered horizontally. So, I have selected them and chose Editor->align->center horizontally. Then added top space to container constraint to both of them. I also need the labels to shrink/grow regarding content size. However, IB shows errors and several warnings. I could make the labels shrink/grow just by adding pin between them (horizontal space) but they will not be centered in that case. Here are the screenshots:
here are the errors and warnings:
UPDATE theraven gave an interesting suggestion to use dummy view for centering it horizontally and pinning two labels to it. I have removed all existing constraints, added this dummy view and center X + center Y constraints to it. Then pined two labels to it (added horizontal space constraints). However, I still get a bunch of errors and warnings:
UPDATE2 Just updating the question, but still no valid answer found. #Theraven workaround works for iPhone4, iPhone4S, iPhone5 and iPhone5S, however it's not real centering but rather a workaround. Therefore for iPhone6 and iPhone6 Plus it doesn't work as leading and trailing spaces will be fixed and won't automatically resize for larger width.
What you could do is add both labels to another view, like a container view. Then you need to center this one horizontally and add the necessary constraints.
To add the containing UIView, you can select both labels, go to Editor -> Embed In -> View.
Then you would need to add constraints to make the containing view fit the two labels. So something like this:
First Label (left one):
Leading Space to Superview
Top and bottom Space to Superview
Horizontal spacing to the next Label
Second Label:
Trailing space to superview
Top and Bottom to superview (or align top with the first one)
Then the containing view should resize as to fit both labels. Then all you need to do is add the top offset constraint for this container view and a horizontal alignment it in the parent view.
This way, the containing view will grow as much as it needs to fit both labels and the space between them and will always be centered in the parent view.
I took a screenshot of my test constraints in case it helps you more.
Hope this was what you were looking for.
To solve this use a blank UIView in between your two labels and center it horizontally. Then pin the two labels either side of the centered blank view. It is common convention to use spacer views like this in auto-layout.
I really don't like the idea of adding another view just for sake of estethic.
Another alternative is to horizontally-center the left view, and horizzontally space the right view of an amout X with the left one.
Then to give the horizontally-align contraint of the first view a negative value equal to the first view width plus half the views distance. Or use multipliers as said in a previous comment.
But this only works with fixed width views i guess.
Use centered UIStackView as a container for two labels with a spacing required.
I didn't really understand what you wish to do.
The error you get (in the first screen shot) is that you are missing constraint for the x position of the labels.
For UILabel you must have constraint both for y and for x position regarding to the container view, when you selected them both and chose Editor->align->center horizontally, you just say that label1.center.x = label2.center.x.
You still need to say where they will be in the container view, you added the top space to container, so you do have the y position, but you didn't say where the x position should be.
You said
I have pretty straightforward requirements where two labels must be centered horizontally
But where they should be in respect to their container?
thanks
Using spacer views is the best possible solution I could figure out, even though it looks ugly for the developer. The user wouldn't even know what's going on behind the scenes and once you have the spacer UIView, you can always reuse it.

Resources