Don't let UILabel overlap another label in UITableViewCell - ios

I have a custom UITableViewCell that has a titleLabel on the left, and a detail label on the right, similar to the Right Detail cell type.
Current neither UILabel has a set width, which is what I want. However the titleLabel sometimes is very long and overlaps the detail label on the right.
How can I give a margin between the two labels, ONLY if the titleLabel is too long and will overlap?

The thing what you can do, is set minimum space between them by putting relation GraterThenOrEqual for example at 10 pixels.
Or there is a dodgy way to it by playing with priority with constraints. You may set priority of constraint between as 750.
In the interface builder you have to set space between the labels, and then select manually this constraint, then you will see the menu
called Relation, just choose there GraterOrEqual

Related

Create UITableViewCell constraints to match with built-in cells and avoid "fixed width constraints my cause clipping."

In my UITableViews I have a mixture of built-in cells and custom cells that mimic the look of built-in cells. For example, I use Left Detail Cell UITableViewCells as well as custom cells that also LOOK like a Left Detail Cell but have custom elements (like a left UILabel, but a textfield instead of the right UILabel and maybe other elements like a checkmark image to let the user know when they have entered valid info).
I originally set up the constraints on my custom cells so that blue left-side label would have a width constraint = 91 because that is what the built-in cell's label's width was.
However, for the last few versions of Xcode, it has been complaining at me about "Fixed width constraints may cause clipping."
I've seen all of the myriad Stack Overflow posts telling me to just make my constraint <= or >=, but that does NOT do what I want. I don't want those labels to get bigger, because then the various rows will not have a consistent width on those left detail labels. The screenshot below wouldn't have a consistent layout from row to row.
So, how can I set my constraints on that left detail UILabel so that it will match with the built-in Left Detail Cell's sizing behaviors without getting that stupid warning clogging up my build results?
I tried setting a proportional width on the label, but when I rotate the device my label gets much wider while the built-in Left Detail cell's detail label stays the same width and my UI looks janky because they aren't lined up anymore.
I tried making my fixed width constraint a lower priority (750) and adding a second <= constraint at priority 1000, but then it just complained about both constraints.
Example below:

Why UITableViewCell's overlap each other?

I have a simple UITableViewCell that contains UIImageView and 3 UILabel's. Here, I provide a normal look of the cell to understand the problem deeply:
As you noticed, the description label can be long, so I set numberOfLines to 0. But the problem occurs when that description is empty or small. Cells start to overlap each other. Here is how it looks when the description is empty or small:
If you noticed, pictures overlap each other. The constraints I gave to views are the following:
UIImageView: Leading to superview, width and height, center vertically
BookName(bold label on top): top and trailing to superview, leading to UIImageView
AuthorName(orange label): top to BookName,trailing to superview, leading to UIImageView
Description(gray label): trailing and bottom to superview, top to AuthorName and leading to UIImageView(book image)
I also provided Content Hugging and Compression Resistance Priorities. I provided them only for UILabel's. I set the smallest for description label in order to it grow and shrink.
What I've done to solve the problem?
I realized that if a description is empty, the cell becomes smaller. In other words, labels decide the size of the cell. Also, considering the fact that UIImageView only gets centered vertically, I thought that my constraints are incorrect. So, I decided to get rid of centering vertically the UIImageView. I set top, leading, width and height constraints only for UIImageView. Other constraints were the same as above. But it didn't help, here is the result:
As you see, UIImageView gets out of cell boundary. I thought that it happens because I don't provide bottom constraint for UIImageView. But I provide it for description. So, the next try was actually providing that bottom constraint. So, I provided top, left, bottom and width constraints for UIImageView. I left other constraints the same. Initially, the result was surprising to me. Here is how cells look when there is no description:
Seems like, everything is good(anyway, the image is too small, it tries to fit cell size, that is controlled by labels), but after scrolling UITableView, cells are changing their sizes and somehow updates their constraints. Here is what happened:
I also tried to set estimatedRowHeight and automatic dimension, but it didn't help and I don't think that the problem is solved in this way. So, any help is appreciated.
Keep constraints on the Image view as leading to superview, width, height, vertically centered. Keeps constraints on book name and author label as is. Now On the detail label put constraint as top to author label, trailing to superview, leading or left to image view, bottom to superview. For bottom to superview constraint on detail label change relation to greater than or equal to in Attributes inspector. Change constant to a value you need.I suggest increasing the constant and testing till you get the desired result. Start with something around 20 or 30 and test and then increment value to something else till you get the effect you want. At some value of this constant you will get the effect.
Hope this helps.
NOTE: This is assuming that your Book name label and the author label at least have some text. It can fail on other devices, so also use size classes to set different constraints

