Swift UItableView 以编程方式自定义单元格(文档)?

Posted

技术标签:

【中文标题】Swift UItableView 以编程方式自定义单元格(文档)?【英文标题】:Swift UItableView Custom cell programmatically (documentation)? 【发布时间】:2015-03-11 23:34:36 【问题描述】:

我一直在尝试查找一些文档/教程/示例。关于如何在 swift 中进行高级表格视图。但除了没完没了的情节提要教程外,我还空无一物。

我这样做没有故事板和笔尖。除了 Apple 的 /poorly/ 解释库之外,我还找不到任何文档。

与其试图解释我在寻找什么,我将简单地展示下面的设计图片。

现在,我显然不是要你们为我创建这个。我只是希望你能给我一个链接到一些文档/教程。这就解释了如何使细胞不同?以及如何以编程方式在单元格中定位元素。

我一直在搜索单元格约束,但找不到?

我也研究了原型单元,但我只能找到与故事板相关的内容。

我希望你们能给我看一个类似的例子,一些文档/教程。

另一个重要的事情。我发现的任何未使用情节提要的文档。都使用了 tableViewController。

我正在使用带有 UITableView 的 UIViewController。不是 tableViewController,这似乎对它的工作方式产生了巨大的影响。

现在我只是想让原型工作。

下面是我的数据:

var objects = NSMutableArray()
var dataArray = [   ["stockName":"CTC Media Inc.","action":"sell","stockPrice":12.44],
                    ["stockName":"Transglobal Energy","action":"buy","stockPrice":39.40],
                    ["stockName":"NU Skin Enterprises","action":"buy","stockPrice":4.18]
                ]

不过,我只能从中获取并显示一条数据。

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    //return self.stocks.count
    return dataArray.count


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
    let object = dataArray[indexPath.row] as NSDictionary
    cell.textLabel?.text = object["stockName"] as? String

    return cell



func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) 
    println("You selected cell #\(indexPath.row)!")

但我仍然对如何定位这些数据或添加更多数据一无所知。比如右边的 UIView 有特定的背景色。在该 UIView 中将 UILabel 居中,在左侧添加一个 UIView,其中包含填充、单元格之间的自定义间距。等等等等。

任何帮助、文档链接、建议将不胜感激!

编辑:

我尝试在单元格内添加约束。 "cell.view.addConstraints("

但它当然会抛出一个错误,说“UITableViewCell 没有名为 view 的成员”。

