添加 UIScrollView 来实现超级视图并添加其内容来实现除安全区域之外的所有内容

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

简而言之,我希望实现以下目标:

内容显示在底部安全区域后面,但用户可以滚动它。 这是使用

UITableView
实现的,默认情况下具有这种行为,但我需要使用带有子视图的
UIScrollView
来实现。

据我了解

UIScrollView
应该满足其超级视图。这个
UIScrollView
包含“内容视图”,它也实现了它的超级视图。这个“内容视图”包含例如带有约束的
UIStackView
(它只是作为示例 - 我在 XIB 中设置了约束):

stackView.bottomAnchor.constraint(greaterThanOrEqualTo: stackView.superview!.bottomAnchor)
        stackView.bottomAnchor.constraint(greaterThanOrEqualTo: scrollView.safeAreaLayoutGuide.bottomAnchor)

但是在这些操作之后,滚动变得中断。

尝试更改

contentInsetAdjustmentBehavior
,但效果很奇怪,即使有足够的空间,
UIScrollView
contentSize
也会被拉伸。

uiscrollview scrollable contentsize intrinsic-content-size safearea
1个回答
1
投票

您想要将滚动视图的“内容”限制为滚动视图的

Content Layout Guide

看一下这个例子...它添加了一个“全视图”滚动视图,向滚动视图添加了一个垂直堆栈视图,然后向堆栈视图添加了 10 个图像视图:

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Wizard"
        
        let scrollView = UIScrollView()
        let stackView = UIStackView()
        
        stackView.axis = .vertical
        stackView.spacing = 8
        
        stackView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(stackView)
        view.addSubview(scrollView)
        
        let cg = scrollView.contentLayoutGuide
        let fg = scrollView.frameLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // constrain all 4 sides of scroll view to view
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

            // constrain all 4 sides of stack view to scroll view's Content Layout Guide
            stackView.topAnchor.constraint(equalTo: cg.topAnchor),
            stackView.leadingAnchor.constraint(equalTo: cg.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: cg.trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: cg.bottomAnchor),

            // constrain stack view width to scroll view's Frame Layout Guide width
            stackView.widthAnchor.constraint(equalTo: fg.widthAnchor),
            
        ])
        
        // generate 10 image views with images and add to the stack view
        for i in 0..<10 {
            let img = genImage(sz: .init(width: 200.0, height: 200.0), num: i)
            let v = UIImageView(image: img)
            v.heightAnchor.constraint(equalToConstant: 200.0).isActive = true
            stackView.addArrangedSubview(v)
        }
        
    }
    
    func genImage(sz: CGSize, num: Int) -> UIImage {
        let colors: [UIColor] = [
            .systemRed, .systemGreen, .systemBlue,
            .cyan, .green, .yellow,
        ]
        
        let renderer = UIGraphicsImageRenderer(size: sz)
        guard let nImg = UIImage(systemName: "\(num).circle.fill") else { fatalError() }
        let img = renderer.image { ctx in
            colors[num % colors.count].setFill()
            ctx.fill(.init(origin: .zero, size: sz))
            nImg.draw(in: .init(origin: .zero, size: sz))
        }
        
        return img
    }

}

看起来像这样:

滚动一下之后:

并一直滚动到底部:


编辑 - 回应评论...

您的 XIB 方法存在一些问题。

问题一“模糊的可滚动高度”与您使用 XIB 而不是 Storyboard 的事实无关。

假设我们像这样设置一个视图控制器:

我们看到红色缺失/模糊约束错误指示器。

A

UIView
没有 size,直到我们给它一个尺寸。如果我们像这样运行应用程序,我们会看到以下内容:

粉色滚动视图,但没有蓝色“内容”视图的迹象。

现在,作为开发人员,我知道在运行时我将向该蓝色视图添加一个或多个视图(例如带有一些大标签的堆栈视图) - 具有适当的约束 - 以获得我想要的用户界面:

而且效果很好。

当使用 Storyboard / Interface Builder 布局视图时,I 知道我要在运行时做什么,但 IB 不知道。

这是一个 IB 错误/警告,我们可以安全地忽略...但是,由于我们通常不想忽略某些事情,所以解决方案是为蓝色“内容”视图提供一个内在内容大小占位符

在尺寸检查器窗格底部附近找到它:

并更改它:

要得到这个:

现在,无需对界面进行任何其他更改,红色指示器就消失了:

您使用的实际宽度和高度值是无关紧要的...它们只是告诉 IB 我们知道我们在做什么。

问题二:尝试让滚动视图填充整个屏幕 - 包括安全区域 - 同时让滚动视图的内容尊重安全区域:

仅当 滚动视图是控制器视图的第一个子视图时,该行为才是自动的。

如果创建 View XIB 并向其添加滚动视图,则必须在运行时“提取”滚动视图。

更简单的方法是创建一个 Empty XIB,并添加

UIScrollView
作为其“基本”视图。

我在 https://github.com/DonMag/Sample20231206 发布了一个项目,您可以看一下。

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