如何通过代码调整主图片位置并在其下方添加3张小图片?
实现主图位置调整+下方3张小图的Auto Layout约束(代码实现)
我需要调整主图片的位置,并像第二张截图那样在其下方添加3张小图片,请问需要设置哪些Auto Layout约束?(通过代码实现)


原代码
import UIKit class DetailsHomeViewController: UIViewController { let someImageView: UIImageView = { let theImageView = UIImageView() theImageView.image = UIImage(named: "t-shirt.png") theImageView.translatesAutoresizingMaskIntoConstraints = false return theImageView }() override func viewDidLoad() { super.viewDidLoad() view.addSubview(someImageView) someImageViewConstraints() view.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1) setupViews() } private func setupViews() { createCustomNavigationBar() let RightButton = createCustomButton( imageName: "square.and.arrow.up", selector: #selector(RightButtonTapped) ) let customTitleView = createCustomTitleView( detailsName: "Label" ) navigationItem.rightBarButtonItems = [RightButton] navigationItem.titleView = customTitleView } func someImageViewConstraints() { someImageView.translatesAutoresizingMaskIntoConstraints = false someImageView.widthAnchor.constraint(equalToConstant: 340).isActive = true someImageView.heightAnchor.constraint(equalToConstant: 340).isActive = true someImageView.translatesAutoresizingMaskIntoConstraints = false someImageView.heightAnchor.constraint(equalToConstant: 80).isActive = true someImageView.widthAnchor.constraint(equalTo: someImageView.heightAnchor, multiplier: 16/9 ).isActive = true } @objc private func RightButtonTapped() { print("RightButtonTapped") } }
解决方案
首先清理原代码的问题:someImageViewConstraints中重复设置translatesAutoresizingMaskIntoConstraints,且重复添加宽高约束会导致布局冲突,需要先删除这些无效代码。
接下来按以下步骤实现目标布局:
1. 定义所有图片控件与容器
用UIStackView管理三个小图,自动处理间距和排列逻辑:
// 主图 let mainImageView: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "t-shirt.png") iv.contentMode = .scaleAspectFit // 保持图片比例 iv.translatesAutoresizingMaskIntoConstraints = false return iv }() // 三个小图 let smallImageView1: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small1.png") // 替换为你的图片名 iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() let smallImageView2: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small2.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() let smallImageView3: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small3.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() // 小图容器StackView let smallImagesStackView: UIStackView = { let stack = UIStackView() stack.axis = .horizontal // 水平排列 stack.spacing = 16 // 小图间距 stack.distribution = .fillEqually // 小图平分容器宽度 stack.translatesAutoresizingMaskIntoConstraints = false return stack }()
2. 在viewDidLoad中添加控件到视图
override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white setupViews() // 添加主图到视图 view.addSubview(mainImageView) // 将小图添加到StackView,再把StackView添加到视图 smallImagesStackView.addArrangedSubview(smallImageView1) smallImagesStackView.addArrangedSubview(smallImageView2) smallImagesStackView.addArrangedSubview(smallImageView3) view.addSubview(smallImagesStackView) setupLayoutConstraints() }
3. 设置Auto Layout约束
private func setupLayoutConstraints() { NSLayoutConstraint.activate([ // 主图约束:顶部与导航栏下方安全区对齐,水平居中,宽度不超过视图90%,宽高比1:1 mainImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20), mainImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor), mainImageView.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor, multiplier: 0.9), mainImageView.heightAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 1.0), // 小图容器约束:顶部与主图底部间距20,水平居中,宽度与主图一致 smallImagesStackView.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 20), smallImagesStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), smallImagesStackView.widthAnchor.constraint(equalTo: mainImageView.widthAnchor), // 单个小图宽高比约束(可根据需求调整比例) smallImageView1.heightAnchor.constraint(equalTo: smallImageView1.widthAnchor, multiplier: 0.8), smallImageView2.heightAnchor.constraint(equalTo: smallImageView2.widthAnchor, multiplier: 0.8), smallImageView3.heightAnchor.constraint(equalTo: smallImageView3.widthAnchor, multiplier: 0.8) ]) }
约束说明
- 主图:
- 顶部绑定安全区,避免被导航栏遮挡
- 水平居中保证视觉平衡
- 宽度限制为视图90%,适配不同屏幕尺寸
- 宽高比1:1确保图片不变形
- 小图容器:
- 与主图保持固定间距,形成上下层级布局
- 和主图宽度一致,保持布局统一性
- 小图:
- 通过StackView的
fillEqually自动平分宽度,再用宽高比约束控制高度,保证小图比例统一
- 通过StackView的
完整可运行代码
import UIKit class DetailsHomeViewController: UIViewController { // 主图 let mainImageView: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "t-shirt.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() // 三个小图 let smallImageView1: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small1.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() let smallImageView2: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small2.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() let smallImageView3: UIImageView = { let iv = UIImageView() iv.image = UIImage(named: "small3.png") iv.contentMode = .scaleAspectFit iv.translatesAutoresizingMaskIntoConstraints = false return iv }() // 小图容器StackView let smallImagesStackView: UIStackView = { let stack = UIStackView() stack.axis = .horizontal stack.spacing = 16 stack.distribution = .fillEqually stack.translatesAutoresizingMaskIntoConstraints = false return stack }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white setupViews() // 添加控件到视图 view.addSubview(mainImageView) smallImagesStackView.addArrangedSubview(smallImageView1) smallImagesStackView.addArrangedSubview(smallImageView2) smallImagesStackView.addArrangedSubview(smallImageView3) view.addSubview(smallImagesStackView) setupLayoutConstraints() } private func setupViews() { createCustomNavigationBar() let rightButton = createCustomButton( imageName: "square.and.arrow.up", selector: #selector(rightButtonTapped) ) let customTitleView = createCustomTitleView( detailsName: "Label" ) navigationItem.rightBarButtonItems = [rightButton] navigationItem.titleView = customTitleView } private func setupLayoutConstraints() { NSLayoutConstraint.activate([ // 主图约束 mainImageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20), mainImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor), mainImageView.widthAnchor.constraint(lessThanOrEqualTo: view.widthAnchor, multiplier: 0.9), mainImageView.heightAnchor.constraint(equalTo: mainImageView.widthAnchor, multiplier: 1.0), // 小图容器约束 smallImagesStackView.topAnchor.constraint(equalTo: mainImageView.bottomAnchor, constant: 20), smallImagesStackView.centerXAnchor.constraint(equalTo: view.centerXAnchor), smallImagesStackView.widthAnchor.constraint(equalTo: mainImageView.widthAnchor), // 小图宽高比约束 smallImageView1.heightAnchor.constraint(equalTo: smallImageView1.widthAnchor, multiplier: 0.8), smallImageView2.heightAnchor.constraint(equalTo: smallImageView2.widthAnchor, multiplier: 0.8), smallImageView3.heightAnchor.constraint(equalTo: smallImageView3.widthAnchor, multiplier: 0.8) ]) } @objc private func rightButtonTapped() { print("RightButtonTapped") } // 补充原有的自定义方法实现 private func createCustomNavigationBar() { // 你的自定义导航栏逻辑 } private func createCustomButton(imageName: String, selector: Selector) -> UIBarButtonItem { let button = UIButton(type: .system) button.setImage(UIImage(systemName: imageName), for: .normal) button.addTarget(self, action: selector, for: .touchUpInside) return UIBarButtonItem(customView: button) } private func createCustomTitleView(detailsName: String) -> UIView { let titleLabel = UILabel() titleLabel.text = detailsName titleLabel.font = UIFont.systemFont(ofSize: 17, weight: .semibold) return titleLabel } }
内容的提问来源于stack exchange,提问作者Captain Grimm
相关产品推荐
相关产品推荐