Two stacked dynamic height labels in UITableViewCell

I am trying to have two labels stacked in a UITableViewCell. I have AutomaticDimension and estimatedRowHeight set on my tableView.
I want the cells to show up stacked, with their dynamic heights if they both have content.
If only one has content, I would like it to be centered in the cell, or rather have the cell collapse to only show that label.
I have tried every constraint combo I can think of, but usually the labels either do not expand, or I end up with filler space where the label should be.
If the label has no text, I am setting label.text = "".
I am calling sizeToFit() on the labels each time I set the text.
What is the correct constraint combo? Here is what I currently have to start with.
you have to make two labels with leading, trailing, top and bottom constrains and don't add height constrains
make the number of lines for labels = 0
check the title label and from size inspector menu click on the vertical content hugging priority to be 250 not 251 as shown in the screen
image
in the viewController connect your tableview and add these lines
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 44
This could be done using StackViews in iOS,
in the Storyboard Select your both Labels and embed them inside a UIStackView
one of the benefits if you declared a good constraints it should automatically handle the requested behavior.
I recommend this tutorial to get started with UIStackView here
Better solution is UIStackView.
If still you want to go with UILabel you can try one more thing:
Setting label.text = "" will decrease the height of label but the constraint for distance between the labels will not make the label in centre.
For that add a referencing outlet of distance constraint and set it :
distanceConstraint.constant = 0
programatically while setting the label.text = "".
This will set the label with data in centre.
Hope this helps.

Stretch UILabel to full width of UICollectionViewCell

This sounds like a trivial thing to do, but for some reason I can't figure out how to get this work with AutoLayout.
I have a UICollectionViewCell with two subviews in Interface Builder
UICollectionViewCell
- UILabel
- UILabel
The UICollectionViewCell has a dynamic width height, and so I'd like to set the first UILabel's frame to be something like this using AutoLayout.
CGRectMake(5, 5, collectionViewCell width, collectionViewCell height-10);
However if I select UICollectionViewCell and UILabel, and then click the left-most icon to "Add new alignment constraints", then none of the options are available (e.g. Trailing Edges).
Those menu items were not enabled, because the two items you selected did not have a common superview.
Select UILabel without also selecting UICollectionViewCell.
Auto Layout already understands that the cell is the label's superview, and knows to pin the label's edges to the cell.
Update:
The 'Pin' tool is used for size, or spacing between items. In your
case, you want to set the space between your label and the cell.
The 'Align' tool is used for centering items, or lining items up by
an edge. For example, if you had two labels in your cell, you could
ensure that one label lined up with the other label's baseline.

UITableViewCell dynamic constraints

I am making filling a UITableView with custom cells of dynamic heights. I am using the methodology as described here.
For the purposes of simplicity, say my cell contains 2 UILabels as shown below.
The purple UILabel will remain the same height for all cells in the UITableView. In this case, the purple UILabel is taller than the green UILabel. I would like the constraint between the bottom of the purple UILabel and the bottom of the contentView to be 8.
However, there is a second scenario that is possible as shown below.
In this case, the purple UILabel is still the same size as the first case (even though it looks smaller, but since the overall cell height is larger, relatively, it looks smaller), however the green UILabel is much larger. In this case, I would like the constraint between the bottom of the green UILabel and the bottom of the contentView to be 8.
Now my dilemma is that I can set either one or the other (I am using storyboard). But I cannot think of a way to make both possible at the same time. My guess is that you would need to adjust constraints programmatically during runtime depending on the size of the green UILabel.
Any thoughts?
I am using XCode 6.1.1 in Swift.
Thank you.
If the purple label is always the same height, then you should just set the height constraint of the element, rather than setting its bottom constraint to superview as 8.
For the green element, perhaps you could select both that element and the contentview and set them as having equal heights from the "add new constraint" pane at the bottom of the storyboard window. Then, select that constraint and edit its multiplier value in the attributes inspector to some value less than 1. That would make the element's height always be some percentage of the parent view's height. You could tweak that around until it gets you close to the desired 8px from the view below it.

Resources