UIStackView 不改变宽度
UIStackView not changing the width
我有一个 UIStackView
,其中 UIImageViews
可能是 1 到 5。每个 UIImageView
都有一个来自数组的图像(来自以前下载和缓存的图像),我想让 UIImageView
保持在一个完美的圆圈内。如果有超过 3 张图像,我会更改 UIStackView
的 width
常数以及图像之间的间距以重叠。
我在以前的项目中写过这段代码,它工作得很好,但由于某种原因,当我调用 changeNavStackWidth
函数来更改 UIStackView
的 width
时,宽度没有更新,我不知道为什么。
var userImages = [String]()
var navStackView : UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
override func viewDidLoad() {
super.viewDidLoad()
setupNavStack()
navBarStackTapGesture()
}
func setupNavStack() {
guard let navController = navigationController else { return }
navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.widthAnchor.constraint(equalToConstant: 95).isActive = true
navStackView.centerYAnchor.constraint(equalTo: navController.navigationBar.centerYAnchor).isActive = true
navStackView.heightAnchor.constraint(equalToConstant: 35).isActive = true
navStackView.centerXAnchor.constraint(equalTo: navController.navigationBar.centerXAnchor).isActive = true
}
func setNavBarImages() {
for image in userImages {
let imageView = UIImageView()
// imageView.image = UIImage(named: image)
let photoURL = URL(string: image)
imageView.sd_setImage(with: photoURL)
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 1
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()
}
switch userImages.count {
case 0:
print("0 images")
case 1:
changeNavStackWidth(constant: 35, spacing: 0)
//changeNavStackWidth(constant: 60, spacing: 0)
case 2:
changeNavStackWidth(constant: 80, spacing: 10)
case 3:
changeNavStackWidth(constant: 95, spacing: -5)
case 4:
changeNavStackWidth(constant: 110, spacing: -10)
case 5:
changeNavStackWidth(constant: 95, spacing: -20)
case 6...1000:
// changeNavStackWidth(constant: 95, spacing: -20)
default:
print("default")
}
navigationItem.titleView = navStackView
navStackView.layoutIfNeeded()
}
func changeNavStackWidth(constant: CGFloat, spacing: CGFloat) {
navStackView.constraints.forEach { constraint in
if constraint.firstAttribute == .width {
constraint.constant = constant
print("constan is:", constant) // not being printed
}
}
navStackView.spacing = spacing
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navStackView.subviews.forEach { [=10=].layer.cornerRadius = [=10=].frame.height / 2 }
}
而不是调整 StackView 的宽度来适应图像:
- 创建一个 UIView 并将 UIImageView 作为子视图添加到 UIView。
- 使用 UIView
向 UIImageView 添加 top
和 bottom
约束
- 用 UIView
添加 center horizontally
约束 UIImageView
- 向 UIImageView 添加
aspect ratio
约束并将该比率设置为 1:1
- 将 UIView 添加到堆栈视图
UIImageView 相对于 UIView 的约束将使图像均匀分离,而其自身的纵横比约束将使 UIImage 保持为一个完美的圆。
将 imageView 的内容模式更改为 .aspectFit
也可以解决问题,而不必弄乱 stackView 的宽度。
将此 imageView.contentMode = .scaleAspectFill
更改为此 imageView.contentMode = .scaleAspectFit
AspectFill
拉伸图像以适应视图,并且不保持图像的比例
AspectFit
拉伸图像直到水平边界或垂直边界到达视图,同时保持图像的比例。
见here
基于我们在聊天中的讨论。这就是你想要的:
A) 如果只有一张Image
B)如果有两个图像:
C) 如果有超过 2 个:
代码:
import UIKit
class TestStack: UIViewController{
var userImages = [#imageLiteral(resourceName: "images-1"),#imageLiteral(resourceName: "images-2"),#imageLiteral(resourceName: "images-4"),#imageLiteral(resourceName: "images-5")]
let imagesHolder: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
userImages.removeLast(2)
guard let bar = navigationController?.navigationBar else {return}
bar.addSubview(imagesHolder)
let size = 25
for i in 0..<userImages.count{
var x = i * size
x = userImages.count > 2 ? x/2 : x
x = (i == 1 && userImages.count == 2) ? x + 5 : x
let imageView = UIImageView(frame: CGRect(x: x, y: 0, width: size, height: size))
imageView.image = userImages[i]
imageView.clipsToBounds = true
imageView.layer.cornerRadius = CGFloat(size / 2)
imagesHolder.addSubview(imageView)
}
let width = CGFloat((userImages.count * size)/2)
NSLayoutConstraint.activate([
imagesHolder.centerYAnchor.constraint(equalTo: bar.centerYAnchor),
imagesHolder.centerXAnchor.constraint(equalTo: bar.centerXAnchor),
imagesHolder.widthAnchor.constraint(equalToConstant: width),
imagesHolder.heightAnchor.constraint(equalToConstant: CGFloat(size))
])
}
}
我有一个 UIStackView
,其中 UIImageViews
可能是 1 到 5。每个 UIImageView
都有一个来自数组的图像(来自以前下载和缓存的图像),我想让 UIImageView
保持在一个完美的圆圈内。如果有超过 3 张图像,我会更改 UIStackView
的 width
常数以及图像之间的间距以重叠。
我在以前的项目中写过这段代码,它工作得很好,但由于某种原因,当我调用 changeNavStackWidth
函数来更改 UIStackView
的 width
时,宽度没有更新,我不知道为什么。
var userImages = [String]()
var navStackView : UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
override func viewDidLoad() {
super.viewDidLoad()
setupNavStack()
navBarStackTapGesture()
}
func setupNavStack() {
guard let navController = navigationController else { return }
navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.widthAnchor.constraint(equalToConstant: 95).isActive = true
navStackView.centerYAnchor.constraint(equalTo: navController.navigationBar.centerYAnchor).isActive = true
navStackView.heightAnchor.constraint(equalToConstant: 35).isActive = true
navStackView.centerXAnchor.constraint(equalTo: navController.navigationBar.centerXAnchor).isActive = true
}
func setNavBarImages() {
for image in userImages {
let imageView = UIImageView()
// imageView.image = UIImage(named: image)
let photoURL = URL(string: image)
imageView.sd_setImage(with: photoURL)
imageView.layer.borderColor = UIColor.white.cgColor
imageView.layer.borderWidth = 1
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()
}
switch userImages.count {
case 0:
print("0 images")
case 1:
changeNavStackWidth(constant: 35, spacing: 0)
//changeNavStackWidth(constant: 60, spacing: 0)
case 2:
changeNavStackWidth(constant: 80, spacing: 10)
case 3:
changeNavStackWidth(constant: 95, spacing: -5)
case 4:
changeNavStackWidth(constant: 110, spacing: -10)
case 5:
changeNavStackWidth(constant: 95, spacing: -20)
case 6...1000:
// changeNavStackWidth(constant: 95, spacing: -20)
default:
print("default")
}
navigationItem.titleView = navStackView
navStackView.layoutIfNeeded()
}
func changeNavStackWidth(constant: CGFloat, spacing: CGFloat) {
navStackView.constraints.forEach { constraint in
if constraint.firstAttribute == .width {
constraint.constant = constant
print("constan is:", constant) // not being printed
}
}
navStackView.spacing = spacing
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navStackView.subviews.forEach { [=10=].layer.cornerRadius = [=10=].frame.height / 2 }
}
而不是调整 StackView 的宽度来适应图像:
- 创建一个 UIView 并将 UIImageView 作为子视图添加到 UIView。
- 使用 UIView 向 UIImageView 添加
- 用 UIView 添加
- 向 UIImageView 添加
aspect ratio
约束并将该比率设置为1:1
- 将 UIView 添加到堆栈视图
top
和 bottom
约束
center horizontally
约束 UIImageView
UIImageView 相对于 UIView 的约束将使图像均匀分离,而其自身的纵横比约束将使 UIImage 保持为一个完美的圆。
将 imageView 的内容模式更改为 .aspectFit
也可以解决问题,而不必弄乱 stackView 的宽度。
将此 imageView.contentMode = .scaleAspectFill
更改为此 imageView.contentMode = .scaleAspectFit
AspectFill
拉伸图像以适应视图,并且不保持图像的比例
AspectFit
拉伸图像直到水平边界或垂直边界到达视图,同时保持图像的比例。
见here
基于我们在聊天中的讨论。这就是你想要的:
A) 如果只有一张Image
代码:
import UIKit
class TestStack: UIViewController{
var userImages = [#imageLiteral(resourceName: "images-1"),#imageLiteral(resourceName: "images-2"),#imageLiteral(resourceName: "images-4"),#imageLiteral(resourceName: "images-5")]
let imagesHolder: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
userImages.removeLast(2)
guard let bar = navigationController?.navigationBar else {return}
bar.addSubview(imagesHolder)
let size = 25
for i in 0..<userImages.count{
var x = i * size
x = userImages.count > 2 ? x/2 : x
x = (i == 1 && userImages.count == 2) ? x + 5 : x
let imageView = UIImageView(frame: CGRect(x: x, y: 0, width: size, height: size))
imageView.image = userImages[i]
imageView.clipsToBounds = true
imageView.layer.cornerRadius = CGFloat(size / 2)
imagesHolder.addSubview(imageView)
}
let width = CGFloat((userImages.count * size)/2)
NSLayoutConstraint.activate([
imagesHolder.centerYAnchor.constraint(equalTo: bar.centerYAnchor),
imagesHolder.centerXAnchor.constraint(equalTo: bar.centerXAnchor),
imagesHolder.widthAnchor.constraint(equalToConstant: width),
imagesHolder.heightAnchor.constraint(equalToConstant: CGFloat(size))
])
}
}