I'm trying to learn auto layout, finally thought I was getting the hang on it when this happened. I'm playing about with prototype cells and labels. I'm trying to have a
- Title,
titleLbl
- blue box in picture - Money,
moneyLbl
- green box in picture - Subtitle / Description,
subTitleLbl
- red box in picture
So far I have this:
What I want to achieve is:
- The green box should always display on 1 line fully
- The value inside the green box should be centred based on the blue box
- The blue box will take the remaining space (-8px for horizontal constraint between the 2) and display on multiple lines if necessary
- The red box should be underneath and display as many lines as needed.
As you can see this is nearly all working, with the exception of the example in the last row. I've tried to research this and from what I can gather it is something to do with the intrinsic content size. Many posts online recommend setting setPreferredMaxLayoutWidth
, i've done this in multiple places for the titleLbl
and it has had no effect. Only when hardcoding it to 180
did I get the results, but it also added whitespace / padding to the other blue boxes on top / underneath the text, greatly increasing the space between the red / blue boxes.
Here are my constraints:
Title:
Money:
Subtitle:
Based on tests i've run with other text samples it does appear to be using the width as shown in the storyboard, but any attempt to correct it isn't working.
I have created an ivar of the cell and used it to create the height of the cell:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
[sizingCellTitleSubMoney.titleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"title"]];
[sizingCellTitleSubMoney.subtitleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"subtitle"]];
[sizingCellTitleSubMoney.moneyLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"cost"]];
[sizingCellTitleSubMoney layoutIfNeeded];
CGSize size = [sizingCellTitleSubMoney.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height+1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MATitleSubtitleMoneyTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifierTitleSubTitleMoney];
if(!cell)
{
cell = [[MATitleSubtitleMoneyTableViewCell alloc] init];
}
cell.titleLbl.layer.borderColor = [UIColor blueColor].CGColor;
cell.titleLbl.layer.borderWidth = 1;
cell.subtitleLbl.layer.borderColor = [UIColor redColor].CGColor;
cell.subtitleLbl.layer.borderWidth = 1;
cell.moneyLbl.layer.borderColor = [UIColor greenColor].CGColor;
cell.moneyLbl.layer.borderWidth = 1;
[cell.titleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"title"]];
[cell.subtitleLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"subtitle"]];
[cell.moneyLbl setText:[[tableViewData objectAtIndex:indexPath.row] objectForKey:@"cost"]];
return cell;
}
I've tried setting setPreferredMaxLayoutWidth
inside the cell's layout subviews:
- (void)layoutSubviews
{
[super layoutSubviews];
NSLog(@"Money lbl: %@", NSStringFromCGRect(self.moneyLbl.frame));
NSLog(@"prefferredMaxSize: %f \n\n", self.moneyLbl.frame.origin.x-8);
[self.titleLbl setPreferredMaxLayoutWidth: self.moneyLbl.frame.origin.x-8];
}
log:
2014-04-30 21:37:32.475 AutoLayoutTestBed[652:60b] Money lbl: {{209, 20}, {91, 61}}
2014-04-30 21:37:32.475 AutoLayoutTestBed[652:60b] prefferredMaxSize: 201.000000
Which is what I would expect as there is 8px between the 2 elements and the console verifies this. It works perfectly on the first row no matter how much text I add to the blue box, which is the same as the storyboard, but any increase to the green box throws off the width calculation. I've tried setting this in the tableView:willDisplayCell
and the tableView:heightForRowAtIndexPath:
as well based on answers from other questions. But no matter what it just doesn't layout.
Any help, ideas or comments would be greatly appreciated
X
position from the green label before the green label was stretched out to fit its content. When using multiline labels in most cases you need to setsetPreferredMaxLayoutWidth
, I needed to calculate the displayed width of the green in order to calculate this value for the blue. Once that was set, it figured out the correct height – Sessions