iOS 8自定型单元,高度不断变化 [英] iOS 8 self sizing cells with changing height

查看:99
本文介绍了iOS 8自定型单元,高度不断变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用



tableview.rowHeight = UITableViewAutomaticDimension;

用于测试创建的单个 UIView 并将其添加到 cell.contentView 具有以下约束。 (使用砌体)

   - (void)updateConstraints {
UIView * superview = self.contentView;

if(!_didSetupConstraints){
[self.testView mas_makeConstraints:^(MASConstraintMaker * make){
make.top.equalTo(superview);
make.height.equalTo(@ 10.0f);
make.left.equalTo(superview);
make.right.equalTo(superview);
make.bottom.equalTo(superview);
}];

_didSetupConstraints = YES;
}

[super updateConstraints];
}

当我选择一行时,我想改变所选单元格的高度。我这样做:

   - (void)setSelected:(BOOL)选择动画:(BOOL)动画{
[super setSelected:selected animated:animated];

[self.testView mas_updateConstraints:^(MASConstraintMaker * make){
if(selected){
make.height.equalTo(@ 100);
}
else {
make.height.equalTo(@ 10);
}
}];

[UIView animateWithDuration:0.3f动画:^ {
[super layoutIfNeeded];
}];
}

似乎有效,但xcode投诉时出现以下错误:



无法同时满足约束条件。



然后问题是那个 contentView 正在创建一个高度constaint(因为默认情况下 contentView.translatesAutoresizingMaskIntoConstraints = YES; )。



因此,当首次运行updateConstraints时,系统将在 contentView 上创建一个等于<$ c $的高度约束c> 10.0f



之后当 setSelected ... 被调用时我改变了我的 testView的高度所以 testView.height (100.0f)和 contentView之间存在冲突.height (10.0f)并且因为 testView 附加到 contentView 的底部(为了使自定义单元格工作,它给出了错误。



我尝试设置 contentView.translatesAutoresizingMaskIntoConstraints = NO;

实现自动调整大小的正确方法是什么?它们的高度可以动态变化?

解决方案

这里有两个问题:



1。 AutoLayout消息:无法同时满足约束。



这是由于您事实造成的更新自定义视图的 height 约束,但不更新 contentView height 约束。因为您还将自定义视图的底部约束设置为contentView bottom ,系统无法满足两个约束:自定义视图不能有100的高度,同时连接到contentView的底部,而contentView仍然有10的高度。



这个问题很容易解决。您为contentView定义高度约束并将其设置为自定义视图的高度:

  [self.contentView mas_makeConstraints:^ (MASConstraintMaker * make){
make.height.equalTo(self.testView);
}];

这解决了这个问题。



<强> 2。更新单元格的高度



更新单元格高度并不容易,因为单元格高度由 UITableViewController处理而不是细胞本身。当然你可以改变单元格的高度,但只要 UITableViewController 没有给单元格足够的空间,你就不会看到新的单元格高度。您将看到现在更高的单元格将与下一个单元格重叠。



因此您需要一种方法来告诉 UITableViewController 它应该更新你的细胞的高度。你可以通过调用 reloadRowsAtIndexPaths:withRowAnimation:来做到这一点。这会重新加载单元格,并且可以很好地激活它。因此,单元格必须在 UITableViewController 上调用该方法。那里的挑战:A UITableViewCell 没有引用它的 UITableViewController (它不应该)。



你可以做的是子类 UITableViewCell 并给它一个闭包属性,它可以在高度发生变化时执行:

  class DynamicHeightTableViewCell:UITableViewCell {
var heightDidChange:(() - > Void)?
...

现在,当您将 UITableViewControllerDataSource 你设置它的闭包:

  func tableView(tableView:UITableView,cellForRowAtIndexPath indexPath:NSIndexPath) - > UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(DynamicHeightTableViewCell,forIndexPath:indexPath)
if let customCell = cell as? DynamicHeightTableViewCell {
customCell.heightDidChange = {[weak cell,weak tableView] in
if let currentIndexPath = tableView?.indexPathForCell(cell!){
tableView?.reloadRowsAtIndexPaths([currentIndexPath],withRowAnimation :.Automatic)
}
}
}

返回单元格
}

然后当单元格更改其高度时,您只需执行闭包,单元格将重新加载:

  func theFunctionWhereTheHeightChanges(){

//更改高度

heightDidChange?()
}


I created a tableview with self-sizing UITableViewCells using

tableview.rowHeight = UITableViewAutomaticDimension;

For testing a created a single UIView and added it to cell.contentView with the following constraints. (using masonry)

- (void)updateConstraints {
    UIView *superview = self.contentView;

    if (!_didSetupConstraints) {
        [self.testView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(superview);
            make.height.equalTo(@10.0f);
            make.left.equalTo(superview);
            make.right.equalTo(superview);
            make.bottom.equalTo(superview);
        }];

        _didSetupConstraints = YES;
    }

    [super updateConstraints];
}

