0
votes

I have two labels: title and description. They should be sided by side

----------- --------------
| title   | |description |
----------- --------------

Depending on the content of the two labels the maximum width of the "line" should be used, whereas one label is the "master" label and is always shown. The behavior should be as follows:

Title Description
TitleTitleTitleTitleTitle Description
TitleTitleTitleTitleTitleTitle Descr…
TitleTitleTitleTitleTitleTitleTitleT…
Title DescriptionDescription
Title DescriptionDescriptionDescript…

There are a few cases:

  1. Title label expands and moves description label to the side.
  2. Once the title label is expanded enough, the title label gets abbreviated and the description label should "hide".
  3. When the title label doesn't contain much text, the description label can expand. The description label expands until it reaches the end of the view and then gets abbreviated.

The question is how should the constraint does look like?

title label:

  • left constraint (parent)
  • center Y constraint (parent)
  • width constraint (<= parent width, abbreviates the label)
  • compression resistance: 750

description label:

  • left constraint (title label right)
  • center Y constraint (title label)
  • right constraint (parent)
  • compression resistance: 250

This is what I have now. But it doesn't work as described above. The right constraint on the description label is problematic, because only with it the label gets abbreviated. Using it pins the label always to the right if the title label gets shorter. I tried it with priorities but its either or. Also the hiding of the description label is not implemented (only if I don't have the right constraint for the description label it will exceed the UIWindow and then "disappears").

I don't think its possible to "hide" the description label with auto layout. Only calculating the width and hiding it manually will do it I think.

Pictures and source

Too make it clearer what I want I've made some pictures demonstrating the problem.

// 1: both short
titleLabel.Text = "Lorem ipsum";
descLabel.Text = "Anything";

both short

The result is wrong because the description label is too far left. It should be

Lorem ipsum dolor sit amet. Anything

// 2: title long, desc short
titleLabel.Text = "Lorem ipsum dolor sit amet.";
descLabel.Text = "Anything";

title long, desc short

Same as no. 1 because the title label is too wide.

// 3: title very long, desc short
titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
descLabel.Text = "Anything";

title very long, desc short

// 4: title short, desc long
titleLabel.Text = "Something";
descLabel.Text = "Lorem ipsum dolor sit amet.";

title short, desc long

// 5: title short, desc very long
titleLabel.Text = "Something";
descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";

title short, desc very long

// 6: both long
titleLabel.Text = "Lorem ipsum dolor sit amet.";
descLabel.Text = "Lorem ipsum dolor sit amet.";

both long

// 7: both very long
titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";

both very long

// 8: title long, desc very long
titleLabel.Text = "Lorem ipsum dolor sit amet.";
descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";

title long, desc very long

// 9: title very long, desc long
titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
descLabel.Text = "Lorem ipsum dolor sit amet.";

title very long, desc long

