ios - AutoLayout:多行标签和固定大小的按钮

标签 ios autolayout uikit uilabel snapkit

我正在尝试从 Kayak 应用复制以下布局: kayak app

布局由 UICollectionViewCell 和一个 UILabel 和一个 INUIAddVoiceShortcutButton 组成。

但是,在我的实现中,当文本不适合时,标签不会强制单元格进一步拉伸(stretch): Clipping text

我怎样才能使 UICollectionViewCell 随标签一起增长,而不是将标签截断为单元格的大小?

单元格的完整代码:

final class AddToSiriCell: CornerMaskCellBase {
  lazy var button: INUIAddVoiceShortcutButton = {
    let b = INUIAddVoiceShortcutButton(style: .whiteOutline)
    return b
  }()

  lazy var textLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    return label
  }()

  override init(frame: CGRect) {
    super.init(frame: frame)
    configureViews()
  }

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

  private func configureViews() {
    textLabel.text = "View balance with your pre-recorded Siri Command .View balance with your pre-recorded Siri Command  View balance with your pre-recorded Siri Command View balance with your pre-recorded Siri Command "
    contentView.backgroundColor = .white
    [button, textLabel].forEach(contentView.addSubview)
    button.snp.makeConstraints { (make) in
      make.top.bottom.trailing.equalTo(contentView.layoutMarginsGuide)
    }

    textLabel.snp.makeConstraints { (make) in
      make.top.bottom.leading.equalTo(contentView.layoutMarginsGuide).priority(.required)
      make.trailing.equalTo(button.snp.leading).priority(.required)
    }
  }
}

更新 1:添加了固定宽度的“基类” 这是我用于 UICollectionView 中所有单元格的基类:

import UIKit
import SnapKit

class AutoSizingCellBase: UICollectionViewCell {
  override class var requiresConstraintBasedLayout: Bool {
    return true
  }

  private final var widthConstraint: Constraint?

  override init(frame: CGRect) {
    super.init(frame: frame)
    contentView.layoutMargins = UIEdgeInsets(padding: 14)
  }

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

  override func updateConstraints() {
    if widthConstraint == nil {
      if let window = window {
        let width = window.bounds.width - 16
        contentView.snp.makeConstraints { (make) in
          widthConstraint = make.width.equalTo(width).priority(.required).constraint
        }
      }
      contentView.translatesAutoresizingMaskIntoConstraints = true
    }
    super.updateConstraints()
  }
}

最佳答案

将标签和按钮的顶部约束设置为 greaterThanOrEqual

将标签和按钮的底部约束设置为 lessThanOrEqual


编辑:

两者都应该有 centerY 约束。

这是一个完整的示例(我不在 iOS 12 上,所以我使用标准 UIButton 代替 INUIAddVoiceShortcutButton)。我还将标签的背景设置为青色,以便于查看其结果帧:

//
//  SnapTableViewController.swift
//
//  Created by Don Mag on 10/19/18.
//

import UIKit

class SnapCell: UITableViewCell {

    lazy var theButton: UIButton = {
        let b = UIButton()
        b.backgroundColor = .yellow
        b.setTitle("Add to Siri", for: .normal)
        b.setTitleColor(.black, for: .normal)
        b.layer.cornerRadius = 8
        b.layer.borderColor = UIColor.black.cgColor
        b.layer.borderWidth = 1
        return b
    }()

    lazy var theLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.backgroundColor = .cyan
        return label
    }()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        configureViews()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configureViews()
    }

    func configureViews() -> Void {

        contentView.backgroundColor = .white
        [theButton, theLabel].forEach(contentView.addSubview)

        // constrain button size to 120 x 40
        theButton.snp.makeConstraints { (make) in
            make.width.equalTo(120)
            make.height.equalTo(40)
        }

        // constrain button to trailing margin
        theButton.snp.makeConstraints { (make) in
            make.trailing.equalTo(contentView.layoutMarginsGuide)
        }

        // constrain button top to greaterThanOrEqualTo margin
        theButton.snp.makeConstraints { (make) in
            make.top.greaterThanOrEqualTo(contentView.layoutMarginsGuide)
        }

        // constrain button bottom to lessThanOrEqualTo margin
        theButton.snp.makeConstraints { (make) in
            make.bottom.lessThanOrEqualTo(contentView.layoutMarginsGuide)
        }

        // also constrain button to centerY
        theButton.snp.makeConstraints { (make) in
            make.centerY.equalTo(contentView.snp.centerY)
        }

        // constrain label to leading margin
        theLabel.snp.makeConstraints { (make) in
            make.leading.equalTo(contentView.layoutMarginsGuide)
        }

        // constrain label top to greaterThanOrEqualTo margin
        theLabel.snp.makeConstraints { (make) in
            make.top.greaterThanOrEqualTo(contentView.layoutMarginsGuide)
        }

        // constrain label bottom to lessThanOrEqualTo margin
        theLabel.snp.makeConstraints { (make) in
            make.bottom.lessThanOrEqualTo(contentView.layoutMarginsGuide)
        }

        // also constrain label to centerY
        theLabel.snp.makeConstraints { (make) in
            make.centerY.equalTo(contentView.snp.centerY)
        }

        // constrain label trailing to 8-pts from button leading
        theLabel.snp.makeConstraints { (make) in
            make.trailing.equalTo(theButton.snp.leading).offset(-8)
        }

    }

}

class SnapTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 100

    }

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SnapCell", for: indexPath) as! SnapCell

        switch indexPath.row % 4 {

        case 0:
            cell.theLabel.text = "One line label."

        case 1:
            cell.theLabel.text = "This label has\nTwo Lines."

        case 2:
            cell.theLabel.text = "This label has enough text that is will wrap to Three Lines (on an iPhone 7)."

        default:
            cell.theLabel.text = "View balance with your pre-recorded Siri Command .View balance with your pre-recorded Siri Command  View balance with your pre-recorded Siri Command View balance with your pre-recorded Siri Command "

        }

        return cell
    }

}

enter image description here

关于ios - AutoLayout:多行标签和固定大小的按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52856274/

相关文章:

ios - 在 64 位系统上使用 LC_ENCRYPTION_INFO 进行基本破解检测?

iphone - 使用 JQuery 和 Scrollto 插件自动滚动时 iPad 闪烁

ios - 如何在 SWIFT 的 sqlite 表中添加列

ios - UITableviewCell 动态高度以编程方式使用 UITableViewAutomaticDimension

ios - 父 View 边界的最小 x 值?

ios - 推送后标签栏的底部布局指南长度问题

ios - 指定 NSLineBreakMode.byTruncatingTail 会导致在 UILabel 中显示 NSAttributedString 时出现问题

iphone - 在uitableview上添加整理分隔符

ios - 从 objective-c 中的数组中找到最大日期

ios - 如何在 Swift 中创建一个 UILabel 数组