Ios 当我使用几种不同的显示方式时,UITableView单元格中是否可能有不同的高度?

Ios 当我使用几种不同的显示方式时,UITableView单元格中是否可能有不同的高度?,ios,iphone,swift,uitableview,autolayout,Ios,Iphone,Swift,Uitableview,Autolayout,我花了好几天的时间试图弄明白这一点,但似乎没有解决办法。我有一个非常基本的UITableView单元格,其中有两个标签。其中一个是一行,第二个是多行。第二个会有不同的高度。以下是我试图在UITableViewCells内部生成UIStackView的示例: 通过阅读数百篇SO帖子、数百篇博客、浏览苹果开发者网站,人们似乎可以用无限的方式来写这篇文章。在尝试了数百种不同的方式之后,我仍然无法像这样显示文本。我认为有些问题是因为我在一个UITableView中使用了3种不同的UITableView单

我花了好几天的时间试图弄明白这一点,但似乎没有解决办法。我有一个非常基本的UITableView单元格,其中有两个标签。其中一个是一行,第二个是多行。第二个会有不同的高度。以下是我试图在UITableViewCells内部生成UIStackView的示例:

通过阅读数百篇SO帖子、数百篇博客、浏览苹果开发者网站,人们似乎可以用无限的方式来写这篇文章。在尝试了数百种不同的方式之后,我仍然无法像这样显示文本。我认为有些问题是因为我在一个UITableView中使用了3种不同的UITableView单元格变体

以下是我最新尝试CellForRowatineXpath的代码:

这就产生了:


通过从tableView委托中简单实现heightForRowAtIndexPath,可以实现您想要实现的目标


如果您不确定什么单元格应该具有什么高度,您可以在运行时计算它。

您想要实现的目标可以通过从tableView委托中简单实现heightForRowAtIndexPath来实现


如果您不确定哪个单元格应该具有什么高度,您可以在运行时计算它。

为此,您需要使用自调整大小的表格视图单元格,即表格视图本身计算每个单元格显示其内容所需的高度,它可以通过两行代码实现:

步骤1:设置表视图的估计高度 tableView.estimatedRowHeight=33.0 步骤2:将tableView的行高设置为UITableViewAutomaticDimension tableView.rowHeight=UITableViewAutomaticDimension


以下是详细说明的教程

为此,您需要使用自调整大小的表格视图单元格,即表格视图本身计算每个单元格显示其内容所需的高度,这可以通过两行代码实现:

步骤1:设置表视图的估计高度 tableView.estimatedRowHeight=33.0 步骤2:将tableView的行高设置为UITableViewAutomaticDimension tableView.rowHeight=UITableViewAutomaticDimension


以下是详细说明的教程

我建议您不要为此使用堆栈视图。只需根据您的要求使用带有标签的自定义单元格,单元格将根据标签文本大小自动调整大小

检查,这里我附上了演示

输出:-

在viewdidload中

super.viewDidLoad()
        self.tblView.estimatedRowHeight = 100;
        self.tblView.rowHeight = UITableViewAutomaticDimension;
        self.tblView.setNeedsLayout()
        self.tblView.layoutIfNeeded()
不要忘记设置UILabel属性的Numberoflines=0

编辑:-如果您需要有关如何设置“约束到UILabel”的分步指南

检查此链接

编辑:-这里我已经采取了2个标签在细胞根据您的上述图像。就这样设置约束

标签1:-顶部、前导、高度和宽度根据您的要求


标签2:-顶部、底部,从标签1开始,从Superview开始,我建议您不要使用堆栈视图。只需根据您的要求使用带有标签的自定义单元格,单元格将根据标签文本大小自动调整大小

检查,这里我附上了演示

输出:-

在viewdidload中

super.viewDidLoad()
        self.tblView.estimatedRowHeight = 100;
        self.tblView.rowHeight = UITableViewAutomaticDimension;
        self.tblView.setNeedsLayout()
        self.tblView.layoutIfNeeded()
不要忘记设置UILabel属性的Numberoflines=0

编辑:-如果您需要有关如何设置“约束到UILabel”的分步指南

检查此链接

编辑:-这里我已经采取了2个标签在细胞根据您的上述图像。就这样设置约束

标签1:-顶部、前导、高度和宽度根据您的要求


标签2:-顶部、底部,从标签1开始,从Superview开始,我将遵循以下方法:

我将创建一个UIView子类作为包含单词标签和英语单词标签的容器视图。它更简单,代码独立,可维护

我将创建一个cell子类,并将此容器视图用作cell的content视图的子视图

然后我将使用CellForRowatinex中的整个设置

我还将在heightForRow中实现一些代码。为了使单元行在运行时保持动态高度,必须实现heightForRow方法

示例输出如下所示,它有一个UIImageView,两个UILabel和自定义灰色分隔符。此动态单元格高度基于UILabel中显示的图像高度和字符串长度:

我将分享一些代码片段给你帮助。下面是容器视图的一些概念代码示例:

容器视图最重要的约束设置如VenueViewContainer:UIView如下所示,对于您的情况,您可以水平而不是垂直地制作标签:

