自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈 [英] Custom UIImageView is not circle inside custom UITableViewCell

查看:17
本文介绍了自定义 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 内的圆圈的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