代码之家  ›  专栏  ›  技术社区  ›  Noodledew

UIScrollView的右锚点不适用

  •  0
  • Noodledew  · 技术社区  · 7 年前

    我有一个 UIViewController? 单事件控制器 显示事件。因为它有动态信息要显示,所以我选择创建一个新类 UIScrollView 事件滚动视图 Answer. 我尝试应用纯自动布局方法:创建另一个 UIView 内容视图 其中包含所有信息,并锚定到scrollView的所有四个锚定。

    scrollView的contentSize在 视图布局子视图 函数。

    我的斗争是,右锚似乎是错误的。所有的信息元素都会越过视图的边界,较大的元素会换行 UILabels 不起作用,在正确的锚点上放置的所有项目都不见了(例如 UITableView 没有人 是contentView的子视图。)

    这看起来像这样: Problem-Image


    中的代码 单一事件控制器:

    view.addSubview(scrollView)
    scrollView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: buttonViewDividerView.topAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    
    override func viewDidLayoutSubviews() {
        let heightOfAllObjects = scrollView.calculateHeightOfAllObjects()
        scrollView.contentSize = CGSize(width: self.view.frame.width, height: heightOfAllObjects + scrollView.heightOfAllPaddings)
    }
    

    代码输入 事件滚动视图

    addSubview(contentView)
    contentView.addSubview(titleLabel)
    contentView.addSubview(locationLabel)
    ...
    contentView.addSubview(nopePeopleTV)
    
    contentView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    titleLabel.anchor(top: contentView.topAnchor, left: contentView.leftAnchor, bottom: nil, right: contentView.rightAnchor, paddingTop: 10, paddingLeft: padding, paddingBottom: 0, paddingRight: padding, width: 0, height: 0)
    locationLabel.anchor(top: titleLabel.bottomAnchor, left: contentView.leftAnchor, bottom: nil, right: nil, paddingTop: 0, paddingLeft: padding, paddingBottom: 0, paddingRight: 0, width: 200, height: 0)
    nopePeopleTV.anchor(top: maybePeopleTV.bottomAnchor, left: contentView.leftAnchor, bottom: nil, right: contentView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    
    layoutIfNeeded()
    contentView.layoutIfNeeded()
    

    我做错什么了?


    func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?,  paddingTop: CGFloat, paddingLeft: CGFloat, paddingBottom: CGFloat, paddingRight: CGFloat, width: CGFloat, height: CGFloat) {
    
        translatesAutoresizingMaskIntoConstraints = false
    
        if let top = top {
            topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
        }
    
        if let left = left {
            leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
        }
    
        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
        }
    
        if let right = right {
            rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
        }
    
        if width != 0 {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }
    
        if height != 0 {
            heightAnchor.constraint(equalToConstant: height).isActive = true
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   matt    7 年前

    问题是您让内容视图的宽度由内而外由子视图的宽度决定。您需要为内容视图提供与滚动视图本身的宽度匹配的宽度约束。

    我将用一个人工但完整的代码示例来演示这一区别:

    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
            let sv = UIScrollView()
            sv.translatesAutoresizingMaskIntoConstraints = false
            self.view.addSubview(sv)
            NSLayoutConstraint.activate([
                sv.topAnchor.constraint(equalTo: self.view.topAnchor),
                sv.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
                sv.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
                sv.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
            ])
            let cv = UIView() // content view
            cv.translatesAutoresizingMaskIntoConstraints = false
            sv.addSubview(cv)
            NSLayoutConstraint.activate([
                sv.topAnchor.constraint(equalTo: cv.topAnchor),
                sv.leadingAnchor.constraint(equalTo: cv.leadingAnchor),
                sv.trailingAnchor.constraint(equalTo: cv.trailingAnchor),
                sv.bottomAnchor.constraint(equalTo: cv.bottomAnchor),
            ])
            let lab = UILabel()
            lab.translatesAutoresizingMaskIntoConstraints = false
            lab.numberOfLines = 0
            lab.text = Array(repeating: "xxx", count: 100).joined(separator: " ")
            cv.addSubview(lab)
            NSLayoutConstraint.activate([
                lab.topAnchor.constraint(equalTo: cv.topAnchor, constant:30),
                lab.leadingAnchor.constraint(equalTo: cv.leadingAnchor),
                lab.trailingAnchor.constraint(equalTo: cv.trailingAnchor),
            ])
        }
    }
    

    结果如下:

    enter image description here

    我们有一个很长的标签,但它没有包装:它一直延伸到右边,离开屏幕。这是因为内容视图本身的右边缘离开了屏幕。那是因为我们什么也没做 防止 这件事不会发生。长标签本身使内容视图与标签的整个文本一样宽。

    现在,我将最后一行代码添加到 viewDidLoad

        cv.widthAnchor.constraint(
            equalTo:sv.frameLayoutGuide.widthAnchor).isActive = true
    

    结果是:

    enter image description here

    然而,我们并没有对世界做同样的事情 高度 内容视图的定义;我们 希望