请确保为标签设置以下两个属性:

[lbl setNumberOfLines:0];

[lbl setLineBreakMode:NSLineBreakByWordWrapping];
在VenueViewContainer实现文件中,创建一个方法:

/*!This method is responsible for getting view dynamic height .*/

-(float)getViewHeight
{
[self layoutIfNeeded];

CGFloat maxY = 0;

for (UIView *subview in self.subviews) {

    maxY = MAX(CGRectGetMaxY(subview.frame),maxY);

}

return maxY;

}

/*!
 This method is responsible for set up Venue.
 @param venue object
 */

#pragma -mark data population

- (void)setupViewWithVenue:(Venue *)venue
{
    self.venueLabel.text = @"my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue last";

    self.sportName.text = @"my sport my sport my sport my sport my sport  my sport my sport my sport my sport my sport my sport my sport my sport my sport last";

    [self.venueImage setImageWithURLString:venue.venueImageUrl defaultImage:[UIImage imageNamed:@"venueinfo_main"]];

}
现在我们来谈谈自定义单元格。UITableViewCell子类。祈祷 内倾是这样的东西:

    @implementation VenueCellTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {

        self.selectionStyle = UITableViewCellSelectionStyleNone;

        [self setUpContainer];

        [self setUpConstraints];

    }

    return self;
}

/*!
 This method is responsible for set up Container
 */

-(void)setUpContainer{

    aViewContainer = [[VenueViewContainer alloc] initWithFrame:CGRectZero];

    [aViewContainer setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.contentView addSubview:aViewContainer];

}

/*!constraints setup*/

-(void)setUpConstraints{

    /*!
     dictionary of views for autolayout
     */
    NSMutableDictionary* views;

    views = [NSMutableDictionary new];

    UIView *parentView = self.contentView;

    views[@"aViewContainer"] = aViewContainer;

    views[@"parentView"] = parentView;

    NSArray* constraints;

    NSString* format;

    /*!
     layouting horizontal
     */
    format = @"|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];

    /*!
     layouting vertical
     */
    format = @"V:|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];
}
/*!
 This method is responsible for set up venue
 @param venue object
 */

- (void)setupCellWithVenue:(Venue *)venue
{
    [aViewContainer setupViewWithVenue:venue];
}
/*!
 This method is responsible to get cell height dynamically
 @param venue object
 */

-(float)getCellHeight
{
   return [aViewContainer getViewHeight];
}
这与你手机的定制有关

现在谈谈cellForRow和heightForRow:

在上述过程中,有几件事我不能使用:

一,。不使用自动行高计算属性。 2.不使用估计高度 3.不需要不必要的更新约束。 4.不使用自动首选最大布局宽度。 5.不使用systemLayoutSizeFittingSize应该对我有用但不起作用,我不知道它在内部做什么,而是我的方法——floatgetViewHeight在工作,我知道它在内部做什么

我已经和你们分享了最相关的代码块,我还没有在swift上工作过。但基本面还是一样。
谢谢

我将遵循以下方法:

我将创建一个UIView子类作为包含单词标签和英语单词标签的容器视图。它更简单,代码独立,可维护

我将创建一个cell子类,并将此容器视图用作cell的content视图的子视图

然后我将使用CellForRowatinex中的整个设置

我还将在heightForRow中实现一些代码。为了使单元行在运行时保持动态高度,必须实现heightForRow方法

示例输出如下所示,它有一个UIImageView,两个UILabel和自定义灰色分隔符。此动态单元格高度基于UILabel中显示的图像高度和字符串长度:

我将分享一些代码片段给你帮助。下面是容器视图的一些概念代码示例:

容器视图最重要的约束设置如VenueViewContainer:UIView如下所示,对于您的情况,您可以水平而不是垂直地制作标签:

请确保为标签设置以下两个属性:

[lbl setNumberOfLines:0];

[lbl setLineBreakMode:NSLineBreakByWordWrapping];
在VenueViewContainer实现文件中,创建一个方法:

/*!This method is responsible for getting view dynamic height .*/

-(float)getViewHeight
{
[self layoutIfNeeded];

CGFloat maxY = 0;

for (UIView *subview in self.subviews) {

    maxY = MAX(CGRectGetMaxY(subview.frame),maxY);

}

return maxY;

}

/*!
 This method is responsible for set up Venue.
 @param venue object
 */

#pragma -mark data population

- (void)setupViewWithVenue:(Venue *)venue
{
    self.venueLabel.text = @"my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue my venue last";

    self.sportName.text = @"my sport my sport my sport my sport my sport  my sport my sport my sport my sport my sport my sport my sport my sport my sport last";

    [self.venueImage setImageWithURLString:venue.venueImageUrl defaultImage:[UIImage imageNamed:@"venueinfo_main"]];

}
现在我们来谈谈自定义单元格。UITableViewCell子类。实现是这样的:

    @implementation VenueCellTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {

        self.selectionStyle = UITableViewCellSelectionStyleNone;

        [self setUpContainer];

        [self setUpConstraints];

    }

    return self;
}

