微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UITableViewCell 基于可变内容的数据来自服务器

如何解决UITableViewCell 基于可变内容的数据来自服务器

我正在努力解决这个与 UITableViewCell 相关的问题。我有一个名为 UITableViewCell 的子类 ApplicantMessageCell,它有一些子视图、标签、图像视图等。它的顶部不依赖于状态。只需获取数据,更改标签文本和 imageView 的图像。

然而,对于底部的每个状态,我有完全不同的 UIView 的 3 个子类。我需要在 UIView底部显示相关的 ApplicationMessageCell 子类。但我找不到办法做到这一点。

  • 当然,我可以为每个州创建不同的 UITableViewCell 子类,但我不想走那条路,因为这只是一种情况,我还有更多。
  • 我尝试创建 UIView 的子类,它在调整自身大小时的行为类似于 UILabel。我无法做到。
  • 最后,我知道添加关于每个状态的每个 UIView 子类并明确显示一个/隐藏的其余部分可以解决这个问题,但我相信有更好的方法来实现这一点。

我没有分享任何代码,因为我认为这更像是一个理论问题,但如果有人提出要求,我当然会分享

提前致谢。

解决方法

这是一个简单的例子...

单元格类有两个标签,一个堆栈视图和三个不同高度的视图(红色、绿色、蓝色)用作“显示或不显示”视图:

  • 第一个标签被限制在顶部
  • 第二个标签被限制在第一个标签的底部
  • 堆栈视图被限制在第二个标签的底部到单元格的底部(当然是 contentView)

然后将三个不同高度的视图添加到堆栈视图中。据推测,对不同视图的子视图的约束将决定它们各自的高度。在本例中,它们被设置为 40、80 和 160。

查看以下代码中的注释 - 它应该是不言自明的:

class ApplicantMessageCell: UITableViewCell {
    
    let titleLabel = UILabel()
    let subLabel = UILabel()
    
    let stackView = UIStackView()
    
    let viewA = UIView()
    let viewB = UIView()
    let viewC = UIView()

    override init(style: UITableViewCell.CellStyle,reuseIdentifier: String?) {
        super.init(style: style,reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    func commonInit() -> Void {
        
        [titleLabel,subLabel,stackView].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            contentView.addSubview(v)
        }
        
        let g = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([
            
            // constrain titleLabel at top
            titleLabel.topAnchor.constraint(equalTo: g.topAnchor),titleLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor),titleLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor),// subLabel 8-pts below titleLabel
            subLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor,constant: 8.0),subLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor),subLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor),// stackView 8-pts below subLabel
            stackView.topAnchor.constraint(equalTo: subLabel.bottomAnchor,stackView.leadingAnchor.constraint(equalTo: g.leadingAnchor),stackView.trailingAnchor.constraint(equalTo: g.trailingAnchor),])
        
        // constrain stackView bottom to bottom
        // this will avoid auto-layout complaints while the cells are configured
        let c = stackView.bottomAnchor.constraint(equalTo: g.bottomAnchor)
        c.priority = .defaultHigh
        c.isActive = true
        
        // UI element properties
        stackView.axis = .vertical
        stackView.spacing = 8
        
        titleLabel.backgroundColor = .yellow
        subLabel.backgroundColor = .cyan
        
        viewA.backgroundColor = .red
        viewB.backgroundColor = .green
        viewC.backgroundColor = .blue

        // you'll be filling the views with something to determine their heights
        //  but here we'll just set them to 40,80 and 160 pts
        
        for (v,h) in zip([viewA,viewB,viewC],[40.0,80.0,160.0]) {
            stackView.addArrangedSubview(v)
            v.heightAnchor.constraint(equalToConstant: CGFloat(h)).isActive = true
        }
        
    }
    
    func fillData(_ top: String,sub: String,showViews: [Bool]) -> Void {
        titleLabel.text = top
        subLabel.text = sub
        // hide views as defined in showViews array
        for (v,b) in zip(stackView.arrangedSubviews,showViews) {
            v.isHidden = !b
        }
    }
    
}

struct ApplicationStruct {
    var title: String = ""
    var subTitle: String = ""
    var showViews: [Bool] = [true,true,true]
}

class FarukTableViewController: UITableViewController {

    var theData: [ApplicationStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        for i in 0..<20 {
            // cycle through views 1,2,3
            let b1 = i % 3 == 0
            let b2 = i % 3 == 1
            let b3 = i % 3 == 2
            let a = [b1,b2,b3]
            let d = ApplicationStruct(title: "Title \(i)",subTitle: "",showViews: a)
            theData.append(d)
        }
        
        // just to test,set more than one view visible in a couple cells
        theData[11].showViews = [true,false,true] // red and blue
        theData[12].showViews = [false,true] // green and blue
        theData[13].showViews = [true,false] // red and green
        theData[14].showViews = [true,true]  // all three

        tableView.register(ApplicantMessageCell.self,forCellReuseIdentifier: "cell")
    }

    override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return theData.count
    }
    
    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath) as! ApplicantMessageCell
        
        let d = theData[indexPath.row]
        
        let subStr = "showViews: " + d.showViews.description
        
        c.fillData(d.title,sub: subStr,showViews: d.showViews)
        
        return c
    }
    
}

第一行显示“ViewType1”的结果,第二行显示“ViewType2”,第三行显示“ViewType3”......然后行循环,直到我们点击行“Title 11”,我们设置了几行显示不止一种“子视图类型”:

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。