9
votes

I am trying to use AutoLayout in UITableViewCell with Multiple labels with percentage calculation. I want equal space between the labels but different widths. Also the width and space will differ in Portrait & Landscape mode as displayed in the following images.

Protrait Display

Landscape Display

I want the space to be 4 in Portrait and 8 in Landscape.

In Portrait Label1 Width - 50% Label2 Width - 20% Label3 Width - 30%

In Landscape Label1 Width - 50% Label2 Width - 15% Label3 Width - 20% Label4 Width - 15%

I have used horizontal spacing and top and bottom constraints but it is not resulting in proper width & space alignment. Also first row is header so it should not have disclosure indicator and remaining rows should have it. Any help would be appreciated.

Note : Its an universal application and Im using splitview in iPad. In portrait it should display 3 labels as in iPhone and in Landscape it should display 4 labels as mentioned above. Also my master view controller is visible always.

5
You need to use Size Classes to achieve this. Here is a pretty good tutorial from Ray WenderichEric Qian
Are you setting spacing and width constraints when orientation changes as what you want?Bhanupriya
@BhanuPriya I am not doing anything programmatically. I know I can achieve it via coding. But I am looking for some solution to be done in StoryBoard.Sasi
then @EricQian is right. You should go for Size ClassesBhanupriya
@EricQian that sample gives basic knowledge but that doesn't help me as my requirement is bit more complicated. Thanks for your help.Sasi

5 Answers

1
votes

As the size classes do not distinguish between iPad in portrait vs iPad in landscape, you can not use size classes. What you can do is in your xib you define all the constraints required as follows

  1. Define the constraint for space between labels and create the IBOutlet for it in your view class, lets name it “gapConstraint”.

  2. Define the constraint for width of each label which will be in proportion to superview’s width e.g. for bigger label constraint would be biggerlabel.width = superView.width*0.5.

  3. For labels where you want different width in portrait and landscape orientation, define two constraints for width (one for each orientation) and set the priority of one constraint to 750(high - lets say for portrait) and other to 500 (low - lets say for landscape). Create the outlets for all such constraints. We need to define two width constraint (one for portrait and one for landscape) for each label because the multiplier property of NSLayoutConstraint is readonly, hence once the multiplier is assigned we can not change its value. To workaround this, we define two constraints and in the code based on orientation we will activate the more appropriate constraint by changing the priorities.

Override UpdateConstraints method and in this method you can check the current device orientation. If the device orientation is portrait change the gapConstraint’s (created in point1) constant value to 4 while in landscape change the gapConstraint’s (created in point1) constant value to 8. For labels width; in portrait orientation change the priority of the portrait width constraint to 750 and lower down the priority of the landscape width constraint to 500 while in landscape orientation change the priority of the portrait width constraint to 500 while raise the priority of landscape width constraint to 750.

0
votes

you can achieve your desired layout by following ways

Method 1 : using VFL

  1. Whenever change in the orientation of device , your tableview automatically reloaded hence cellForRowIndexPath function will be called.
  2. Check for device orientation in cellForRowIndexPath 3.Remove all subview and its constraints 4.Add all subview again with required specification using VFL.

Method 2 : Using different Custom UItableViewCell

You can use different Custom UItableviewCell for each orientation.

-1
votes

First we come to the problem that you want space 4 in portrait and 8 in LandScape.

If you are well aware of size classes then use them , From the bottom of the story board select your desired size class (the size class that used in Portrait Mode) You can use size class "Compact Width regular Height" to set the constraints for all Iphones in Portrait Mode.

Now you set the horizontal spacing constraint between buttons, after placing the constraint of horizontal Spacing you can disable it from the size classes in which you do not want this constraint i.e. those size classes that are used in landscape mode.

To Disable the specific constraint for any size class, just simply select that constraint and then in attribute inspector you will see a check box named as "Installed" which means that this constraint is enabled for this size class. By default the "Installed" is for "Any Any" size class that means this constraint is applied to all size classes , simply uncheck that checkbox.

On the left side of that "Installed" checkBox there is a icon "+" which helps you enable or disable the constraint for specific size class , so select your desired size class from that icon and check the checkBox of that size class.See the Image1 enter image description here

Now add another horizontal spacing constraint for landscape and , disable it from "Any Any" size class and Enabled it for Any Width ,Compact Height that represents iphone in Landscape , now you have added two same constraint with different constants that works in different situations (One is portrait and other in Landscape).

Now Come towards your actual problem that you want size of your Labels to be proportional. Now just like constraints you can enable or disable views for different size classes , so drag four labels on story board and disable the fourth one for "Compact Width regular Height" size class.

To enable or disable the view in specific size class, select the label then use same "Installed" checkbox in attriburted inspector and disable the fourth label for "Compact Width regular Height" size class.

Now the only thing that is remaining is you want to set the different width for landscape and portrait. For this we have to set the two width constraint for each label (only fourth label has one width constraint) one for Portrait and other for Landscape.

Now set the width constraint for each label for portrait as you desire and enable these constraints only for "Compact Width regular Height" size class. So that they only work in Portrait.

Now from bottom of storty board change the size class to "Regular Width Compact height" and again place the width constraints on your labels this time with different constants. One thing you will observe that this time you are able to set the constraint for fourth label as this label is only visible is this size class.

And thats it :) Hope this will help you, tell me if that works or not.

-1
votes

Attached code is solution of your problem in iPhone. it`s working exact as your mention problem in iPhone in portrait and landscape mode. you can update this logic for your split-view in iPad. if you found any problem please comment here.

This problem is solved with size class in iOS 8 as per following logic.

1) Add reference view(yellow view) with total width - total space between label

As per your problem you mention above you want to add labels as per cell width. So for that you will req. reference width because you can`t use contentView as ref. so we have to take one extra view for this yellow view in my demo code. extra space are used to manage spacing b/w labels.

2) Then assign equal width with reference view by multiplier

Now you req. 50% width for 1st label so using multiplier logic we achieve it. for example if you want 100px first label then set "Ref. view" width 200. Same way i manage for other label to 20% and 30% of width ratio to ref. view.

3) For portrait mode add one more constraint for portrait size class

In portrait mode you req. only 3 labels so using size class assign width of 4th label to 0.

this all things done below code

Check out my code with size class

Download

-1
votes

to have equal spacing in UITableViewCell you can add views b/w labels and then set constarint to width and height of all labels to be same .

in potraitin the landscape