具有静态表的动态类型和自定尺寸单元

时间:2015-10-05 17:56:50

标签: ios swift uitableview ios9

我有一个典型的主 - 细节应用程序,允许用户浏览滚动的对象列表,然后使用push segue钻取到任何特定对象的详细信息。滚动主列表是使用原型单元格构建的UITableView,详细信息场景是具有固定数量的部分和单元格的静态UITableView。

我想在我的应用程序中实现Dynamic Type和Self-Sizing Cells,以便用户可以更改基本字体大小。到目前为止,我已成功使用原型单元的滚动列表制作自调整单元格:通过使用自动布局,将每个标签中的行数设置为0,并设置tableView.rowHeight = UITableViewAutomaticDimension,每个原型单元格的高度增长或缩小以适应其中文本的大小。

但我在静态表视图中无法达到相同的效果。无论我使用自定义单元格还是内置单元格类型,字体都会增大/缩小,但单元格高度则不会。

所以我的问题实际上是两个问题:1)是否可以在静态表视图中实现自调整单元格,就像我对原型表视图一样? 2)如果第一个问题的答案为否,我如何编写测量静态表格视图单元格中标签高度的代码并适当调整单元格高度?

谢谢!

4 个答案:

答案 0 :(得分:19)

静态表视图返回在Interface Builder中设置的行高。 tableView.rowHeight设置似乎完全被忽略了。这显然是UIKit中的一个错误。

要解决此问题,只需覆盖-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath并返回UITableViewAutomaticDimension

答案 1 :(得分:4)

首先在你的班级中添加这两个功能

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

其次,为了使UITableViewAutomaticDimension工作,请确保已添加相对于单元容器视图的所有左,右,底部和顶部约束。另外不要忘记将标签的行数设置为零。

答案 2 :(得分:1)

由于这是一个静态表,你不能将单元格出列,所以你必须为它们创建IBOutlets,我将它们保存在这样的数组中:

@IBOutlet var cells: [UITableViewCell]!  

然后你必须实现heightForRowAtIndexPath并计算大小:

var rowSizes: [Int: CGFloat] = [:]

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return calculateHeightForCell(indexPath)
}

func calculateHeightForCell(indexPath: NSIndexPath) -> CGFloat {

    // check if we already calculated the height
    if let height = rowSizes[indexPath.row] {
        return height
    }

    // else, calculate it
    let cell = cells[indexPath.row]

    let size = cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)

    rowSizes[indexPath.row] = size.height

    return size.height
}

rowSizes就像一个缓存,它将保持行高,因此它们只会被计算一次。更改字体大小时,只需清空rowSizes并刷新表格,以便再次计算它们。

答案 3 :(得分:1)

我很感谢我昨天发布的问题的答案。不幸的是(可能是因为我自己作为iOS程序员缺乏经验)我无法使systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)方法工作。然而,在经过一些试验和错误之后,我发现了一种似乎有用的不同方法:

import UIKit

class MasterTVC: UITableViewController {
    @IBOutlet weak var staticCustomCellLabel: UILabel!

    //viewDidLoad
    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.estimatedRowHeight = 44.0

        staticCustomCellLabel.text = "This is the text for the static custom cell label; This is the text for the static custom cell label; This is the text for the static custom cell label"

        //Register handleDynamicTypeChange in observer: self
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleDynamicTypeChange:", name: UIContentSizeCategoryDidChangeNotification, object: nil)
    }

    //deinit
    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    //handleDynamicTypeChange
    //called when user changes text size in Settings > General > Accessibility > Larger Text
    //or Settings > Display & Brightness > Text Size
    func handleDynamicTypeChange(notification: NSNotification) {
        staticCustomCellLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)

        self.tableView.reloadData()
    }

    //tableView:heightForRowAtIndexPath
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
}

在Storyboard方面,设置从一个具有以下属性的Table View Controller开始:

  • 班级:MasterTVC(我的自定义班级);
  • 指定了初始视图控制器;
  • 内容:静态细胞;
  • 风格:分组
  • 章节:1。

科-1:

  • 行:1。

表视图单元格:

  • 样式:自定义(在此处使用“基本”会导致标签在“设置”中更改文本大小时消失);
  • 包含UILabel。

UILabel进一步配置为:

  • 字体:正文(动态类型样式);
  • 行:0;
  • 将内容视图的顶部,底部,左侧和右侧四边固定(我使用了相应的约束8,8,15,15);
  • 在自定义类代码中使用@IBOutlet。

这适用于我在Xcode 7和Swift 2中设计适用于iOS 9且启用了自动布局。有趣的是,如果你删除用于立即响应文本大小变化的NSNotificationCenter代码,自调整单元格代码基本上是两行:在viewDidLoad中设置estimatedRowHeight,并从tableView:heightForRowAtIndexPath返回UITableViewAutomaticDimension。

基于这些结果,我相信我原来问题的答案是:1)是; 2)见1。