【问题标题】:How do you align SF Symbols with one another in a UITableView?如何在 UITableView 中将 SF 符号相互对齐?
【发布时间】:2020-07-21 08:52:37
【问题描述】:

在 WWDC SF Symbols 视频中,Apple 表示在显示 SF Symbols 时更喜欢水平和垂直对齐。据推测,这意味着每个UIImageView.center.x 应该包含相同的值,以便它们排成一列。我的问题是如何确定 x 值应该是什么,因为它们都是不同的宽度。这是一个示例截图:

此屏幕截图使用UITableViewCellStyleDefaultcell.imageViewcell.textLabel。但是,我想知道如何使用自定义UITableViewCell 达到相同的效果。根据UIImageSymbolConfiguration.pointSize 确定一定宽度的正确方法是什么?一旦你有了那个宽度,所有的符号都会按照那个中心显示?

任何关于如何布局/对齐 SF 符号的指导,尤其是在不使用自动布局的情况下,都会非常有帮助:)

【问题讨论】:

  • 为您的图像视图提供所需的宽度,然后将图像视图的内容模式设置为 Center ...myImageView.contentMode = .center
  • 是的,但是你怎么知道图像视图的宽度?或者如何定位文本以使单元格排列在一起?
  • 这通常是通过自动布局完成的......我不太明白你的评论:“尤其是不使用自动布局”
  • 您是否打算将您的单元设计为故事板原型?还是仅通过代码?
  • 我只在代码中做。使用layoutSubviews进行定位

标签: ios iphone uitableview uiimage sf-symbols


【解决方案1】:

这是一个非常简单的例子。

它遍历数据以确定将用于设置 imageView 的宽度约束常量的最宽符号。

class MySymbolCell: UITableViewCell {

    let symbolImageView: UIImageView = {
        let v = UIImageView()
        v.contentMode = .center
        return v
    }()
    let theLabel: UILabel = {
        let v = UILabel()
        return v
    }()

    var imageWidthConstraint: NSLayoutConstraint!

    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 {

        symbolImageView.translatesAutoresizingMaskIntoConstraints = false
        theLabel.translatesAutoresizingMaskIntoConstraints = false

        contentView.addSubview(symbolImageView)
        contentView.addSubview(theLabel)

        // this way we can change imageView width at run-time if needed
        imageWidthConstraint = symbolImageView.widthAnchor.constraint(equalToConstant: 40.0)
        imageWidthConstraint.priority = UILayoutPriority(rawValue: 999)

        let g = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([

            // constrain imageView top / bottom / leading
            symbolImageView.topAnchor.constraint(equalTo: g.topAnchor),
            symbolImageView.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            symbolImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor),

            // constrain width
            imageWidthConstraint,

            // constrain height equal to width
            symbolImageView.heightAnchor.constraint(equalTo: symbolImageView.widthAnchor),

            // constrain label leading 8-pts from image view
            theLabel.leadingAnchor.constraint(equalTo: symbolImageView.trailingAnchor, constant: 8.0),

            // constrain label centerY to image view centerY
            theLabel.centerYAnchor.constraint(equalTo: symbolImageView.centerYAnchor),

            // constrain label trailing to content view trailing
            theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor),

        ])
    }
}

class MySymbolTableViewController: UITableViewController {

    var myData: [String] = [
        "arrow.up",
        "arrow.down",
        "person.badge.plus",
        "eye.slash",
        "line.horizontal.3",
        "textformat.123",
    ]

    var symbolImageViewWidth: CGFloat = 40.0

    // configure as desired
    let imageConfig = UIImage.SymbolConfiguration(pointSize: 20, weight: .light, scale: .default)

    override func viewDidLoad() {
        super.viewDidLoad()

        // calculate how wide you need your cell's symbol image view to be

        // either run a loop to get the widest symbol your data is using,
        //  or
        // just make sure you can fit the widest of the symbols ("bold.italic.underline")

        let testLoop = true

        if testLoop {

            var maxW: CGFloat = 0.0
            myData.forEach {
                if let img = UIImage(systemName: $0, withConfiguration: imageConfig) {
                    maxW = max(img.size.width, maxW)
                }
            }
            symbolImageViewWidth = maxW

        } else {

            if let img = UIImage(systemName: "bold.italic.underline", withConfiguration: imageConfig) {
                symbolImageViewWidth = img.size.width
            }

        }

        tableView.register(MySymbolCell.self, forCellReuseIdentifier: "MySymbolCell")

    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

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

        let img = UIImage(systemName: myData[indexPath.row], withConfiguration: imageConfig)

        cell.symbolImageView.image = img
        cell.theLabel.text = myData[indexPath.row]

        cell.imageWidthConstraint.constant = symbolImageViewWidth

        return cell
    }

}

结果:

【讨论】:

  • 在这里感谢您的帮助! bold.italic.underline 是最宽的符号吗?
  • 是的——至少现在是这样。我想苹果可能会在未来的更新中添加一个新符号,但我的假设是你知道你将使用哪些符号(或至少是哪组符号)。
【解决方案2】:

调整 cell.separatorInset 可能更容易

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cell.separatorInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 0)
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-27
    • 2016-03-17
    • 2014-11-15
    • 2022-11-30
    • 2015-02-23
    • 2013-02-09
    • 2023-03-11
    相关资源
    最近更新 更多