如何排列不同的 UITableViewCell 图像和标签?

Posted

技术标签:

【中文标题】如何排列不同的 UITableViewCell 图像和标签?【英文标题】:How can I line up different UITableViewCell images and labels? 【发布时间】:2019-07-28 19:46:50 【问题描述】:

我在cellForRowAt 中所做的只是设置 UITableViewCell 的(无子类)imageView?.image 和 textLabel?.text 值(以及字体和颜色)。根据我的模型通过 SF Symbols 和文本设置图像。更详细地说,只有三种可能的单元格类型:工作区、“添加工作区”按钮和存档。

在下面的屏幕截图中,我用绿线演示了这些视图如何不完全按照逻辑方式排列。所有三种类型的单元格之间的文本都未对齐,并且(令人讨厌的)带有“添加”(+)指示符的方形图标的 SF 符号图像比标准图像略宽。

任何人都可以帮助我解决这个我只是想念的简单问题吗?我已经尝试使用约束将 imageViews 的纵横比设置为 1:1。这没有任何影响。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell: UITableViewCell

    if indexPath.section == 0 
        cell = tableView.dequeueReusableCell(withIdentifier: "workspace", for: indexPath)
        if indexPath.row == addWorkspaceRow 
            cell.imageView?.image = .addWorkspace
            cell.imageView?.tintColor = cell.tintColor
            cell.textLabel?.text = "Add Workspace"
            cell.textLabel?.textColor = cell.tintColor
            cell.accessoryType = .none
         else 
            let workspace = model.workspaces[indexPath.row]
            cell.imageView?.image = .workspace
            cell.imageView?.tintColor = .label
            cell.textLabel?.text = workspace.displayName
            cell.textLabel?.textColor = .label
            cell.accessoryType = .disclosureIndicator
        
     else 
        cell = tableView.dequeueReusableCell(withIdentifier: "archive", for: indexPath)
        cell.imageView?.image = .archive
        cell.imageView?.tintColor = .archive
        cell.textLabel?.text = "Archive"
        cell.textLabel?.textColor = .label
        cell.accessoryType = .disclosureIndicator
    

    cell.textLabel?.font = .preferredFont(forTextStyle: .body)

    return cell

【问题讨论】:

哥们,你只需要玩一些约束。将“添加”图像的约束设置为与默认(黑色)图像相同。 【参考方案1】:

我遇到了同样的事情,想在不使用自定义单元格的情况下解决它。但是没有子类化约束是很难配置的。

最终,我转而使用自定义单元格,它使用简单,如果您可能需要在 tableView 单元格中添加更多内容,自定义单元格是更好的选择。

我的代码,是的,我现在正在制作音乐播放器;)

class LibraryTableCell: UITableViewCell 
    var cellImageView = UIImageView()
    var cellLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: "libraryTableCell")
        
        cellImageView.translatesAutoresizingMaskIntoConstraints = false
        cellImageView.contentMode = .scaleAspectFit
        cellImageView.tintColor = .systemPink
        contentView.addSubview(cellImageView)
        
        cellLabel.translatesAutoresizingMaskIntoConstraints = false
        cellLabel.font = UIFont.systemFont(ofSize: 20)
        contentView.addSubview(cellLabel)
        
        NSLayoutConstraint.activate([
            cellImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            cellImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
            cellImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            cellImageView.widthAnchor.constraint(equalToConstant: 44),
            
            cellLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            cellLabel.leadingAnchor.constraint(equalTo: cellImageView.trailingAnchor, constant: 10),
            
        ])
    
    
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

class LibraryViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 
    var tableView = UITableView()
    let cellTitles = ["Playlists", "Artists", "Albums", "Songs", "Genres"]
    let imageNames = ["music.note.list", "music.mic", "square.stack", "music.note", "guitars"]

    override func viewDidLoad() 
        super.viewDidLoad()

        view.backgroundColor = .white
        title = "Library"
        
        navigationController?.navigationBar.prefersLargeTitles = true
        
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(LibraryTableCell.self, forCellReuseIdentifier: "libraryTableCell")
        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.rowHeight = 48
        view.addSubview(tableView)
        
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            tableView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20),
            tableView.heightAnchor.constraint(equalTo: g.heightAnchor, multiplier: 0.6)
        ])
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return cellTitles.count
    
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "libraryTableCell", for: indexPath) as? LibraryTableCell else 
            fatalError("Unable to dequeue libraryTableCell")
        
        
        cell.accessoryType = .disclosureIndicator
        
        let imageName = imageNames[indexPath.row]
        cell.cellImageView.image = UIImage(systemName: imageName)
        
        let title = cellTitles[indexPath.row]
        cell.cellLabel.text = title
        
        return cell
    
    
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) 
        cell.separatorInset = UIEdgeInsets(top: 8, left: 20, bottom: 8, right: 8)
    

【讨论】:

【参考方案2】:

更改UIImageViewcontentMode 属性就可以了:

cell.imageView?.contentMode = .scaleAspectFit

这是因为图像本身的尺寸不正确。

【讨论】:

我真的试过了,它并没有改变任何东西。即使将 imageView 的水平拥抱优先级设置为高也不起作用。 看来您使用的是 UITableViewCell 的原生 imageView,您是否尝试过对其进行子类化并实现自己的 imageView 并使用约束固定其大小? 我确信这会奏效。如果可能的话,我只是在避免那些(诚然很少量的)工作。感觉基类应该是可能的。 老实说,我总是直接对 UITableViewCell 进行子类化,只是为了增加自定义,以防万一我需要它。【参考方案3】:

您在 tableviewCell 中的图像是错误的 contentMode。这是由于标签布局错误的原因。

您可以选择解决该问题:

选项1

打开文件XIB tableviewCell并改变UIImage的内容模式

选项 2

您可以通过代码设置: yourUImage.contentMode = .scaleAspectFit

【讨论】:

您似乎在另一个(相同)答案上跳过了一些 cmets。这不适用于本机 UITableViewCell 类。它仅在您出于某种原因进行子类化时才有效。【参考方案4】:

我为您描述的问题寻找了很长时间的解决方案,但遗憾的是我没有找到任何解决方案。问题似乎是UITableViewCell 中的原生UIImageView。基本上有两种解决方法:

A) 将您用作表格视图单元格图标的所有图像调整为特定宽度(例如 30 和高度 44)。绘制这个空间并将图标居中(同时保持原始大小)

B) 习惯 Apple 的“您可以使用我们预先构建的解决方案,但如果您想改变一点点,您必须自下而上重新构建所有内容”——哲学只需使用自定义单元格来完成您在应用程序中所做的一切。使用自定义单元格,您可以简单地将 imageView 宽度设置为某个值。

我想知道他们是如何在 ios 邮件应用中解决这个问题的。

【讨论】:

以上是关于如何排列不同的 UITableViewCell 图像和标签?的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell如何加载Subview

重新排序单元格时如何在 UITableViewcell 内容视图中添加图像?

当 UIStackView 更改其排列的子视图时,UITableViewCell 不会调整大小

如何将 JSON 中返回的图像 URL 显示为 UITableViewCell 的缩略图

如何将origin多个图层的图例放到一个图上

如何通过触摸uitableviewcell中视频的视频缩略图上的按钮来播放视频?