【问题标题】:Programmatically add views one after another以编程方式一个接一个地添加视图
【发布时间】:2018-01-29 06:19:29
【问题描述】:

我是 Swift 新手(使用 4 个版本)。 我有 HTML 文本,里面可以包含图片链接。

some text 
<img src=""/>
some text

我想让内容可滚动,所以我将容器(简单的 UIView)包装到 UIScrollview。

然后我将 HTML 文本解析为多个部分:“文本”和“图像链接”到一个数组(数据和类型)中。 然后遍历我观察的那个数组,如果类型是文本 - 我输入带有约束的标签:

如果它是容器的第一个元素,那么左、上、右、下是匹配的。 如果不是,则 top 匹配容器中前一个视图的底部(如链)。

但由于某种原因,它不起作用。 我究竟做错了什么? 我把我的代码:

    var lastView = containerView!
    var label : UILabel
    var imageView : UIImageView

    for item in articleContent {
        if (item.type == RenderDetailBlogObject.TYPE_TEXT) {
            label = UILabel()

            label.numberOfLines = 0
            label.attributedText = item.data.html2AttributedString
            containerView.addSubview(label)

            label.translatesAutoresizingMaskIntoConstraints = false

            NSLayoutConstraint.activate([
                label.leftAnchor.constraint(equalTo: containerView.leftAnchor),
                label.rightAnchor.constraint(equalTo: containerView.rightAnchor),
                ])

            if (lastView == containerView) {
                print("ADDING LABEL lastView == containerView")
                label.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0).isActive = true
            } else {
                  print("ADDING LABEL lastView != containerView")
                 label.topAnchor.constraint(equalTo: lastView.bottomAnchor, constant: 0.0).isActive = true
            }

            lastView = label
        } else {
            imageView = UIImageView()

            imageView.sd_setImage(with: URL(string: item.data))
            containerView.addSubview(imageView)

            imageView.translatesAutoresizingMaskIntoConstraints = false

            NSLayoutConstraint.activate([

                imageView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
                imageView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
                ])

            if (lastView == containerView) {
                print("ADDING AN IMAGE lastView == containerView")
                 imageView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0).isActive = true
            } else {
                 print("ADDING AN IMAGE lastView != containerView")
                imageView.topAnchor.constraint(equalTo: lastView.bottomAnchor, constant: 0.0).isActive = true
            }

            lastView = imageView
        }

        lastView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0.0)
    }

编辑: 代码似乎是正确的,并且视图添加正确,但约束不允许滚动视图。

我测试了约束(中心 Y - 向它添加了 200 多个范围并开始滚动,但它是硬编码值,所以它可能有更合法的解决方案吗?) 没有这个约束,它就会出错并且根本不起作用。

【问题讨论】:

  • 使用UIWebview或WKWebView显示html
  • 它没有提供任何定制的可能性

标签: ios swift uiscrollview autolayout


【解决方案1】:

我相信这条线是你的麻烦来源:

lastView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0.0)

现在,当您遍历项目时,您将每个标签/图像视图约束为将底部锚点约束到 containerView 的底部。我希望这会导致不可满足的约束警告(检查您的控制台)。您想要约束添加到容器的最后一个标签/imageView 的底部。因此,只需将该行移出其后面的 for 循环即可:

var lastView = containerView!
var label : UILabel
var imageView : UIImageView

for item in articleContent {
    if (item.type == RenderDetailBlogObject.TYPE_TEXT) {
        label = UILabel()

        label.numberOfLines = 0
        label.attributedText = item.data.html2AttributedString
        containerView.addSubview(label)

        label.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            label.leftAnchor.constraint(equalTo: containerView.leftAnchor),
            label.rightAnchor.constraint(equalTo: containerView.rightAnchor),
            ])

        if lastView == containerView {
            print("ADDING LABEL lastView == containerView")
            label.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0).isActive = true
        } else {
              print("ADDING LABEL lastView != containerView")
            label.topAnchor.constraint(equalTo: lastView.bottomAnchor, constant: 0.0).isActive = true
        }

        lastView = label
    } else {
        imageView = UIImageView()

        imageView.sd_setImage(with: URL(string: item.data))
        containerView.addSubview(imageView)

        imageView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([

            imageView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
            imageView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
            ])

        if lastView == containerView {
            print("ADDING AN IMAGE lastView == containerView")
            imageView.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0).isActive = true
        } else {
            print("ADDING AN IMAGE lastView != containerView")
            imageView.topAnchor.constraint(equalTo: lastView.bottomAnchor, constant: 0.0).isActive = true
        }

        lastView = imageView
    }
}
// Constrain the bottom only for the last view that was added
lastView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor, constant: 0.0).isActive = true

如果根据这个答案进行重构不能解决滚动问题,我建议检查containerView 和scrollView 之间的约束 - 您可以使用this answer 作为参考。

【讨论】:

  • "label.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 0.0) 与 label.topAnchor.constraint(equalTo: lastView.bottomAnchor, constant: 0.0) 相同”。是否会发生这种情况,因为此时 containerView 的高度为 0,并且底部和顶部当时相等。我想,当我在里面添加一些东西时——容器的底部和顶部会有所不同。它是否只记得底部(和顶部)所在的点,即使在底部更改后,该点也会相同?
  • @Vadim 哦,我现在才注意到它的底部和顶部,我的错误.. 你之前的代码是正确的,我的错误,我会尽快编辑答案
  • @Vadim 好的,我修正了答案.. 很好,你怀疑我的代码 :)
  • 谢谢)代码现在很好(我编辑了一些更改的帖子)并且约束“中心 Y”不让我滚动(它自动向后滚动):(虽然没有那个约束滚动根本不起作用.
  • @Vadim 不要在 scrollView 中对 containerView 使用 centerY 和 centerX .. 将 containerView 的左右锚点约束到与您约束 scrollView 左右两侧的视图相同的视图(但不是 scrollView 本身) , 并将顶部和底部约束到 scrollView 的顶部和底部锚点 - 请参阅此答案以供参考:stackoverflow.com/questions/48321859/… 虽然我认为在 x 轴的情况下,您也可以使用 centerX + width 锚点,但绝对不能用于 y 轴.. .
【解决方案2】:

也许更简洁的方法是在滚动视图中使用UIStackView,这样您就可以将任何其他视图作为子视图添加到UIStackView。这样你就不必自己处理约束了。

所以您的视图层次结构应该类似于下面的内容。

->UIView
    ->UIScrollView
        ->UIView
            ->UIStackView

然后将约束添加到 scrollView 为 top-left-bottom-right

另外添加另一个 UIView 到 UIScrollView 作为 Wrapper View 并将约束添加为 top-left-bottom-right 并添加两个约束到此 wrapper view 等于宽度 并且 等于高度 相对于主视图。这将使UIScrollView 使用动态高度,更多信息请参见post

现在将约束添加到堆栈视图,因为 top-left-right-bottom 还添加了带有插座连接的高度约束。

现在,当您将任何视图添加到堆栈视图时,只需更改 UIStackView 的高度常量,您的 UIScrollView 就会自动扩展。

【讨论】:

  • 好点也。但是 Scroll 和 Stack 之间的 UIView 真的需要吗?
  • 这取决于你是否想要一个只有垂直滚动的滚动视图,然后在两者之间有一个与父级宽度相等的视图将阻止滚动视图水平滚动,它还有助于管理滚动看来只有独生子女要处理,也是各论坛很多人建议的,你可以自己去看看!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2023-03-11
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
相关资源
最近更新 更多