使用 Auto Layout 创建具有多个不同自定义单元格的 UITableView 具有几乎相同的子视图

Posted

技术标签:

【中文标题】使用 Auto Layout 创建具有多个不同自定义单元格的 UITableView 具有几乎相同的子视图【英文标题】:Use Auto Layout to create UITableView with multiple different custom cells have almost the same subviews 【发布时间】:2015-10-29 20:40:31 【问题描述】:

我对这个应用程序的想法:创建一个用户列表,其中包含基于额外信息的职位。

我的编码:

为了显示列表,我使用带有动态表格视图单元格高度和自动布局的 UITableView。因为所有单元格都有几乎相同的子视图(例如:头像、全名、描述),所以我只想使用 1 个自定义 UITableViewCell 来显示用户信息。

这是 CustomCell.xib 的图像:Custom Cell + Extra Info Constraints

Extra Info 是 UIView,我将用每种工作类型的正确额外信息替换它(例如:摄影师的 UIImageView、显示作者书籍列表的 UITextField 等)。

当我从数据库或 API 加载用户数据时,我只用代码为 CustomCell 类分配每一行:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier(customCellIdentifier) as! CustomCell

    cell.userData = allUserData[indexPath.row] as NSDictionary
    return cell

这是CustomCell类的代码(我删除了设置头像,全名,描述的代码以使帖子更短):

class CustomCell: UITableViewCell 
    var userData: NSDictionary! 
        didSet 
            updateContent()
        
    

    function updateContent() 
        if let userType = userData["job_type"] as? String 
            if (userType == "Photographer") 
                // I think I was wrong with this code
                let photographerContentView = PhotographerView()
                photographerContentView.mainImage = UIImage(name: userData["image"] as String)
                self.extraInfoView = photographerContentView
             else 
                // I have a lot job types need to check
            
        
    

PhotographerView 是自定义 UIView,我将从带有设置自动布局的 xib 文件中加载它

class PhotographerView: UIView 
@IBOutlet var mainImage: UIImage!
var view: UIView!

override init(frame: CGRect) 
    super.init(frame: frame)
    xibSetup()


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    xibSetup()


func xibSetup() 
    view = loadViewFromNib()
    view.frame = bounds
    view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
    addSubview(view)


func loadViewFromNib() -> UIView 
    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: "PhotographerView", bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
    return view


问题:

我无法使用 Auto Layout 的新数据绘制 PhotographerContentView 并将其分配给 extraInfoView 我知道我可以通过为每个用户作业类型(如Dynamic Table View Cell Height and Auto Layout)创建一个新的自定义 UITableViewCell 来完成我的应用程序。但如果我这样做了,当我需要添加更多相同的子视图(如地址、电话号码等)时,我将不得不更改所有自定义 xib 文件。 我知道 UIView 在 Apple Docs 的 Auto Layout Guide 中没有内在内容大小,但我需要使用 Auto Layout 呈现自定义视图并将其添加到具有全屏宽度的父视图的方法(也许我需要以编程方式添加约束)。

我的问题的最佳解决方案是什么?你能给我一些示例代码吗?

谢谢!

【问题讨论】:

【参考方案1】:

您最好为每个独特的布局创建一种自定义单元格类型。否则,每次渲染单元格时都会对性能造成不必要的影响。尤其是这条线会相对昂贵,因为您每次都会从 XIB 重新加载视图:

let photographerContentView = PhotographerView()

您可以将通用代码/布局放在“抽象”基类中,并让您的具体单元类型扩展此类型。例如,您将有一个基础 JobCell 类,PhotographerCell 等将扩展。这样一来,您将从单元重用中获得更好的价值,并且您的代码可能会更简单。

正如我提到的elsewhere,您当然可以使用 MarkupKit 来帮助简化您的布局任务。您的PhotographerView 类可以完全按照您编写的方式实现,除了不是从XIB 加载视图,而是使用LMViewBuilderviewWithName:owner:root: 方法从标记文档加载它。使用 MarkupKit,您可以使用(可选嵌套的)布局视图来声明单元格的布局,而不是像在 XIB 文件中那样手动应用约束。例如:

https://dzone.com/articles/creating-custom-table-view-cells-in-markup-1

有关 MarkupKit 的更多信息,请参阅 GitHub 上的 project site。

【讨论】:

以上是关于使用 Auto Layout 创建具有多个不同自定义单元格的 UITableView 具有几乎相同的子视图的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义行布局的 ListView - Android

在 Interface Builder 中使用 Auto Layout 更改方向

css 这类似于主题安装,因为它具有多个专门针对不同layout.css关联的css页面。

Leanback 创建不同的自定义行视图

每行具有不同布局的Android ListView

Debugging Auto Layout:Ambiguous Layouts