自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈

Custom UIImageView is not circle inside custom UITableViewCell(自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈)

本文介绍了自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在代码中完成了自定义 UITableViewCell,但是我在使用带有 SfSymbol 的圆形 UIImageView 时遇到了问题.有时它运行良好,如您在屏幕截图中看到的那样,但有时它有一些奇怪的形状.如果我不设置任何 SfSymbol 形状是好的.

I have custom UITableViewCell done in code, but I have trouble with circular UIImageView with SfSymbol inside. Sometimes it is working well as you can see on the screenshot, but sometimes it has some strange shape. If I don't set any SfSymbol shape is good.

我认为我尝试了任何我可以尝试的方法,但仍然无法正常工作.这是我的自定义单元格代码:

I think that I tried anything, which I can, but still it's not working. This is my custom cell code:

import UIKit

class ListsTableViewCell: UITableViewCell {
    
    // MARK: - Properties
    
    let configuration = UIImage.SymbolConfiguration(pointSize: 16, weight: .medium)
    
    var list: List? {
        didSet {
            guard let list = list else { return }
            
            iconView.backgroundColor = list.color
            titleLabel.text = list.name
        }
    }
    
    // MARK: - Layout properties
    
    var iconView: CircularImageView!
    var titleLabel: UILabel!
    
    // MARK: - Initialization
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        iconView = CircularImageView()
        iconView.translatesAutoresizingMaskIntoConstraints = false
        iconView.tintColor = .white
        iconView.contentMode = .center
        
        titleLabel = UILabel()
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        
        contentView.addSubview(iconView)
        contentView.addSubview(titleLabel)
        
        NSLayoutConstraint.activate([
            iconView.heightAnchor.constraint(equalToConstant: 34),
            iconView.widthAnchor.constraint(equalToConstant: 34),
            iconView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
            iconView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
            iconView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
            iconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            
            titleLabel.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: 12),
            titleLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
            titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

这是行函数的表格视图单元格:

This is table view cell for row function:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let list = listsToDisplay![indexPath.row]
    
    let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "list", for: indexPath) as! ListsTableViewCell
    tableViewCell.iconView.image = UIImage(systemName: list.icon, withConfiguration: tableViewCell.configuration)
    tableViewCell.list = list
    tableViewCell.accessoryType = .disclosureIndicator
   
    return tableViewCell
}

这是 UIImageView 的自定义子类

And this is custom subclass of UIImageView

import UIKit

class CircularImageView: UIImageView {
    override func layoutSubviews() {
        self.layer.masksToBounds = true
        self.clipsToBounds = true
        self.layer.cornerRadius = self.frame.size.width / 2
    }
}

推荐答案

啊 - 我以前见过这个.

Ah - I've seen this before.

我不知道为什么,但是在 UIImageView 中使用 SF Symbol 会改变图像视图的高度!!!

I don't know why, but using a SF Symbol in a UIImageView will change the image view's height!!!

您可以轻松地确认这一点:

You can easily confirm this:

  • 在 Storyboard 中添加视图控制器
  • 添加一个UIImageView
  • 将内容模式设置为中心(没关系)
  • 约束宽度:60 高度:60 centerX 和 centerY
  • 检查尺寸检查器 - 它会显示 60 x 60

现在:

  • 使用下拉菜单将图像设置为地球"
  • 检查尺寸检查器 - 它将显示 60 x 59

现在:

  • 使用下拉菜单将图像设置为信封"
  • 检查尺寸检查器 - 它将显示 60 x 56.5

没有明显的约束冲突...没有明显的原因.

No apparent constraint conflicts... no apparent reason for this.

据我所知(除非 iOS 14 对此有所改变),我们需要将图像视图嵌入到 UIView ...约束它 centerX &centerY ... 设置该视图的背景颜色和圆角半径属性使其变为圆形.