All other results seems ok with my code. And last but not least I can provide you (C#) code:

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    // Perform any additional setup after loading the view, typically from a nib.

    container = new UIView();
    container.BackgroundColor = UIColor.Red;
    container.TranslatesAutoresizingMaskIntoConstraints = false;
    View.AddSubview(container);

    titleLabel = new UILabel();
    titleLabel.BackgroundColor = UIColor.Yellow;
    titleLabel.TranslatesAutoresizingMaskIntoConstraints = false;
    titleLabel.SetContentCompressionResistancePriority(750, UILayoutConstraintAxis.Horizontal);
    container.AddSubview(titleLabel);

    descLabel = new UILabel();
    descLabel.BackgroundColor = UIColor.Yellow;
    descLabel.TranslatesAutoresizingMaskIntoConstraints = false;
    descLabel.SetContentCompressionResistancePriority(250, UILayoutConstraintAxis.Horizontal);
    container.AddSubview(descLabel);

    NSMutableDictionary viewsDictionary = new NSMutableDictionary();
    viewsDictionary["container"] = container;
    viewsDictionary["parent"] = this.View;
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("H:|[container]|", (NSLayoutFormatOptions)0, null, viewsDictionary));
    View.AddConstraints(NSLayoutConstraint.FromVisualFormat("V:|[container(==200)]", (NSLayoutFormatOptions)0, null, viewsDictionary));

    container.AddConstraint(NSLayoutConstraint.Create(titleLabel, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, container, NSLayoutAttribute.CenterY, 1, 0));
    container.AddConstraint(NSLayoutConstraint.Create(titleLabel, NSLayoutAttribute.Left, NSLayoutRelation.Equal, container, NSLayoutAttribute.Left, 1, 10));
    // solves 3
    titleLabelWidth = NSLayoutConstraint.Create(titleLabel, NSLayoutAttribute.Width, NSLayoutRelation.LessThanOrEqual, container, NSLayoutAttribute.Width, 1, -20);
    container.AddConstraint(titleLabelWidth);

    container.AddConstraint(NSLayoutConstraint.Create(descLabel, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, container, NSLayoutAttribute.CenterY, 1, 0));
    container.AddConstraint(NSLayoutConstraint.Create(descLabel, NSLayoutAttribute.Left, NSLayoutRelation.Equal, titleLabel, NSLayoutAttribute.Right, 1, 10));
    // solves the rest but breaks 1
    descWidth = NSLayoutConstraint.Create(descLabel, NSLayoutAttribute.Width, NSLayoutRelation.GreaterThanOrEqual, null, NSLayoutAttribute.NoAttribute, 1, 0);
    container.AddConstraint(descWidth);
    descRight = NSLayoutConstraint.Create(descLabel, NSLayoutAttribute.Right, NSLayoutRelation.Equal, container, NSLayoutAttribute.Right, 1, -5);
    //container.AddConstraint (descRight);

    // test cases
    // 1: both short
    //          titleLabel.Text = "Lorem ipsum";
    //          descLabel.Text = "Anything";
    // 2: title long, desc short
    //          titleLabel.Text = "Lorem ipsum dolor sit amet.";
    //          descLabel.Text = "Anything";
    // 3: title very long, desc short
    //          titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    //          descLabel.Text = "Anything";
    // result: X => solved (except desc label)
    // 4: title short, desc long
    //          titleLabel.Text = "Something";
    //          descLabel.Text = "Lorem ipsum dolor sit amet.";
    // 5: title short, desc very long
    //          titleLabel.Text = "Something";
    //          descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    // result: X
    // 6: both long
    //          titleLabel.Text = "Lorem ipsum dolor sit amet.";
    //          descLabel.Text = "Lorem ipsum dolor sit amet.";
    // 7: both very long
    //          titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    //          descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    // 8: title long, desc very long
    //          titleLabel.Text = "Lorem ipsum dolor sit amet.";
    //          descLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    // 9: title very long, desc long
    titleLabel.Text = "Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.";
    descLabel.Text = "Lorem ipsum dolor sit amet.";
}

public override void ViewWillLayoutSubviews()
{
    base.ViewWillLayoutSubviews();
    if (titleLabelWidth.Constant + descWidth.Constant > container.Bounds.Size.Width)
    {
        //              if (descWidth.Constant > kDescMaxWidth){
        //                  descWidth.Constant = kDescMaxWidth;
        //              } else {
        container.RemoveConstraint(descRight);
        descLabel.Font = UIFont.SystemFontOfSize(0);
    //              }
    }
    else
    {
        container.AddConstraint(descRight);
    }
}

How can I solve no. 1/2 or the issue in general? Is it possible with auto layout alone?

Solution:

I completely took another approach (other constraints, ...). You can find my approach here.

1

1 Answers

0
votes

You can not pin description label to right, and add two width constraint to title and description, and check. To hide description label you can set zero font

if (titleWidth.constant + descWidth.constant > UIScreen.mainScreen().bounds.size.width
{
   if descWidth.constant > kdescMaxWidth
   {
      descWidth.constant = kDescMaxWidth
   }
   else
   {
      descLabel.font = UIFont.systemFontOfSize(0)
   }
}