/*!
 This method is responsible for set up Container
 */

-(void)setUpContainer{

    aViewContainer = [[VenueViewContainer alloc] initWithFrame:CGRectZero];

    [aViewContainer setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.contentView addSubview:aViewContainer];

}

/*!constraints setup*/

-(void)setUpConstraints{

    /*!
     dictionary of views for autolayout
     */
    NSMutableDictionary* views;

    views = [NSMutableDictionary new];

    UIView *parentView = self.contentView;

    views[@"aViewContainer"] = aViewContainer;

    views[@"parentView"] = parentView;

    NSArray* constraints;

    NSString* format;

    /*!
     layouting horizontal
     */
    format = @"|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];

    /*!
     layouting vertical
     */
    format = @"V:|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];
}
/*!
 This method is responsible for set up venue
 @param venue object
 */

- (void)setupCellWithVenue:(Venue *)venue
{
    [aViewContainer setupViewWithVenue:venue];
}
/*!
 This method is responsible to get cell height dynamically
 @param venue object
 */

-(float)getCellHeight
{
   return [aViewContainer getViewHeight];
}
这与你手机的定制有关

现在谈谈cellForRow和heightForRow:

在上述过程中,有几件事我不能使用:

一,。不使用自动行高计算属性。 2.不使用估计高度 3.不需要不必要的更新约束。 4.不使用自动首选最大布局宽度。 5.不使用systemLayoutSizeFittingSize应该对我有用但不起作用,我不知道它在内部做什么,而是我的方法——floatgetViewHeight在工作,我知道它在内部做什么

我已经和你们分享了最相关的代码块,我还没有在swift上工作过。但基本面还是一样。
感谢

表格视图单元格的高度由表格根据rowHeight属性决定,或者由表格视图委托中可选的func tableView\uTableView:UITableView、heightForRowAtIndexPath indexPath:NSIndexPath->CGFloat的返回值决定

程序员通过其frame属性为UITableViewCell设置的高度被忽略

因此,您需要通过编程计算出每个单元所需的高度。然后,您需要从每个单元格的表视图委托中实现可选的func tableView\utableview:UITableView,heightForRowAtIndexPath indexath:nsindepath->CGFloat

如果在显示表格视图时单元格大小发生变化,则需要:

使用UITableView中的重新加载数据重新加载表,或 使用func reloadrowsatindexpath\uindexpath:[nsindepath],使用rowAnimation动画:UITableViewRowAnimation from UITableView更新单元格。 编辑

实际上,因为您在视图中使用了约束,所以它应该在不使用``的情况下工作

尝试将if categories[parent]==words{..}中的代码替换为:

此外,我将使用两个不同的单元格类来完成此任务,而不是删除contentView中的视图


请告诉我进展如何

表格视图单元格的高度由表格根据rowHeight属性或表格视图委托中可选的func tableView\uTableView:UITableView、heightForRowAtIndexPath indexPath:NSIndexPath->CGFloat的返回值决定

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{


    NSString *firstLable = firstLable.text;
    NSString *secondLable = SecondLable.text;



    CGSize constraint = CGSizeMake(cell.frame.size.width/2, 20000.0f);
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    CGRect firstLableRect = [firstLable boundingRectWithSize:constraint
                       options:NSStringDrawingUsesLineFragmentOrigin
                       attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],      
                        NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];


    CGRect secondLableRect = [secondLable boundingRectWithSize:constraint
                              options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],                                       NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];


    float max = MAX(firstLableRect.size.height, secondLableRect.size.height) + 20;


    //20 for spacing 10 pc above and 10 pc below 


    return max ;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier=@"cellIdentifier";
    UITableViewCell *cell =  [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.selectionStyle =UITableViewCellSelectionStyleNone;



    NSString *lable1 = @"first label text";
    NSString *lable2 = @"second lable text";

    CGSize constraint = CGSizeMake(cell.frame.size.width/2-10, 20000.0f);
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    CGRect firstLableRect = [lable1 boundingRectWithSize:constraint
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],
                             NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];


    CGRect secondLableRect = [lable2 boundingRectWithSize:constraint
                              options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],                                       NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];



    UILabel *firstLable = [[UILabel alloc]initWithFrame:CGRectMake(5,10,constraint.width,firstLableRect.size.height)];
    [firstLable setLineBreakMode:NSLineBreakByWordWrapping];
    firstLable.minimumScaleFactor = 15.0f;
    [firstLable setNumberOfLines:0];
    firstLable.textAlignment = NSTextAlignmentLeft;
    [firstLable setFont:[UIFont fontWithName:@"your App font" size:16.0f]];
    [cell.contentView addSubview:firstLable];


    UILabel *secondLable = [[UILabel alloc]initWithFrame:CGRectMake(cell.frame.size.width/                       2+5,10,constraint.width,secondLableRect.size.height)];
    [secondLable setLineBreakMode:NSLineBreakByWordWrapping];
    secondLable.minimumScaleFactor = 15.0f;
    [secondLable setNumberOfLines:0];
    secondLable.textAlignment = NSTextAlignmentLeft;
    [secondLable setFont:[UIFont fontWithName:@"your App font" size:16.0f]];

    [cell.contentView addSubview:secondLable];

    return cell;
}
程序员通过其frame属性为UITableViewCell设置的高度被忽略

