Ios 使用内容展开的UIScrollView';内部大小直到高度X,然后滚动

Ios 使用内容展开的UIScrollView';内部大小直到高度X,然后滚动,ios,uiscrollview,autolayout,intrinsic-content-size,Ios,Uiscrollview,Autolayout,Intrinsic Content Size,我基本上是想重现警报标题和消息部分的行为 标题和消息标签显示在滚动视图中。如果标签文本增加,则警报高度也会随着标签的固有内容大小而增加。但在某个高度,警报高度停止增加,标题和消息文本可滚动 我读到的: 文章 堆栈溢出 答案可能就在那里,但我无法把它抽象出来 我尝试过的: 仅关注带有两个标签的滚动视图,我尝试制作一个最小的示例,其中父视图将根据滚动视图的固有高度调整大小。我玩过很多限制。这里有一个组合(在许多组合中)不起作用: 我曾经和甚至一起工作过。还有,我知道。然

我基本上是想重现警报标题和消息部分的行为

标题和消息标签显示在滚动视图中。如果标签文本增加,则警报高度也会随着标签的固有内容大小而增加。但在某个高度,警报高度停止增加,标题和消息文本可滚动

我读到的:

文章

堆栈溢出

答案可能就在那里,但我无法把它抽象出来

我尝试过的:

仅关注带有两个标签的滚动视图,我尝试制作一个最小的示例,其中父视图将根据滚动视图的固有高度调整大小。我玩过很多限制。这里有一个组合(在许多组合中)不起作用:


我曾经和甚至一起工作过。还有,我知道。然而,我从来没有做过任何事情的优先级和内容拥抱和压缩阻力。从我所做的阅读中,我对它们的含义有一个肤浅的理解,但我不知道如何在这个例子中应用它们。我的猜测是,我需要在内容拥抱和优先级方面做一些事情。

单靠约束无法解决您的问题,您必须使用一些代码。这是因为滚动视图没有固有的内容大小

因此,创建scroll view的子类。也许给它一个属性或者一个委托或者其他东西来告诉它它的最大高度应该是多少

在子类中,每当内容大小发生更改时,使内部内容大小无效,并将新的内部内容大小计算为内容大小的最小值和允许的最大值


一旦滚动视图有了一个固有的大小,它和它的超级视图之间的约束实际上会为您的问题做一些有意义的事情。

您应该能够通过纯自动布局来实现这个解决方案

通常,如果我希望标签随着内容的垂直增长而增长,我会这样做

[label setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal]; 
[label setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];

为了使scrollview符合您的要求,您需要确保可以绘制一条线,将scrollview的顶部通过标签一直连接到scrollview的底部,以便它可以计算其高度。为了使scrollview仅限于其父视图,您可以使用superview的倍增设置高度约束,例如0.8,我想我已经实现了与纯自动布局类似的效果

结构

首先,让我向您展示我的结构:

内容视图是具有白色背景的视图,调用者视图和底部视图具有固定高度。底部视图有您的按钮,调用方视图有您的标题

解决方案

因此,在设置基本约束(请注意,scroll view内部的视图与scroll view之间有上、左、右和下四个方向,且宽度相等)之后,问题在于scroll view不知道应该有什么大小。 因此,我所做的就是:

我希望卷轴可以增长到最大值。因此,我在superview中添加了一个比例高度来设置最大值:

然而,这带来了两个问题:滚动视图仍然不知道应该有多高,现在您可以调整大小,滚动视图将传递其内容的大小(如果内容小于最大大小)

因此,为了解决这两个问题,我在Scroll视图和Scroll视图内部添加了一个具有较小优先级的等高


我希望这能帮助您。

