自定义 UIImageView 不是自定义 UITableViewCell 内的圆圈
Custom UIImageView is not circle inside custom UITableViewCell
我在代码中完成了自定义 UITableViewCell,但是我在使用内部带有 SfSymbol 的圆形 UIImageView 时遇到了问题。有时它运行良好,如您在屏幕截图中所见,但有时它的形状有些奇怪。如果我不设置任何 SfSymbol 形状是好的。
我想我已经尽我所能,但仍然没有用。这是我的自定义单元格代码:
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")
}
}
这是 table 行函数的视图单元格:
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 的自定义子类
import UIKit
class CircularImageView: UIImageView {
override func layoutSubviews() {
self.layer.masksToBounds = true
self.clipsToBounds = true
self.layer.cornerRadius = self.frame.size.width / 2
}
}
移除图像视图的高度限制。而不是使用有助于根据单元格高度占据位置的纵横比。
啊 - 我以前见过这个。
我不知道为什么,但是在 UIImageView
中使用 SF 符号会 改变图像视图的高度!!!
你可以很容易地确认这一点:
- 在故事板中添加一个视图控制器
- 添加一个
UIImageView
- 将内容模式设置为居中(并不重要)
- constrain 宽度:60 高度:60 centerX 和 centerY
- 检查大小检查器 - 它会显示
60 x 60
现在:
- 使用下拉菜单将图像设置为“globe”
- 检查大小检查器 - 它会显示
60 x 59
现在:
- 使用下拉菜单将图像设置为“信封”
- 检查大小检查器 - 它会显示
60 x 56.5
没有明显的约束冲突...没有明显的 原因。
据我所知(除非随着 iOS 14 发生变化),我们需要将图像视图嵌入 UIView
... 约束它的 centerX 和 centerY ... 设置该视图的背景颜色和圆角半径属性,使其成为圆形。
编辑 -- 作为练习...
两个水平堆栈视图:
- 对齐:填充
- 分布:FillEqually
- 间距:0
- 每个限制为
Width: 300
和 Height: 100
- 每个装满3个
UIImageView
s
给我们 3 100 x 100
个正方形图像视图。对于第二个堆栈,将每个图像视图设置为系统图像,UIImage.SymbolConfiguration(pointSize: 60, weight: .regular)
。 应该还是给我们3个100 x 100
方格。
相反,这是结果:
这是生成该代码的代码:
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 {
[=10=].translatesAutoresizingMaskIntoConstraints = false
view.addSubview([=10=])
}
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 - 只是为了它...
为 SystemImageView
和 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 {
[=11=].translatesAutoresizingMaskIntoConstraints = false
view.addSubview([=11=])
}
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 符号尺寸决定的:
我在代码中完成了自定义 UITableViewCell,但是我在使用内部带有 SfSymbol 的圆形 UIImageView 时遇到了问题。有时它运行良好,如您在屏幕截图中所见,但有时它的形状有些奇怪。如果我不设置任何 SfSymbol 形状是好的。
我想我已经尽我所能,但仍然没有用。这是我的自定义单元格代码:
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")
}
}
这是 table 行函数的视图单元格:
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 的自定义子类
import UIKit
class CircularImageView: UIImageView {
override func layoutSubviews() {
self.layer.masksToBounds = true
self.clipsToBounds = true
self.layer.cornerRadius = self.frame.size.width / 2
}
}
移除图像视图的高度限制。而不是使用有助于根据单元格高度占据位置的纵横比。
啊 - 我以前见过这个。
我不知道为什么,但是在 UIImageView
中使用 SF 符号会 改变图像视图的高度!!!
你可以很容易地确认这一点:
- 在故事板中添加一个视图控制器
- 添加一个
UIImageView
- 将内容模式设置为居中(并不重要)
- constrain 宽度:60 高度:60 centerX 和 centerY
- 检查大小检查器 - 它会显示
60 x 60
现在:
- 使用下拉菜单将图像设置为“globe”
- 检查大小检查器 - 它会显示
60 x 59
现在:
- 使用下拉菜单将图像设置为“信封”
- 检查大小检查器 - 它会显示
60 x 56.5
没有明显的约束冲突...没有明显的 原因。
据我所知(除非随着 iOS 14 发生变化),我们需要将图像视图嵌入 UIView
... 约束它的 centerX 和 centerY ... 设置该视图的背景颜色和圆角半径属性,使其成为圆形。
编辑 -- 作为练习...
两个水平堆栈视图:
- 对齐:填充
- 分布:FillEqually
- 间距:0
- 每个限制为
Width: 300
和Height: 100
- 每个装满3个
UIImageView
s
给我们 3 100 x 100
个正方形图像视图。对于第二个堆栈,将每个图像视图设置为系统图像,UIImage.SymbolConfiguration(pointSize: 60, weight: .regular)
。 应该还是给我们3个100 x 100
方格。
相反,这是结果:
这是生成该代码的代码:
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 {
[=10=].translatesAutoresizingMaskIntoConstraints = false
view.addSubview([=10=])
}
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 - 只是为了它...
为 SystemImageView
和 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 {
[=11=].translatesAutoresizingMaskIntoConstraints = false
view.addSubview([=11=])
}
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 符号尺寸决定的: