如何通过编程将 ImageView 对齐到 ScrollView 底部?

3

我正在尝试使用自动布局,以编程方式将背景图像对齐到适合屏幕的滚动视图底部。理想情况下,我希望图像始终与滚动视图底部对齐。当滚动视图内容超出屏幕高度或滚动视图内容大小小于屏幕高度且滚动视图适合整个屏幕时。

MyView

class MyView: UIView {

    let myScrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.bounces = false
        return scrollView
    }()

    let contentView: UIView = {
        let view = UIView()
        view.backgroundColor = .red
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    let myLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Hello world"
        label.font = UIFont.systemFont(ofSize: 24)
        return label
    }()

    let myImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.image = #imageLiteral(resourceName: "Mask Group 3")
        return imageView
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
        setupConstraints()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func setupView() {
        backgroundColor = .white

        addSubview(myScrollView)

        myScrollView.addSubview(contentView)

        contentView.addSubview(myLabel)
        contentView.addSubview(myImageView)
    }

    private func setupConstraints() {
        myScrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        myScrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        myScrollView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        myScrollView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true

        contentView.topAnchor.constraint(equalTo: myScrollView.topAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: myScrollView.bottomAnchor).isActive = true
        contentView.leftAnchor.constraint(equalTo: myScrollView.leftAnchor).isActive = true
        contentView.rightAnchor.constraint(equalTo: myScrollView.rightAnchor).isActive = true
        contentView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        // If I am setting this and when the content size go beyond the screen, it does not scroll
        // If I don't set this, there is no content size and image view will not position correctly
//        contentView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true

        myLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 200).isActive = true
        myLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true

        myImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        myImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
        myImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
    }

}

MyViewController

import UIKit

class MyViewController: UIViewController {

    override func loadView() {
        view = MyView()
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

}

说明

滚动视图


1
这是你想做的吗?https://dev59.com/8FUL5IYBdhLWcg3wHUwt#50864054 - DonMag
2个回答

3

我已经找到了解决方案。

  1. 需要一个contentView
  2. contentView的顶部、左侧、底部、右侧约束设置为与scrollView边缘相等
  3. contentView的宽度等于view的宽度锚点
  4. contentView的高度大于等于view的高度锚点
  5. imageView的底部等于contentView的底部锚点。
  6. 对于imageView的顶部,将约束设置为具有大于等于关系的元素,以给它一个恒定的间隔,并避免在较小的屏幕上重叠元素。

0

看起来还好:

private func setupConstraints() {
        myScrollView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        myScrollView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        myScrollView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
        myScrollView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true

        contentView.topAnchor.constraint(equalTo: myScrollView.topAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: myScrollView.bottomAnchor).isActive = true
        contentView.leftAnchor.constraint(equalTo: myScrollView.leftAnchor).isActive = true
        contentView.rightAnchor.constraint(equalTo: myScrollView.rightAnchor).isActive = true
        contentView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        // If I am setting this and when the content size go beyond the screen, it does not scroll
        // If I don't set this, there is no content size and image view will not position correctly
        contentView.heightAnchor.constraint(equalToConstant: 1400).isActive = true

        myLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 200).isActive = true
        myLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true

        myImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        myImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
        myImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
        myImageView.heightAnchor.constraint(equalToConstant: 200).isActive = true

    }

如果你认为你只是忘记指定图像高度:

myImageView.heightAnchor.constraint(equalToConstant: 200).isActive = true

没有滚动视图,我不必指定imageView的高度,也不知道内容大小,它可能小于屏幕高度或大于屏幕高度,我认为设置contentView的高度在这种情况下没有帮助。 - Samuel Kith
你说的“没有滚动视图”是什么意思?我改变了ContentView的大小,只是为了展示图片对齐到底部。 - Andrew
我所说的无需使用ScrollView,是指如果我只是添加一个子视图,比如一个imageView,我不需要指定高度,子视图也会根据其内容自动设置高度,而无需我显式地设置。 - Samuel Kith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接