因此,您需要通过编程计算出每个单元所需的高度。然后,您需要从每个单元格的表视图委托中实现可选的func tableView\utableview:UITableView,heightForRowAtIndexPath indexath:nsindepath->CGFloat

如果在显示表格视图时单元格大小发生变化,则需要:

使用UITableView中的重新加载数据重新加载表,或 使用func reloadrowsatindexpath\uindexpath:[nsindepath],使用rowAnimation动画:UITableViewRowAnimation from UITableView更新单元格。 编辑

实际上,由于您在视图中使用了约束,因此在不使用usin的情况下应该可以工作 g```

尝试将if categories[parent]==words{..}中的代码替换为:

此外,我将使用两个不同的单元格类来完成此任务,而不是删除contentView中的视图

请告诉我进展如何

首先,除非你需要一个UIStackView用于你在问题中没有提到的其他目的,否则不要使用它们。如果不需要多行标签和动态高度单元,它们也可以正常工作,不会使代码变得不必要的复杂

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{


    NSString *firstLable = firstLable.text;
    NSString *secondLable = SecondLable.text;



    CGSize constraint = CGSizeMake(cell.frame.size.width/2, 20000.0f);
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    CGRect firstLableRect = [firstLable boundingRectWithSize:constraint
                       options:NSStringDrawingUsesLineFragmentOrigin
                       attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],      
                        NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];


    CGRect secondLableRect = [secondLable boundingRectWithSize:constraint
                              options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],                                       NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];


    float max = MAX(firstLableRect.size.height, secondLableRect.size.height) + 20;


    //20 for spacing 10 pc above and 10 pc below 


    return max ;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier=@"cellIdentifier";
    UITableViewCell *cell =  [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (!cell)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.selectionStyle =UITableViewCellSelectionStyleNone;



    NSString *lable1 = @"first label text";
    NSString *lable2 = @"second lable text";

    CGSize constraint = CGSizeMake(cell.frame.size.width/2-10, 20000.0f);
    NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
    paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
    CGRect firstLableRect = [lable1 boundingRectWithSize:constraint
                             options:NSStringDrawingUsesLineFragmentOrigin
                             attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],
                             NSParagraphStyleAttributeName: paragraphStyle.copy} context:nil];


    CGRect secondLableRect = [lable2 boundingRectWithSize:constraint
                              options:NSStringDrawingUsesLineFragmentOrigin
                              attributes:@{NSFontAttributeName:[UIFont fontWithName:@"Your App Font" size:16.0f],                                       NSParagraphStyleAttributeName: paragraphStyle.copy}context:nil];



    UILabel *firstLable = [[UILabel alloc]initWithFrame:CGRectMake(5,10,constraint.width,firstLableRect.size.height)];
    [firstLable setLineBreakMode:NSLineBreakByWordWrapping];
    firstLable.minimumScaleFactor = 15.0f;
    [firstLable setNumberOfLines:0];
    firstLable.textAlignment = NSTextAlignmentLeft;
    [firstLable setFont:[UIFont fontWithName:@"your App font" size:16.0f]];
    [cell.contentView addSubview:firstLable];


    UILabel *secondLable = [[UILabel alloc]initWithFrame:CGRectMake(cell.frame.size.width/                       2+5,10,constraint.width,secondLableRect.size.height)];
    [secondLable setLineBreakMode:NSLineBreakByWordWrapping];
    secondLable.minimumScaleFactor = 15.0f;
    [secondLable setNumberOfLines:0];
    secondLable.textAlignment = NSTextAlignmentLeft;
    [secondLable setFont:[UIFont fontWithName:@"your App font" size:16.0f]];

    [cell.contentView addSubview:secondLable];

    return cell;
}
据我所知,iOS中没有任何bug会阻止它工作。动态调整大小的单元格非常适合自动布局,您只需在单元格中设置正确的约束,并设置表视图的rowHeight和EstimateDrowEight属性

这对您不起作用的最可能原因是您没有在单元格中放置所有需要的约束。所需的限制是:

单元格内容(即多行标签)到单元格内容视图顶部的顶部约束 从单行标签到单元格左侧的前导约束 从多行标签到单元格右侧的尾随约束 从多行标签底部到单元格底部的底部约束 我想你错过了第四点

编辑

根据您的评论,您正在使用UIStackView,以便在单行和多行标签之间对齐顶部基线。由此,我了解到您希望标签按如下方式对齐:

    @implementation VenueCellTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {

        self.selectionStyle = UITableViewCellSelectionStyleNone;

        [self setUpContainer];

        [self setUpConstraints];

    }

    return self;
}

/*!
 This method is responsible for set up Container
 */

-(void)setUpContainer{

    aViewContainer = [[VenueViewContainer alloc] initWithFrame:CGRectZero];

    [aViewContainer setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.contentView addSubview:aViewContainer];

}

/*!constraints setup*/

-(void)setUpConstraints{

    /*!
     dictionary of views for autolayout
     */
    NSMutableDictionary* views;

    views = [NSMutableDictionary new];

    UIView *parentView = self.contentView;

    views[@"aViewContainer"] = aViewContainer;

    views[@"parentView"] = parentView;

    NSArray* constraints;

    NSString* format;

    /*!
     layouting horizontal
     */
    format = @"|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];

    /*!
     layouting vertical
     */
    format = @"V:|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];
}
/*!
 This method is responsible for set up venue
 @param venue object
 */

- (void)setupCellWithVenue:(Venue *)venue
{
    [aViewContainer setupViewWithVenue:venue];
}
/*!
 This method is responsible to get cell height dynamically
 @param venue object
 */

-(float)getCellHeight
{
   return [aViewContainer getViewHeight];
}
要获得这种行为,不需要视图。只需给出标签约束,即可允许多行标签定义单元格高度。下图显示了两个标签之间对齐的顶部基线,即每个标签的第一行对齐

请注意,左标签只需要前导和顶部约束,而右标签需要顶部、尾部和底部约束,因为它定义了单元格高度

总之,动态表视图单元格需要三件事:

tableView.rowHeight=UITableViewAutomaticDimension tableView.estimatedRowHeight=100 单元格内容必须具有前导、尾随、顶部和底部四个约束才能定义单元格高度。 首先,除非你需要一个UIStackView用于你在问题中没有提到的其他目的,否则不要使用它们。如果不需要多行标签和动态高度单元,它们也可以正常工作,不会使代码变得不必要的复杂

据我所知,iOS中没有任何bug会阻止它工作。动态调整大小的单元格非常适合自动布局,您只需在单元格中设置正确的约束,并设置表视图的rowHeight和EstimateDrowEight属性

这对您不起作用的最可能原因是您没有在单元格中放置所有需要的约束。所需的限制是:

单元格内容(即多行标签)到单元格内容视图顶部的顶部约束 从单行标签到单元格左侧的前导约束 从多行标签到单元格右侧的尾随约束 从多行标签底部到单元格底部的底部约束 我想你错过了第四点

编辑

根据您的评论,您正在使用UIStackView,以便在单行和多行标签之间对齐顶部基线。由此,我了解到您希望标签按如下方式对齐:

    @implementation VenueCellTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (self) {

        self.selectionStyle = UITableViewCellSelectionStyleNone;

        [self setUpContainer];

        [self setUpConstraints];

    }

    return self;
}

/*!
 This method is responsible for set up Container
 */

-(void)setUpContainer{

    aViewContainer = [[VenueViewContainer alloc] initWithFrame:CGRectZero];

    [aViewContainer setTranslatesAutoresizingMaskIntoConstraints:NO];

    [self.contentView addSubview:aViewContainer];

}

/*!constraints setup*/

-(void)setUpConstraints{

    /*!
     dictionary of views for autolayout
     */
    NSMutableDictionary* views;

    views = [NSMutableDictionary new];

    UIView *parentView = self.contentView;

    views[@"aViewContainer"] = aViewContainer;

    views[@"parentView"] = parentView;

    NSArray* constraints;

    NSString* format;

    /*!
     layouting horizontal
     */
    format = @"|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];

    /*!
     layouting vertical
     */
    format = @"V:|-0-[aViewContainer]-0-|";

    constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views];

    [parentView addConstraints:constraints];
}
/*!
 This method is responsible for set up venue
 @param venue object
 */

- (void)setupCellWithVenue:(Venue *)venue
{
    [aViewContainer setupViewWithVenue:venue];
}
/*!
 This method is responsible to get cell height dynamically
 @param venue object
 */

-(float)getCellHeight
{
   return [aViewContainer getViewHeight];
}
要获得这种行为,不需要视图。只需给出标签约束,即可允许多行标签定义单元格高度。下图显示了两个标签之间对齐的顶部基线,即每个标签的第一行对齐

请注意,左标签只需要前导和顶部约束,而右标签需要顶部、尾部和底部约束,因为它定义了单元格高度

总之,动态表视图单元格需要三件事:

tableView.rowHeight=UITableViewAutomaticDimension tableView.estimatedRowHeight=100 单元格内容必须具有前导、尾随、顶部和底部四个约束才能定义单元格高度。
这很容易。让我们一步一步走吧

一,。设置表格视图的EstimateDrowEight。这样可以轻松快速地加载单元格

2.将tableview的rowHeight属性设置为UITableViewAutomaticDimension。并且不使用heightForRowAtIndexPath

3.在两个标签上放置所有上下引导和尾随约束。这很重要

让我们来摇滚吧
无需使用stackView,这很简单。让我们一步一步走

一,。设置表格视图的EstimateDrowEight。这样可以轻松快速地加载单元格

2.将tableview的rowHeight属性设置为UITableViewAutomaticDimension。并且不使用heightForRowAtIndexPath

3.在两个标签上放置所有上下引导和尾随约束。这很重要

让我们来摇滚吧 不需要我们 e从iOS 9.1开始,stackView未实现intrinsicContentSize:因此表视图无法计算每个单元格的高度,因此它们以估计的高度显示

因此,理想情况下,您可以简化代码,这意味着您不需要使用堆栈视图,也不需要一直添加、删除、创建和销毁视图。解决方案的根本是不使用堆栈视图

如果需要,可以继续使用堆栈视图,但需要创建子类并实现intrinsicContentSize:。使用堆栈视图的原因不应该是必需的,因为您可以配置约束以匹配第一个基线。

从iOS 9.1开始,UIStackView没有实现intrinsicContentSize:因此表视图无法计算每个单元格的高度,因此它们以估计的高度显示

因此,理想情况下,您可以简化代码,这意味着您不需要使用堆栈视图,也不需要一直添加、删除、创建和销毁视图。解决方案的根本是不使用堆栈视图


如果需要,可以继续使用堆栈视图,但需要创建子类并实现intrinsicContentSize:。使用堆栈视图的原因不应该是必需的,因为您可以配置约束以匹配第一基线。

如其他人所述,请确保让表视图单元格动态调整大小:

tableView.estimatedRowHeight = <estimatedHeightValue>
tableView.rowHeight = UITableViewAutomaticDimension
但是您没有向autolayout提到此堆栈视图如何与单元格的内容视图和超级视图相关联。这对于动态调整大小的单元格是必要的,因为根据:

要定义单元格的高度,需要一个完整的约束链和具有定义高度的视图,以填充内容视图的上边缘和下边缘之间的区域。如果视图具有固有的内容高度,系统将使用这些值。如果没有,则必须向视图或内容视图本身添加适当的高度约束

标签具有内在内容,因此这没有问题,但为了完成完整的链,需要告诉autolayout堆栈视图的顶部和底部应等于内容视图的顶部和底部,如下所示:

// stackView.superview! is the table view cell's content view
stackView.topAnchor.constraintEqualToAnchor(stackView.superview!.topAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(stackView.superview!.bottomAnchor).active = true
在将堆栈视图添加到内容视图之后再添加这两行,我相信您会成功的

仅供参考,即使您像现在这样以编程方式将这些视图添加到单元格中,您仍然可以使用Xcode强大的捕获视图层次结构功能在视觉上很好地调试布局问题。当应用程序从Xcode运行时,单击菜单项“调试>查看调试>捕获视图层次结构”。很容易看到视图层次结构中发生了什么,激活了哪些约束,消失的视图去了哪里,等等


第二,每次单元格出现在屏幕上时,销毁视图,然后重新实例化新视图,这会显著降低滚动时的性能。您将尽可能地从已出列的单元格中获取现有视图,并使用该行的适当内容重新分配其内容,从而避免视图实例化。您仍然可以使用纯粹的编程方式来完成这项工作,方法是对单元格进行排队,并为每个可能的视图调用cell.viewWithTag。如果该方法返回nil,则对单元格的视图进行一次性实例化,并为视图提供一个标记,例如1表示wordLabel,2表示englishWordLabel。然后将行的适当内容分配给视图。

如其他人所述,请确保让表视图单元格动态调整大小:

tableView.estimatedRowHeight = <estimatedHeightValue>
tableView.rowHeight = UITableViewAutomaticDimension
但是您没有向autolayout提到此堆栈视图如何与单元格的内容视图和超级视图相关联。这对于动态调整大小的单元格是必要的,因为根据:

要定义单元格的高度,需要一个完整的约束链和具有定义高度的视图,以填充内容视图的上边缘和下边缘之间的区域。如果视图具有固有的内容高度,系统将使用这些值。如果没有,则必须向视图或内容视图本身添加适当的高度约束

标签具有内在内容,因此这没有问题,但为了完成完整的链,需要告诉autolayout堆栈视图的顶部和底部应等于内容视图的顶部和底部,如下所示:

// stackView.superview! is the table view cell's content view
stackView.topAnchor.constraintEqualToAnchor(stackView.superview!.topAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(stackView.superview!.bottomAnchor).active = true
在将堆栈视图添加到内容视图之后再添加这两行,我相信您会成功的

仅供参考,即使您像现在这样以编程方式将这些视图添加到单元格中,您仍然可以使用Xcode强大的捕获视图层次结构功能在视觉上很好地调试布局问题。当应用程序从Xcode运行时,单击菜单项“调试>查看调试>捕获视图层次结构”。很容易看到视图层次结构中发生了什么,激活了哪些约束,消失的视图去了哪里,等等

第二个FYI
,每次单元格出现在屏幕上时,销毁视图,然后重新实例化新视图会显著降低滚动时的性能。您将尽可能地从已出列的单元格中获取现有视图,并使用该行的适当内容重新分配其内容,从而避免视图实例化。您仍然可以使用纯粹的编程方式来完成这项工作,方法是对单元格进行排队,并为每个可能的视图调用cell.viewWithTag。如果该方法返回nil,则对单元格的视图进行一次性实例化,并为视图提供一个标记,例如1表示wordLabel,2表示englishWordLabel。然后为视图指定适当的行内容。

我一次又一次地遇到类似的自动布局问题。我不经常使用StackView,我通常在需要添加/删除或显示/隐藏视图时使用它们。如果不这样做,我选择只使用约束。我觉得StackView在很多情况下都有很多问题。尤其是在锡伯银行。我不知道为什么会有不同,但它似乎总是导致警告,我不能删除,当使用超过一个标签

尽管如此,autoLayout也并非没有问题,它们主要围绕preferredMaxLayoutWidth展开

为了解释,为了让AutouLayout计算标签的高度,它需要知道标签的宽度。如果将多个标签放在一起,尤其是在tableViewCell中,这会导致各种问题

几天后,我提出并随后回答了一个相关问题

我所做的是添加了UILabel的子类,该子类始终确保在修改标签时更新preferredMaxLayoutWidth。我最近更新了iOS 8、iOS 9和一个单独的问题,我发现了模态视图

因此,整个步骤是:

创建UIlabel子类。 创建一个单元格,其中标签不在视图中放置。 根据您的用例,将一个或两个标签的行数设置为0。 将标签设置为子类的类型。 实现EstimatedHeightForrowatineXpath方法来猜测可能的高度。 计算RowAtIndexPath中单元格的内部高度。 为了计算高度,您可以使用类似这样的东西,我已经将其抽象为一个助手方法,我可以更容易地重用它

// Set the cell data first, i.e. the label text, any programmatic  fonts, font sizes etc.


if let tempCell = cell as? UITableViewCell
{
    tempCell.width = tableView.width

    let size = tempCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

    if tableView.separatorStyle != UITableViewCellSeparatorStyle.None
    {
        // +0.5 for seperator
        return size.height+0.5
    }
    else
    {
        return size.height
    }
}
我将其与一个协议结合起来,该协议使所有单元格都可以在一个字典中设置它们的数据。然后,我可以总结这个方法,接收并传入一个字典,并反复重用代码


这对我来说已经天衣无缝地工作了很长一段时间。

我一次又一次地遇到类似的自动布局问题。我不经常使用StackView,我通常在需要添加/删除或显示/隐藏视图时使用它们。如果不这样做,我选择只使用约束。我觉得StackView在很多情况下都有很多问题。尤其是在锡伯银行。我不知道为什么会有不同,但它似乎总是导致警告,我不能删除,当使用超过一个标签

尽管如此,autoLayout也并非没有问题,它们主要围绕preferredMaxLayoutWidth展开

为了解释,为了让AutouLayout计算标签的高度,它需要知道标签的宽度。如果将多个标签放在一起,尤其是在tableViewCell中,这会导致各种问题

几天后,我提出并随后回答了一个相关问题

我所做的是添加了UILabel的子类,该子类始终确保在修改标签时更新preferredMaxLayoutWidth。我最近更新了iOS 8、iOS 9和一个单独的问题,我发现了模态视图

因此,整个步骤是:

创建UIlabel子类。 创建一个单元格,其中标签不在视图中放置。 根据您的用例,将一个或两个标签的行数设置为0。 将标签设置为子类的类型。 实现EstimatedHeightForrowatineXpath方法来猜测可能的高度。 计算RowAtIndexPath中单元格的内部高度。 为了计算高度,您可以使用类似这样的东西,我已经将其抽象为一个助手方法,我可以更容易地重用它

// Set the cell data first, i.e. the label text, any programmatic  fonts, font sizes etc.


if let tempCell = cell as? UITableViewCell
{
    tempCell.width = tableView.width

    let size = tempCell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

    if tableView.separatorStyle != UITableViewCellSeparatorStyle.None
    {
        // +0.5 for seperator
        return size.height+0.5
    }
    else
    {
        return size.height
    }
}
我将其与一个协议结合起来,该协议使所有单元格都可以在一个字典中设置它们的数据。然后,我可以总结这个方法,接收并传入一个字典,并反复重用代码


这对我来说已经天衣无缝地工作了很长一段时间。

为什么不创建一个自定义子类并在其中设置布局约束呢?是的,也许一旦我完成了所有设置,想干掉代码..为什么要使用stackview?要实现多行标签或计划在多行标签下方垂直添加更多视图?@dineshudinwal要将两个UILabel与其顶基线对齐,为什么不创建自定义子类并设置布局约束

在那里?是的,也许一旦我准备好了,想干掉代码..你为什么要用stackview?要实现多行标签或计划在多行标签下方垂直添加更多视图?@dineshudinwal要将两个UILabel与其顶基线对齐,因为我是3个不同的UITableView单元格,每个单元格的高度要求完全不同,我肯定需要在运行时进行计算。有人如何在运行时计算单元格高度?我认为更大的问题是,iOS7和iOS8中存在一个错误,他们无法识别多行UILabel的intrinsicContentSize。。如本文所述,但这些答案都不起作用。最有效的方法是将设置单元格标签的代码移动到新方法中,然后在HeightForRowatinex中,调用设置单元格的方法,然后可以调用cell.contentView.SystemLayoutSizeFittingSizeUILayoutFittingCompressedSizeBe,因为我是3个不同的UITableView单元格,每个都有完全不同的高度要求,我肯定需要在运行时进行计算。有人如何在运行时计算单元格高度?我认为更大的问题是,iOS7和iOS8中存在一个错误,他们无法识别多行UILabel的intrinsicContentSize。。如本文所述,但这些答案都不起作用。最有效的方法是将设置单元格标签的代码移动到一个新方法中,然后在HeightForRowatinex中,调用设置单元格的方法,然后可以调用cell.contentView.SystemLayoutSizeFittingSizeUILayoutFittingCompressedSize。我现有的代码中包含所有这些内容。UIStackView和UITableView单元格不尊重或不承认多行UILabelI的intrinsicContentSize,我在现有代码中有这些。UIStackView、UITableView和UITableView单元格不承认或不承认多行UILabelThanks的内部内容大小以获取详细响应。链接和附加文件中存在故障,导致其无法运行。我最初确实在没有UIStackView的情况下尝试了此操作,目前在我的viewDidLoad中有所有这些设置,但它们也不起作用。@Trip您需要正确设置约束bro。你查过我的第二个链接了吗?步骤bt步骤约束到UILabel?我缺少哪些约束?根据我的经验,在contentView、单元格及其任何子视图中,我设置的任何约束(宽度、高度、前导、尾随、顶部、底部)都会被忽略。也许我遗漏了什么?你能给我看看你的第二个标签吗?您在tableview中设置了numberofline=0吗?谢谢您的详细回复。链接和附加文件中存在故障,导致其无法运行。我最初确实在没有UIStackView的情况下尝试了此操作,目前在我的viewDidLoad中有所有这些设置,但它们也不起作用。@Trip您需要正确设置约束bro。你查过我的第二个链接了吗?步骤bt步骤约束到UILabel?我缺少哪些约束?根据我的经验,在contentView、单元格及其任何子视图中,我设置的任何约束(宽度、高度、前导、尾随、顶部、底部)都会被忽略。也许我遗漏了什么?你能给我看看你的第二个标签吗?您在tableview中设置了numberofline=0吗?我正在使用tableview.EstimateDrowEight=200;tableView.rowHeight=UITableViewAutomaticDimension,但基于您所说的。。也许我不应该这样做,在heightForRowAtIndexPath中手动计算每个单元格?啊,我看到你有或在那里。是的。。都试过了。什么都不管用您是否确实尝试过在heightForRowAtIndexPath中以编程方式计算高度?你确定你的计算结果是正确的吗?很抱歉反应太晚了。我继续写了一些程序来实现这一点,但看起来即使我能得到高度,它也会破坏我其他单元格的所有约束。我认为这是苹果的另一个巨大缺陷,滚动时单元格中的约束会被破坏。另外,将对齐方式改为.fill也不会影响单元格的高度。它仍然无法识别我正在使用的高度tableView.EstimateDrowEight=200;tableView.rowHeight=UITableViewAutomaticDimension,但基于您所说的。。也许我不应该这样做,在heightForRowAtIndexPath中手动计算每个单元格?啊,我看到你有或在那里。是的。。都试过了。什么都不管用您是否确实尝试过在heightForRowAtIndexPath中以编程方式计算高度?你确定你的计算结果是正确的吗?很抱歉反应太晚了。我继续写了一些程序来实现这一点,但看起来即使我能得到高度,它也会破坏我其他单元格的所有约束。我认为这是苹果的另一个巨大缺陷,滚动时单元格中的约束会被破坏。另外,将对齐方式改为.fill也不会影响单元格的高度。它仍然不承认高度感谢您的详细回复。我的问题是关于对齐两个UIL标签
,一个具有动态高度的。你的是关于动态高度的。我的有3个单独的CellIdentifier可能导致此问题。您的仅使用一个。感谢您的详细回复。我的问题是关于对齐两个UILabel,其中一个具有动态高度。你的是关于动态高度的。我的有3个单独的CellIdentifier可能导致此问题。你的答案只能用一个。你的答案可以用MarkDown吗?你的答案可以用MarkDown?单词吗。决定放弃使用stackView。现在添加顶部和底部约束。我已经将其设置为自动标注.Word。决定放弃使用stackView。现在添加顶部和底部约束。我已经把它设置成自动尺寸标注了。你完全正确。我想要UIStackView的唯一原因是,这是我唯一能想到的将两个UILabel与其顶部基线对齐的方法。你能想出其他方法吗?检查我更新的答案,这显示了在单线和多线标签之间对齐第一行所需的约束,如果我理解正确,这就是你想要的。耶,你完全正确。我想要UIStackView的唯一原因是,这是我唯一能想到的将两个UILabel与其顶部基线对齐的方法。你能想出其他方法吗?检查我更新的答案,这显示了在单行和多行标签之间对齐第一行所需的约束,如果我理解正确,这就是你想要的。