When i select a row i like to change the height of the selected cell. I do this by:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    [self.testView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (selected) {
            make.height.equalTo(@100);
        }
        else {
            make.height.equalTo(@10);
        }
    }];

    [UIView animateWithDuration:0.3f animations:^{
        [super layoutIfNeeded];
    }];
}

It seems to work but, xcode complaints with the following error:

Unable to simultaneously satisfy constraints.

Then problem is that contentView is creating a height constaint on its own (because contentView.translatesAutoresizingMaskIntoConstraints = YES; per default).

So when updateConstraints is first run, the system will create a height constraint on contentView equal to 10.0f

afterwards when setSelected... is called i alter the height of my testView so theres a conflict between testView.height (100.0f) and contentView.height (10.0f) and since testView is attached to the bottom of contentView (in order for self-sizing cells to work) it gives and error.

I tried setting contentView.translatesAutoresizingMaskIntoConstraints = NO; but then it seems the UITableViewCell cant really figure out a proper size for the cell. (sometimes it too wide / too small) etc.

What is the proper way to implement self-sizing cells which can have their height changed dynamicly?

解决方案

There are two issues here:

1. The AutoLayout message: Unable to simultaneously satisfy constraints.

This is caused by the fact that you update your custom view's height constraint, but you do not update the contentView's height constraint. Because you also set the custom view's bottom constraint to the contentView bottom, the system cannot satisfy both contstraints: The custom view cannot have a height of 100 and at the same time be connected to the contentView's bottom while the contentView still has a height of 10.

The fix for this is quite easy. You define a height constraint for the contentView and set it to the height of your custom view:

[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(self.testView);
}];

This fixes the problem.

2. Updating the cell's height

Updating the cell height is not so easy because the cell heights are handled by the UITableViewController and not the cells themselves. Of course you can change the height of your cell, but as long as the UITableViewController does not give the cell enough space you won't see the new cell height. You will see that your now higher cell will overlap the next cell.

So you need a way to tell the UITableViewController that it should update the height of your cell. You can do that by calling reloadRowsAtIndexPaths:withRowAnimation:. That reloads the cell and also animates it nicely. So the cell somehow has to call that method on the UITableViewController. The challenge there: A UITableViewCell has no reference to its UITableViewController (and it shouldn't).

What you can do is subclass UITableViewCell and give it a closure property that it can execute whenever its height has changed:

class DynamicHeightTableViewCell: UITableViewCell {
    var heightDidChange: (() -> Void)?
    ...

Now, when you dequeue a cell in your UITableViewControllerDataSource you set its closure:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("DynamicHeightTableViewCell", forIndexPath: indexPath)
    if let customCell = cell as? DynamicHeightTableViewCell {
        customCell.heightDidChange = { [weak cell, weak tableView] in
            if let currentIndexPath = tableView?.indexPathForCell(cell!) {
                tableView?.reloadRowsAtIndexPaths([currentIndexPath], withRowAnimation: .Automatic)
            }
        }
    }

    return cell
}

And then when the cell changes its height you just execute the closure and the cell will be reloaded:

func theFunctionWhereTheHeightChanges() {

   // change the height

   heightDidChange?()
}

这篇关于iOS 8自定型单元,高度不断变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