Defining UITableViewCell Heights with AutoLayout

Source: Internet
Author: User

In order to better use AutoLayout, in the development process found the need to use UITableViewCell, so crawling text online. Here is the translation

Original link: Point me to jump

Use different heights of Tableviewcell

[This article has introduced a simpler way for iOS8 to implement this approach]

I used to post articles about using dynamic types to increase the height of a cell (cell) that grows because of a larger font size. This, however, can be effective for tableview with the same height as cells (cell). In this article, I'll step through using AutoLayout to set different cell heights.

Before I start, I will thank Amy Worrall for this article because he inspired me to save a cell's properties so that I can use the tableView:heightForRowAtIndexPath: method to get the right size based on the content.

Huckleberry(I don't know how to translate Orz as source of content)

As the source data my content, I chose the first 15 chapters in Project Gutenberg-"The Adventures of Huckleberry Finn" and imported it into the plist file (each sentence as an item). This gave me nearly 2000 lines of different lengths of content. This is to show that each sentence in the corresponding tableview has a corresponding line number.

The height of each cell (cell) is required for a different number of rows, which is more noticeable when using larger font settings:

Begin

We use single View application as the basis for Xcode, and through certain changes, so that he has a tableviewcontroller, and embedded in a uinavigationcontroller, as shown below:

AutoLayout to set up a saved cell prototype

Add AutoLayout constraints to the label of the sentence, constraining left (leading), right (trailing), lower (bottom) space between the cell and the content. If you're not familiar with using AutoLayout in inderface Builder , there are ways to add constraints (I use Xcode 5.0.2 when writing this article). You can click the control button in storyboard to drag the label to the content containing it or right-drag in the left document outline and select left (leading), right (trailing), Down (bottom)

Depending on the location of your label, you may need to adjust your constraints to make sure that they have a default space. You can check the constraint and set the corresponding value in the detector on the right.

Add further constraints between two labels to set their vertical space to set the standard distance, repeating the above procedure to set the line number and the spatial constraints that contain the left, right, and upper spaces of his space. Interface Builder will error, you these two labels in the vertical direction of the ambiguous layout, you can see such a problem in the storyboard to the left of the document outline. If you click on the red button:

AutoLayout will not know that we will adjust the size of the content to ensure that each label is appropriate, so he wants to know a hint to understand which label should first shrink or expand to accommodate this space. In order to remove warning, we will set the line number (label) of the lower vertical compression resistance while increasing the vertical hug to be the size that he keeps in the We want

If you set the above constraint, he looks like this:

To create a class to customize a cell (cell)

Create a new OC class file into the project from the definition Tableviewcell, this class only created the Iboutlet prototype to hold these two labels

//UYLTextCell.h#import <UIKit/UIKit.h>  @interface uyltextcell : uitableviewcell @property(nonatomic,Weak)Iboutlet UILabel*numberlabel;@property(nonatomic,Weak)Iboutlet UILabel*linelabel;@end//UYLTEXTCELL.M#import "UYLTextCell.h"  @implementation Uyltextcell @end

Set this class in storyboard and connect the two labels in storyboard to the two Iboutlet, and set the identifier of it (UITableViewCell):

Set the DataSource of TableView

Create a private priviate prototype in the VC to save our data:

@interface UYLTableViewController ()@property (nonatomicstrongNSArray *sourceData;@end

These are stored in the plist file called: sourcedata.plist, which is imported into memory when SourceData's getter method is called.

- (NSArray *)sourceData{  if (!_sourceData)  {    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"SourceData" ofType:@"plist"];    _sourceData = [NSArray arrayWithContentsOfFile:filePath];  }  return _sourceData;}

This tableviewcontroller must be mandatory to implement 2 Uitableviewdatasource methods, the first to return the number of rows in a section, where we return the size of the SourceData array

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{  return [self.sourceData count];}

The second method is to return the TableView cell from a special place (translator Note: If no build is generated then from the memory pool, otherwise created)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:UYLCellIdentifier forIndexPath:indexPath];  [self configureCell:cell forRowAtIndexPath:indexPath];  return cell;}

The Uylcellidentifier variable inside is a static NSString class, which is to match the values we set in storyboard:

staticNSString *UYLCellIdentifier = @"UYLTextCell";

The Configurecell method will set the contents of the cell, and you will see why this is a good way to put the code in a separate, shorter way:

