如何使用自动布局以编程方式设置UIScrollView使其水平滚动

时间:2018-08-31 08:03:59

标签: ios swift

我正在尝试实现一种行为,即我在表格视图中具有最小宽度的表单。因此,基本上,如果屏幕宽,则视图仅垂直滚动,但是当屏幕狭窄时,表单会缩小到其最小宽度,然后开始水平滚动以免出现内容松动的情况。因此,我需要使用autoLayout来设置这些约束,并且我想以编程方式进行此操作(因为使用的是框架)。

问题是,我根本无法水平滚动视图。我已经阅读了所有可以找到的内容,并尝试了所有我能想到的内容,但没有任何效果。现在,我尝试仅向视图添加大图片并使其向两个方向滚动,但是我无法使其正常工作。

这是我的等级结构:

>UIView
>>UIScrollView
>>>ContentView (UIView)
>>>>ImageView

这是我的代码:

   override func viewDidLoad() {
    if scrollView == nil {
        scrollView = UIScrollView(frame: view.bounds)
        scrollView.backgroundColor = .groupTableViewBackground
        scrollView.isDirectionalLockEnabled = true
        scrollView.showsHorizontalScrollIndicator = true
    }
    if scrollView.superview == nil {
        view.addSubview(scrollView)

        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

        let contentView = UIView(frame: view.bounds)
        scrollView.addSubview(contentView)

        contentView.translatesAutoresizingMaskIntoConstraints = false
        contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
        contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true

        let a = contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
        let b = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
        a.priority = .defaultLow
        b.priority = .defaultLow
        a.isActive = true
        b.isActive = true

        let image = MyImage.icon(named: "myImage", of: CGSize(width: 1000, height: 1000))
        let imageView = UIImageView(image: image)

        imageView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(imageView)

        imageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true

    }
    super.viewDidLoad()
}

当我调试视图层次结构时,可以看到图像的大小仍然正确(1000, 1000),但是scrollView的内容大小没有更新,并且图片被截断,没有滚动。

>
<UIScrollView: 0x11ead5c00; frame = (0 0; 834 1112); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x1c8853800>; layer = <CALayer: 0x1c8c32240>; contentOffset: {0, -64}; contentSize: {834, 1112}; adjustedContentInset: {64, 0, 0, 0}>

<UIImageView: 0x11a89b000; frame = (0 0; 1000 1000); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1c8231c80>>

我发现并查看了此示例,以编程方式https://github.com/zaxonus/AutoLayScroll来设置滚动视图。它垂直滚动,但无论如何,我一生都无法将其设置为水平滚动。

请帮助,我在俯视什么?

2 个答案:

答案 0 :(得分:0)

要使您的示例scrollView的内容大小为1000x1000,只需将这些约束添加到imageView

imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true

没有它们,您的contentView不知道应该包装imageView,因此其大小是根据低优先级约束ab

计算的

答案 1 :(得分:0)

多亏了Anton,我的工作才能顺利!如果有人尝试做我想做的事,我只是想分享我的最终解决方案。

使用以下代码,您可以向Eureka框架FormViewController(https://github.com/xmartlabs/Eureka)的表单添加水平滚动功能。

import UIKit
import Eureka

class MyScrollableViewController: FormViewController {

    var scrollView: UIScrollView!
    var minimumWidth: CGFloat = 500.0

    override func viewDidLoad() {
        if tableView == nil {
            tableView = UITableView(frame: view.bounds, style: .grouped)
            if #available(iOS 9.0, *) {
                tableView.cellLayoutMarginsFollowReadableWidth = false
            }
        }
        if scrollView == nil {
            scrollView = UIScrollView(frame: view.bounds)
            scrollView.backgroundColor = .groupTableViewBackground
            scrollView.isDirectionalLockEnabled = true
            scrollView.showsHorizontalScrollIndicator = true
        }
        if scrollView.superview == nil && tableView.superview == nil {
            view.addSubview(scrollView)

            scrollView.translatesAutoresizingMaskIntoConstraints = false
            scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

            let contentView = UIView(frame: view.bounds)
            scrollView.addSubview(contentView)

            contentView.translatesAutoresizingMaskIntoConstraints = false
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true

            let a = contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
            let b = contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
            a.priority = .defaultLow
            b.priority = .defaultLow
            a.isActive = true
            b.isActive = true

            contentView.addSubview(tableView)
            tableView.translatesAutoresizingMaskIntoConstraints = false
            tableView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
            tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
            tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
            tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
            tableView.widthAnchor.constraint(greaterThanOrEqualToConstant: minimumWidth).isActive = true
        }
        // Has to be called after setting up the tableView since we override the Eureka default setup
        super.viewDidLoad()

        // Setup your Eureka form as usual
        form +++ Section()
            <<< LabelRow { row in
                row.title = "My first row"
        }
    }
}