至于如何在单元格内做约束,我还是一头雾水:(

编辑 2 - 进度:

我设法使用以下代码显示 UIView:

        testView.setTranslatesAutoresizingMaskIntoConstraints(false)
    testView.backgroundColor = UIColor.redColor()
    cell.addSubview(testView)

    var viewsDictionary = [ "testView":testView]
    cell.addConstraints(
        NSLayoutConstraint.constraintsWithVisualFormat(
            "H:|-50-[testView]|", options: nil, metrics: nil, views: viewsDictionary))
    cell.addConstraints(
        NSLayoutConstraint.constraintsWithVisualFormat(
            "V:|[testView]|", options: nil, metrics: nil, views: viewsDictionary))

但是,由于某种原因,它只显示在最后一个单元格中,而不是所有单元格中?

【问题讨论】:

您需要为价格容器创建一个视图。根据每行的操作,您可以使用if... else... 来决定背景图像。有关如何以编程方式添加约束的更多信息,您可以查看本教程。 thinkandbuild.it/learn-to-love-auto-layout-programmatically 感谢您的评论!我已经创建了我需要的所有对象,但是我无法将它们放入这些单元格中。我知道约束是如何工作的。但我不知道如何为单元格内的项目添加约束? tableview 是否为我创建了一个单元格对象?,是什么决定了单元格标签的放置位置?如何将这些对象添加到我的单元格中。 你看到this tutorial了吗?您是否尝试找到足够多的东西? 你好 Huy Nghia,感谢您的评论!是的,我看到了那个教程,但就像我能找到的其他教程一样,它是基于故事板的,单元的设计是通过故事板中的原型单元完成的,而不是以编程方式完成的 :( 看到这个问题的时候我笑了,我觉得你兄弟!因为我目前正在学习 swift 并进入那个头痛,并且没有仇恨我可以对这个故事板大白话表达更多,糟糕的文档,这些愚蠢的教程缺乏理解,好像所有的观察者都不知道什么类对象是!以及所有这些限制和苹果设计的“标准”……创造力发生了什么!以及这些可笑的愚蠢的长方法名称是什么......真的是苹果!感谢上帝,我来自 windows/linux/web 背景,编程很严肃! 【参考方案1】:

我只是玩了一点。即使所有颜色/字体都不完全正确,这将为您提供良好的起点。希望对你有帮助。

class Stock 
var name: String?
var action: String?
var price: String?
init(stockData: [String: AnyObject]) 
    if let n = stockData["stockName"] as? String 
        name = n
    
    if let a = stockData["action"] as? String 
        action = a
    
    if let p = stockData["stockPrice"] as? Float 
        price = NSString(format: "%.2f", p)
    


var backgroundColor: UIColor 
    if action == "sell" 
        return UIColor.greenColor()
    
    return UIColor.blueColor()


var typeColor: UIColor 
    if action == "sell" 
        return UIColor.blackColor()
    
    return UIColor.purpleColor()


var priceLabelColor: UIColor 
    if action == "sell" 
        return UIColor.redColor()
    
    return UIColor.greenColor()




class StockCell: UITableViewCell 

let padding: CGFloat = 5
var background: UIView!
var typeLabel: UILabel!
var nameLabel: UILabel!
var priceLabel: UILabel!

var stock: Stock? 
    didSet 
        if let s = stock 
            background.backgroundColor = s.backgroundColor
            priceLabel.text = s.price
            priceLabel.backgroundColor = s.priceLabelColor
            typeLabel.text = s.action
            typeLabel.backgroundColor = s.typeColor
            nameLabel.text = s.name
            setNeedsLayout()
        
    


override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    backgroundColor = UIColor.clearColor()
    selectionStyle = .None

    background = UIView(frame: CGRectZero)
    background.alpha = 0.6
    contentView.addSubview(background)

    nameLabel = UILabel(frame: CGRectZero)
    nameLabel.textAlignment = .Left
    nameLabel.textColor = UIColor.blackColor()
    contentView.addSubview(nameLabel)

    typeLabel = UILabel(frame: CGRectZero)
    typeLabel.textAlignment = .Center
    typeLabel.textColor = UIColor.whiteColor()
    contentView.addSubview(typeLabel)

    priceLabel = UILabel(frame: CGRectZero)
    priceLabel.textAlignment = .Center
    priceLabel.textColor = UIColor.whiteColor()
    contentView.addSubview(priceLabel)


required init(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


override func prepareForReuse() 
    super.prepareForReuse()



override func layoutSubviews() 
    super.layoutSubviews()
    background.frame = CGRectMake(0, padding, frame.width, frame.height - 2 * padding)
    typeLabel.frame = CGRectMake(padding, (frame.height - 25)/2, 40, 25)
    priceLabel.frame = CGRectMake(frame.width - 100, padding, 100, frame.height - 2 * padding)
    nameLabel.frame = CGRectMake(CGRectGetMaxX(typeLabel.frame) + 10, 0, frame.width - priceLabel.frame.width - (CGRectGetMaxX(typeLabel.frame) + 10), frame.height)


在您的视图控制器中

var stocks: [Stock] = []

override func viewDidLoad() 
    super.viewDidLoad()

    view.backgroundColor = UIColor.whiteColor()

    for stockData in dataArray 
        var stock = Stock(stockData: stockData)
        stocks.append(stock)
    


    tableView = UITableView(frame: view.bounds, style: .Grouped)
    tableView.delegate = self
    tableView.dataSource = self
    tableView.separatorStyle = .None
    tableView.registerClass(StockCell.self, forCellReuseIdentifier: NSStringFromClass(StockCell))
    view.addSubview(tableView)




func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return stocks.count


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    let cell = tableView.dequeueReusableCellWithIdentifier( NSStringFromClass(StockCell), forIndexPath: indexPath) as StockCell
    cell.stock = stocks[indexPath.row]
    return cell



func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
    return 70

自定义单元格

class StockCell: UITableViewCell 

let padding: CGFloat = 5
var background: UIView!
var typeLabel: UILabel!
var nameLabel: UILabel!
var priceLabel: UILabel!

var stock: Stock? 
    didSet 
        if let s = stock 
            background.backgroundColor = s.backgroundColor
            priceLabel.text = s.price
            priceLabel.backgroundColor = s.priceLabelColor
            typeLabel.text = s.action
            typeLabel.backgroundColor = s.typeColor
            nameLabel.text = s.name
            setNeedsLayout()
        
    


override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    backgroundColor = UIColor.clearColor()
    selectionStyle = .None

    background = UIView(frame: CGRectZero)
    background.alpha = 0.6
    contentView.addSubview(background)

    nameLabel = UILabel(frame: CGRectZero)
    nameLabel.textAlignment = .Left
    nameLabel.textColor = UIColor.blackColor()
    contentView.addSubview(nameLabel)

    typeLabel = UILabel(frame: CGRectZero)
    typeLabel.textAlignment = .Center
    typeLabel.textColor = UIColor.whiteColor()
    contentView.addSubview(typeLabel)

    priceLabel = UILabel(frame: CGRectZero)
    priceLabel.textAlignment = .Center
    priceLabel.textColor = UIColor.whiteColor()
    contentView.addSubview(priceLabel)


required init(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


override func prepareForReuse() 
    super.prepareForReuse()



override func layoutSubviews() 
    super.layoutSubviews()
    background.frame = CGRectMake(0, padding, frame.width, frame.height - 2 * padding)
    typeLabel.frame = CGRectMake(padding, (frame.height - 25)/2, 40, 25)
    priceLabel.frame = CGRectMake(frame.width - 100, padding, 100, frame.height - 2 * padding)
    nameLabel.frame = CGRectMake(CGRectGetMaxX(typeLabel.frame) + 10, 0, frame.width - priceLabel.frame.width - (CGRectGetMaxX(typeLabel.frame) + 10), frame.height)


【讨论】:

哇,我只是在寻找一些文档提示,或者有人告诉我可以为单元格创建一个类。但是,是的,完美的答案,谢谢一百万次!按照下面答案中的文档,我的做法有点不同。但这绝对是更好的答案。 @user100002 很高兴它有帮助。我有点匆忙,所以我忘了在重用时添加重置所有单元格子视图。您只需在 prepareForReuse 中将所有标签的文本设置为 nil 并将背景颜色设置为默认颜色(如果有的话)。 @HMHero - 非常感谢。这是对简单直接的设计模式的完美而简单的分解。感谢您的宝贵时间!

以上是关于Swift UItableView 以编程方式自定义单元格(文档)?的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将 UISearchController 添加到 swift 2 中的 UITableView 标头

swift UITableView的。以编程方式将表头添加到表部分

如何在 Swift 3 中以编程方式在 UIImageview 中添加 UITableview

Swift UItableView 以编程方式自定义单元格(文档)?

如何实现自定尺寸 UITableView?

以编程方式设置约束的问题 Swift