-(void) Configurecell: (UITableViewCell *) cell Forrowatindexpath: (Nsindexpath *) indexpath{if ([cell iskindofclass:[ Uyltextcell class]]) {Uyltextcell *textcell = (Uyltextcell *) cell;Textcell. Numberlabel. Text= [NSString stringwithformat:@"line%ld", (Long) Indexpath. Row+1];Textcell. Numberlabel. Font= [Uifont Preferredfontfortextstyle:uifonttextstylecaption1];Textcell. Linelabel. Text= [Self. SourceDataObjectatindex:indexpath. Row];Textcell. Linelabel. Font= [Uifont Preferredfontfortextstyle:uifonttextstylebody];}}

We have set two label fonts above, in case the user wants to change their font size.

Handling changes in dynamic text

TableView should be reloaded after the user has changed the font size. We will set Viewcontroller as an observer (Observer) in Viewdidload to observe uicontentsizecategorydidchangenotification messages.

- (void) viewdidload{[SuperViewdidload]; [[NsnotificationcenterDefaultcenter] Addobserver: SelfSelector@selector(didchangepreferredcontentsize:) Name:uicontentsizecategorydidchangenotification object:Nil];} - (void) dealloc{[[NsnotificationcenterDefaultcenter] Removeobserver: SelfName:uicontentsizecategorydidchangenotification object:Nil];} - (void) Didchangepreferredcontentsize: (nsnotification*) notification{[ Self. TableViewReloaddata];}
Calculate the cell's height

The row height of each row, we need to use the tableView:heightForRowAtIndexPath method. However, when this method is called, we have not set the contents of the cell, so it is difficult to set his height. As mentioned earlier, the solution cell is not loaded but should call his layout to determine the height he needs. So we've added Uyltextcell to save the prototype cell's content.

@interface UYLTableViewController ()...@property (nonatomic, strong) UYLTextCell *prototypeCell;@end

This cell prototype will request TableView in the Getter method to use a new cell in the queue.

- (UYLTextCell *)prototypeCell{  if (!_prototypeCell)  {    _prototypeCell = [selfdequeueReusableCellWithIdentifier:UYLCellIdentifier];  }  return _prototypeCell;}

The complete delegate to calculate the height of each row is as follows:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  [self configureCell:self.prototypeCell forRowAtIndexPath:indexPath];  [self.prototypeCell layoutIfNeeded];  CGSize size = [self.prototypeCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];  return size.height+1;}

Here are some of the content feeds:

    • Use configureCell the method to configure the cell based on the content to get the corresponding row. It is tableView:cellForRowAtIndexPath: configured just like a method before the cell is displayed.
    • Call Layoutifneed to lay out the cell immediately
    • Call the systemLayoutSizeFittingSize method to get the smallest size of the content, creating the appropriate constraints. (uilayoutfittingcompressedsize)
    • Remember to add a point size to the cell's split line.
Estimated cell Height

When we correctly set the size of the Tableviewcell in the previous instance project, there is still a big problem, and that is the TableView overload. In order to find this problem in real machine debugging, we changed the size of the text content in the background. On my test device, this completely blocked the user's interface, Zhejiang telephone for a few seconds to recalculate 2000 lines of text. Here's a workaround in iOS7:

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{  return UITableViewAutomaticDimension;}

This method will quickly return the height of the cell you need to estimate. Because this method is quick to estimate, it does not take much time. Generating an accurate estimate can also be dynamically selected based on the size of the different text.

If you are unable to correctly estimate the size of the text and want to keep the user from noticing that your table is being brushed, return to the system default value of Uitableviewautomaticdimension.

Problem and device direction change (March 2014 update)

As noted in the comments (I am grateful for the person who made it.) ), here is a problem that will cause the height of the error to be returned, and when the user device is dropped, the solution to this problem can be referred to Smileyborg's GitHub project. At the same time this GitHub project also pointed out my problem, the solution is to ensure that the cell width is set to the original width of the icon, and then calculate the height.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{  [self configureCell:self.prototypeCell forRowAtIndexPath:indexPath];  self.prototypeCell.bounds = CGRectMake(0.0.0f, CGRectGetWidth(self.tableView.bounds), CGRectGetHeight(self.prototypeCell.bounds));  ...  ...}

Second we need to call Layoutsubview in our custom cell class to set the maximum width we want in the multi-line label. These details are provided in the official documentation preferredMaxLayoutWidth .

This property will affect the size of the label when the remainder of the setting is applied. When displayed, if the content exceeds its range, the extra content will become one or more rows, thus increasing the label's height.

// UYLTextCell.m- (void)layoutSubviews{  [super layoutSubviews];  [self.contentView layoutIfNeeded];  self.lineLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.lineLabel.frame);}
Written in the last

This is a long article, I want to be useful to you, if you want the code you can find on GitHub

Defining UITableViewCell Heights with AutoLayout

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.