这可以在Interface builder中使用自动布局轻松完成

  • 使用“小于或等于”关系设置外部容器视图(“示例中scrollview的父容器”)高度约束
  • 2.在内容视图和滚动视图中添加“等高”约束。然后为此约束设置低优先级

    就这些。现在,如果内容高度更改,您的scrollview将按高度调整大小,但仅限于受外部视图高度约束限制的最大高度


    对于我的项目,我有一个类似的问题。您可以使用以下方法使其正常工作

    首先,标题和底部动作高度是固定的。内容具有可变高度。您可以使用字体大小将其作为一个子视图添加到主视图中,然后调用layoutIfNeeded,然后可以计算其高度并将其保存为XX。然后将其从mainView中删除

    其次,使用法线约束使用scrollView布局内容部分,mainView的高度约束为XX,设置ContentCompressionResistancePriority(.defaultLow,表示:.vertical)


    最后,alert可以在短内容时显示精确大小,在长内容时通过滚动显示有限大小。

    我已经能够仅通过自动布局约束实现这一精确行为。下面是一个通用的演示:它可以应用到您认为合适的视图层次结构中

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let kTestContentHeight: CGFloat = 1200
    
            // Subview that will shrink to fit content and expand up to 50% of the view controller's height
            let modalView = UIView()
            modalView.backgroundColor = UIColor.gray
    
            // Scroll view that will facilitate scrolling if the content > 50% of view controller's height
            let scrollView = UIScrollView()
            scrollView.backgroundColor = .yellow
    
            // Content which has an intrinsic height
            let contentView = UIView()
            contentView.backgroundColor = .green
    
    
            // add modal view
            view.addSubview(modalView)
            modalView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([modalView.leftAnchor.constraint(equalTo: view.leftAnchor),
                                         modalView.rightAnchor.constraint(equalTo: view.rightAnchor),
                                         modalView.heightAnchor.constraint(lessThanOrEqualTo: view.heightAnchor,
                                                                           multiplier: 0.5),
                                         modalView.bottomAnchor.constraint(equalTo: view.bottomAnchor)])
    
            let expandHeight = modalView.heightAnchor.constraint(equalTo: view.heightAnchor)
            expandHeight.priority = UILayoutPriority.defaultLow
            expandHeight.isActive = true
    
            // add scrollview to modal view
            modalView.addSubview(scrollView)
            scrollView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([scrollView.topAnchor.constraint(equalTo: modalView.topAnchor),
                                         scrollView.leftAnchor.constraint(equalTo: modalView.leftAnchor),
                                         scrollView.rightAnchor.constraint(equalTo: modalView.rightAnchor),
                                         scrollView.bottomAnchor.constraint(equalTo: modalView.bottomAnchor)])
    
    
            // add content to scrollview
            scrollView.addSubview(contentView)
            contentView.translatesAutoresizingMaskIntoConstraints = false
            NSLayoutConstraint.activate([contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
                                         contentView.widthAnchor.constraint(equalTo: modalView.widthAnchor),
                                         contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
                                         contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
                                         contentView.heightAnchor.constraint(equalToConstant: kTestContentHeight)])
            let contentBottom = contentView.bottomAnchor.constraint(equalTo: modalView.bottomAnchor)
            contentBottom.priority = .defaultLow
            contentBottom.isActive = true
        }
    
    }
    

    您可以通过两个约束相当简单地做到这一点


    • 约束1:ScrollView.height滚动视图没有固有的大小-您是否对其进行了子类化?@Wain。我没有对滚动视图进行子类化,但是由于
      UILabel
      确实有一个固有的内容大小,我正在尝试使滚动视图的内容视图根据其包含的标签的大小增加到一个点。如果你固定边缘,应该这样做,但这只是意味着你没有很好地解释你的问题…@Wain,对不起,我上次的评论不正确。内容视图的大小正在增加。我正在尝试使scrollview的父视图(以及滚动视图本身)随着内容视图的大小增加而增大。当父对象达到某个最大大小时
      override func viewWillLayoutSubviews() {
      
          scrollViewHeightConstraint?.constant = scrollView.contentSize.height     
      
          super.viewWillLayoutSubviews()
      }