Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell with left and right labels. How to make them display correctly?

Tags:

ios

swift

I have an UITableViewCell with 2 labels which can have different content. Sometimes the left label is very big and the right label is small, or empty or sometimes the right label contains a lot of information.

Is it possible to make them display correctly (i.e. no label should be truncated and the hight of the labels should be as small as possible) only by playing with the constraints and content hugging/compression resistance priorities?

I already tried adding constraints for minimum width, or changing the priorities for compression and hugging to 1000, but I always have some issues like either the text is truncated (see screenshot) or one of the labels is displayed on 10 lines and the other on only one line (see the second screenshot).

Here is some sample data that I'm playing with (demo project available here https://github.com/adi2004/iosamples/tree/master/TableView):

    let data = [
    (left: "left one two three four five", right: "7"),
    (left: "left one two three four five 6 7 more here", right: "right one two three four five 6 7"),
    (left: "left one two three four five 6 7", right: "right one two three four five 6 7 something"),
    (left: "6 = ", right: "right one two three four five 6 7"),
    (left: "left one two three four five 6 7 right one two three four five 6 7 eight right one two three four five 6 7 eight", right: "")
]

Here are some samples of the issues I'm facing: Imgur

-- or --

Imgur

like image 740
Adi Avatar asked Dec 28 '18 13:12

Adi


People also ask

What is a uitableviewcell?

The visual representation of a single row in a table view. A UITableViewCell object is a specialized type of view that manages the content of a single table row. You use cells primarily to organize and present your app’s custom content, but UITableViewCell provides some specific customizations to support table-related behaviors, including:

How to add a recipe thumbnail to a table view cell?

Select “Image View” and drag it into the Table View Cell. This image view will be used for displaying the thumbnail. You can resize it to make it fit the cell. For your reference, I set both the height and width to 69 pixels. Next, we’ll add three labels: Name, Prep Time and Time. The “Name” label will be used to display the name of recipe.

How to create a custom table view cell in Xcode?

Right after selecting the option, Xcode prompts you to select a template. As we’re going to create a new class for the custom table view cell, select “Objective-C class” under “Cocoa Touch” and click “Next”. Fill in “SimpleTableCell” for the class name and select “UITableViewCell” for the “Subclass of” option.

How do I create a custom table view cell in simpletable?

As we’re going to create a new class for the custom table view cell, select “Objective-C class” under “Cocoa Touch” and click “Next”. Fill in “SimpleTableCell” for the class name and select “UITableViewCell” for the “Subclass of” option. Click “Next”, save the file in the SimpleTable project folder and click “Create” to continue.


Video Answer


3 Answers

Main idea is to declare how wide should labels be. To do this, you have to declare some rules.

Start with deciding, which label will have bigger priority, so let's say you need bigger priority for left label, so set its Horizontal Content Hugging Priority bigger than of right label

enter image description here

Now for both labels set their minimal width. This you can achive by setting width constraint with certain constant and relation Greater Than or Equal

enter image description here


enter image description here enter image description here

if you need to have always same "spacing" between labels, set their common constraint with relation Equal

enter image description here

like image 26
Robert Dresler Avatar answered Sep 20 '22 07:09

Robert Dresler


First of all check this screenshot. Is it fulfilling what you want?

enter image description here

From your comments on other questions, i can say, this one is what you were looking for.

These are steps that i have taken for creating the cell for this:

  1. Add TableViewCell in your tableview, give identifier and cell class to it.
  2. Add UIStackview in this cell with Alignment = Fill, Distribution = Fill Proportionally, Spacing = 0 . Give top, bottom, leading, trailing constraint to stackview, currently I used value = 12.(use whatever marging you want)
  3. Add 2 UIViews inside this stackview, add background to both view, rightnow, i gave green and red to each one.
  4. Now add UILabel to each UIView, set numberOfLines = 0, give top, bottom, leading and trailing constraints with value 0 to each label. Now, just connect the IBOutlets to respective cell class.

Your required cell is ready, set value you want in datasource and run the code. Let me know any further help you required. Make sure you are adding UILabel inside UIView, not directly to UIStackview. This is done because, multiline label inside stackview will never give you proper result.

UPDATE:

As @Gal pointd out that above code is not working while dequing.. Here, is changes that i made to resolve the same.

Change 1 : Updated cellForRowAtIndexPath to invalidate intrinsicContentSize of containerViews and asking cell to layout the constraints again. Here, is my implementation:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell") as! TestCell;
    cell.leftLabel.text = data[indexPath.row].left;
    cell.rightLabel.text = data[indexPath.row].right;
    cell.leftLabel.superview!.invalidateIntrinsicContentSize();
    cell.rightLabel.superview!.invalidateIntrinsicContentSize();
    cell.layoutIfNeeded()
    return cell;
}

Change 2: Making above single change were working for all the cases, except that one in which any label's text value was empty(in that uiview was apparently removed out from stackview, by stackview itself). So, to prevent this, i have again updated my above cellForRowAtIndexPath code, making sure that any label's text is not getting empty. If empty, then adding just empty space there. It will be like this,

let leftText = data[indexPath.row].left;
if leftText.isEmpty{
    cell.leftLabel.text = " "
}else{
    cell.leftLabel.text = leftText;
}

let rightText = data[indexPath.row].right;
if rightText.isEmpty{
    cell.rightLabel.text = " "
}else{
    cell.rightLabel.text = rightText
} 

After making above change. The screenshot will have very minor small slice, if you hide the background, then you cant find that, it exists there. Here, is the screenshot:

enter image description here

like image 121
Mehul Thakkar Avatar answered Sep 24 '22 07:09

Mehul Thakkar


One more approach with UIStackView,

Image 1Image 2Image 3

Notes:

  • UITableView should have,

    tableView.estimatedRowHeight = 44.0
    tableView.rowHeight = UITableView.automaticDimension
    
  • Keep Label 1 and Label 2 numberOfLines = 0

  • UIStackView should have Fill Proportionally distribution

like image 45
Bappaditya Avatar answered Sep 24 '22 07:09

Bappaditya