使用UIScrollView的内容最少的顶部锚会导致视觉故障

问题描述 投票:1回答:1

我有一个滚动视图,其中有一个内容视图。我将滚动视图的顶部锚点设置为刚好在图像底部上方。我将内容视图的顶部锚点设置为实际上位于图像的底部。这样,您可以拉下内容并向上显示图像的底部,而无需进一步拉下内容视图。但是,这导致内容跳跃。

这是我的代码:

class HomeParallaxScrollViewController: UIViewController {

    private let topImageView = UIImageView(image: UIImage(named: "cat"))
    private let contentView = UIView()
    private let scrollView = UIScrollView()
    private let label = UILabel()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .gray

        topImageView.contentMode = .scaleAspectFill
        contentView.backgroundColor = .white
        label.text = "SOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT"
        label.textColor = .black
        label.numberOfLines = 0

        [contentView, label, topImageView, scrollView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }

        scrollView.addSubview(contentView)
        contentView.addSubview(label)
        view.addSubview(topImageView)
        view.addSubview(scrollView)

        NSLayoutConstraint.activate([
            topImageView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
            topImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            topImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            topImageView.heightAnchor.constraint(equalToConstant: 200),

            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.widthAnchor.constraint(equalTo: view.widthAnchor),
            scrollView.topAnchor.constraint(equalTo: topImageView.bottomAnchor, constant: -30),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.topAnchor.constraint(lessThanOrEqualTo: topImageView.bottomAnchor), //This is what's causing the glitch

            label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])
    }
}

这就是发生的情况:enter image description here

swift uiscrollview visual-glitch page-jump
1个回答
0
投票

[尝试添加另一个最高约束,特别是向滚动视图外部的元素添加约束,这是一个坏主意,而且您将无法使用。我确定您注意到正在生成自动布局冲突消息。

一种方法是实现scrollViewDidScroll委托函数:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // limit drag-down in the scroll view to the overlap size
    scrollView.contentOffset.y = max(scrollView.contentOffset.y, -30)
}

当用户向下滚动以滚动时,它将停止在30点处。

这是您的示例,稍作修改-我没有您的.plBackgroundLightGray.PLSemiboldFont,并且为顶部图像视图添加了图像加载-但这应原样运行:

// conform to UIScrollViewDelegate
class HomeParallaxScrollViewController: UIViewController, UIScrollViewDelegate {

    private let topImageView = UIImageView(image: UIImage(named: "cat"))
    private let contentView = UIView()
    private let scrollView = UIScrollView()
    private let label = UILabel()

    // this will be the "overlap" of the scroll view and top image view
    private var scrollOverlap: CGFloat = 30.0

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // limit drag-down in the scroll view to scrollOverlap points
        scrollView.contentOffset.y = max(scrollView.contentOffset.y, -scrollOverlap)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .lightGray // .plBackgroundLightGray

        topImageView.contentMode = .scaleAspectFill
        if let img = UIImage(named: "background") {
            topImageView.image = img
        }
        contentView.backgroundColor = .white
        label.text = "SOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT\n\n\nSOME\n\n\nRANDOM\n\n\nCONTENT"
        label.font = UIFont.boldSystemFont(ofSize: 16) // .PLSemiboldFont(size: 16)
        label.textColor = .black
        label.numberOfLines = 0

        [contentView, label, topImageView, scrollView].forEach { $0.translatesAutoresizingMaskIntoConstraints = false }

        scrollView.addSubview(contentView)
        contentView.addSubview(label)
        view.addSubview(topImageView)
        view.addSubview(scrollView)

        NSLayoutConstraint.activate([
            topImageView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
            topImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            topImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            topImageView.heightAnchor.constraint(equalToConstant: 200),

            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.widthAnchor.constraint(equalTo: view.widthAnchor),
            scrollView.topAnchor.constraint(equalTo: topImageView.bottomAnchor, constant: scrollOverlap),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),

            // nope, not a good idea -- will cause constraint conflicts
            //contentView.topAnchor.constraint(lessThanOrEqualTo: topImageView.bottomAnchor), //This is what's causing the glitch

            label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
        ])

        // set delegate to self
        scrollView.delegate = self
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.