As far as I can tell (unless this changes with iOS 14), we need to embed the image view in a UIView ... constrain it centerX & centerY ... set the background color and corner-radius properties of that view to make it round.

编辑——就像一个练习...

Edit -- just as an exercise...

两个水平堆栈视图:

  • 对齐方式:填充
  • 分布:FillEqually
  • 间距:0
  • 每个限制为 Width: 300Height: 100
  • 每个填充 3 个 UIImageViews

为我们提供了 3 个 100 x 100 方形图像视图.对于第二个堆栈,使用 UIImage.SymbolConfiguration(pointSize: 60, weight: .regular) 将每个图像视图设置为系统图像.应该仍然给我们 3 个 100 x 100 方块.

Gives us 3 100 x 100 square image views. For the second stack, set each image view to a system image, with UIImage.SymbolConfiguration(pointSize: 60, weight: .regular). Should still give us 3 100 x 100 squares.

结果却是这样:

这是生成该代码的代码:

Here's the code to produce that:

class SystemImageTestViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let stack1 = UIStackView()
        stack1.axis = .horizontal
        stack1.alignment = .fill
        stack1.distribution = .fillEqually
        
        let stack2 = UIStackView()
        stack2.axis = .horizontal
        stack2.alignment = .fill
        stack2.distribution = .fillEqually
        
        // add stack views to the view
        [stack1, stack2].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            stack1.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            stack1.widthAnchor.constraint(equalToConstant: 300.0),
            stack1.heightAnchor.constraint(equalToConstant: 100.0),
            stack1.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            stack2.topAnchor.constraint(equalTo: stack1.bottomAnchor, constant: 20.0),
            stack2.widthAnchor.constraint(equalToConstant: 300.0),
            stack2.heightAnchor.constraint(equalToConstant: 100.0),
            stack2.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
        ])
        
        let colors: [UIColor] = [
            UIColor(red: 0.75, green: 0.00, blue: 0.00, alpha: 1.0),
            UIColor(red: 0.00, green: 0.75, blue: 0.00, alpha: 1.0),
            UIColor(red: 0.00, green: 0.00, blue: 1.00, alpha: 1.0),
        ]
        
        for c in colors {
            let v = UIImageView()
            v.backgroundColor = c
            stack1.addArrangedSubview(v)
        }
        
        let configuration = UIImage.SymbolConfiguration(pointSize: 60, weight: .regular)
        
        let names: [String] = [
            "globe",
            "bandage",
            "envelope",
        ]

        for (c, n) in zip(colors, names) {
            let v = UIImageView()
            v.backgroundColor = c
            v.contentMode = .center
            v.tintColor = .white
            let img = UIImage(systemName: n, withConfiguration: configuration)
            v.image = img
            stack2.addArrangedSubview(v)
        }
        
    }
}


编辑 2 - 只是为了它......


Edit 2 - just for the heck of it...

SystemImageViewCircularSystemImageView 实现几个类:

Implementing a couple classes for a SystemImageView and CircularSystemImageView:

class SystemImageView: UIView {

    override var contentMode: UIView.ContentMode {
        didSet {
            imageView.contentMode = contentMode
        }
    }
    override var tintColor: UIColor! {
        didSet {
            imageView.tintColor = tintColor
        }
    }
    var image: UIImage = UIImage() {
        didSet {
            imageView.image = image
        }
    }
    let imageView = UIImageView()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        clipsToBounds = true
        addSubview(imageView)
        imageView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            imageView.topAnchor.constraint(equalTo: topAnchor),
            imageView.leadingAnchor.constraint(equalTo: leadingAnchor),
            imageView.trailingAnchor.constraint(equalTo: trailingAnchor),
            imageView.bottomAnchor.constraint(equalTo: bottomAnchor),
        ])
    }
}

class CircularSystemImageView: SystemImageView {
    override func layoutSubviews() {
        super.layoutSubviews()
        self.layer.masksToBounds = true
        self.clipsToBounds = true
        self.layer.cornerRadius = bounds.size.width * 0.5
    }
}

class SystemImageTestViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let stack1 = UIStackView()
        stack1.axis = .horizontal
        stack1.alignment = .fill
        stack1.distribution = .fillEqually
        
        let stack2 = UIStackView()
        stack2.axis = .horizontal
        stack2.alignment = .fill
        stack2.distribution = .fillEqually
        
        let stack3 = UIStackView()
        stack3.axis = .horizontal
        stack3.alignment = .fill
        stack3.distribution = .fillEqually
        
        let stack4 = UIStackView()
        stack4.axis = .horizontal
        stack4.alignment = .fill
        stack4.distribution = .fillEqually
        
        // add stack views to the view
        [stack1, stack2, stack3, stack4].forEach {
            $0.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview($0)
        }
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            stack1.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            stack1.widthAnchor.constraint(equalToConstant: 300.0),
            stack1.heightAnchor.constraint(equalToConstant: 100.0),
            stack1.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            stack2.topAnchor.constraint(equalTo: stack1.bottomAnchor, constant: 20.0),
            stack2.widthAnchor.constraint(equalToConstant: 300.0),
            stack2.heightAnchor.constraint(equalToConstant: 100.0),
            stack2.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            stack3.topAnchor.constraint(equalTo: stack2.bottomAnchor, constant: 20.0),
            stack3.widthAnchor.constraint(equalToConstant: 300.0),
            stack3.heightAnchor.constraint(equalToConstant: 100.0),
            stack3.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
            stack4.topAnchor.constraint(equalTo: stack3.bottomAnchor, constant: 20.0),
            stack4.widthAnchor.constraint(equalToConstant: 300.0),
            stack4.heightAnchor.constraint(equalToConstant: 100.0),
            stack4.centerXAnchor.constraint(equalTo: g.centerXAnchor),
            
        ])
        
        let colors: [UIColor] = [
            UIColor(red: 0.75, green: 0.00, blue: 0.00, alpha: 1.0),
            UIColor(red: 0.00, green: 0.75, blue: 0.00, alpha: 1.0),
            UIColor(red: 0.00, green: 0.00, blue: 1.00, alpha: 1.0),
        ]
        
        for c in colors {
            let v = UIImageView()
            v.backgroundColor = c
            stack1.addArrangedSubview(v)
        }
        
        let configuration = UIImage.SymbolConfiguration(pointSize: 60, weight: .regular)
        
        let names: [String] = [
            "globe",
            "bandage",
            "envelope",
        ]

        for (c, n) in zip(colors, names) {
            let v = UIImageView()
            v.backgroundColor = c
            v.contentMode = .center
            v.tintColor = .white
            if let img = UIImage(systemName: n, withConfiguration: configuration) {
                v.image = img
            }
            stack2.addArrangedSubview(v)
        }
        
        for (c, n) in zip(colors, names) {
            let v = SystemImageView()
            v.backgroundColor = c
            v.contentMode = .center
            v.tintColor = .white
            if let img = UIImage(systemName: n, withConfiguration: configuration) {
                v.image = img
            }
            stack3.addArrangedSubview(v)
        }
        
        for (c, n) in zip(colors, names) {
            let v = CircularSystemImageView()
            v.backgroundColor = c
            v.contentMode = .center
            v.tintColor = .white
            if let img = UIImage(systemName: n, withConfiguration: configuration) {
                v.image = img
            }
            stack4.addArrangedSubview(v)
        }
        
    }
}

结果:

或者,使用更实用的 let configuration = UIImage.SymbolConfiguration(pointSize: 40, weight: .regular) 来显示尺寸不是由 SF Symbol 尺寸决定的:

or, with a little more practical let configuration = UIImage.SymbolConfiguration(pointSize: 40, weight: .regular) to show the sizes are not being determined by the SF Symbol size:

这篇关于自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