【问题标题】:ScrollView inside StackViewStackView 内的滚动视图
【发布时间】:2018-01-23 14:29:44
【问题描述】:

我创建了垂直stackView: screenshot

并在其中添加scrollView:

let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.contentMode = .scaleToFill
scrollView.clipsToBounds = true
self.addArrangedSubview(scrollView)
scrollView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
scrollView.heightAnchor.constraint(equalToConstant: 100).isActive = true

在这个scrollView里面我添加了水平scrollView:

let imageStack = UIStackView()
imageStack.spacing = 5
imageStack.axis = .horizontal
imageStack.alignment = .center
imageStack.contentMode = .left
imageStack.distribution = .fillProportionally
imageStack.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(imageStack)
imageStack.heightAnchor.constraint(equalToConstant: 100).isActive = true
imageStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
imageStack.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
imageStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
imageStack.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true

在这个 imageStack 中,我以编程方式插入图像。但是当有很多图像(超过 4 个)时,它们会相互叠加并且滚动不起作用。

是否可以在垂直 stackView 内使用水平滚动来排列子视图?或者子视图的宽度不可能超过垂直stackView的宽度?

已编辑

我尝试编辑约束条件,例如 @beyowulf 推荐,但没有任何改变。看看screenshot。我在 imageStack 中添加了 5 张图片,但如果它们和滚动不起作用,则只有部分可见

已编辑 查看我找到 imageStack 的代码并将图像添加到其中:

let scrollView = self.dynamicView.subviews.first(where: {$0 is UIScrollView}) as! UIScrollView
let filesView = scrollView.subviews.first(where: { $0 is UIStackView } ) as! UIStackView
var filesCount = filesView.arrangedSubviews.count - 1

for image in images {
    let imgView = UIImageView()
    imgView.translatesAutoresizingMaskIntoConstraints = false
    let imageViewWidthConstraint = NSLayoutConstraint(item: imgView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100)
    let imageViewHeightConstraint = NSLayoutConstraint(item: imgView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 100)
    imgView.addConstraints([imageViewWidthConstraint, imageViewHeightConstraint])
    imgView.contentMode = .scaleAspectFill
    imgView.clipsToBounds = true
    imgView.image = image
    imgView.isUserInteractionEnabled = true
    let swipeToTopRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(imageDelete))
    swipeToTopRecognizer.direction = .up
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
    imgView.addGestureRecognizer(tapRecognizer)
    imgView.addGestureRecognizer(swipeToTopRecognizer)
    filesView.insertArrangedSubview(imgView, at: filesCount)
    filesCount += 1
}

【问题讨论】:

  • 您可以尝试将fillProportionally 更改为.fill 吗?看看它是否有效?
  • 在滚动视图中添加一个 contentView 并将其限制为所需的高度。将宽度设置为 >= stackview.widthAnchor。将所有子视图添加到滚动视图。这将允许滚动视图根据其内容调整大小,并且堆栈视图将正确约束它。
  • @Honey,我试过了,但没有任何改变
  • 对不起。那我不知道。

标签: ios swift swift4


【解决方案1】:

如果您的目标是 iOS 11 或更高版本,您可以使用 UIScrollViewcontentLayoutGuideframeLayoutGuide 来区分何时要约束滚动视图的内容或滚动视图的框架。例如这里:

scrollView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0).isActive = true
scrollView.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0).isActive = true
scrollView.heightAnchor.constraint(equalToConstant: 100).isActive = true

例如,您可以尝试:

scrollView.frameLayoutGuide.heightAnchor.constraint(equalToConstant: 100).isActive = true
scrollView.frameLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true

您正在添加更适合应用于滚动视图框架的约束。在这里:

imageStack.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true
imageStack.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
imageStack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0).isActive = true
imageStack.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true

您正在添加更恰当地决定滚动视图的内容大小的约束。

例如,您可以尝试:

imageStack.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: 0).isActive = true
imageStack.leftAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leftAnchor, constant: 0).isActive = true
imageStack.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: 0).isActive = true
imageStack.rightAnchor.constraint(equalTo: scrollView.contentLayoutGuide.rightAnchor, constant: 0).isActive = true

话虽如此,您添加的约束超出了绝对必要的数量,这通常是不好的并且可能导致布局冲突。如果您要向UIStackView 添加排列的子视图,您实际上应该只添加大小约束,因为定位将由axisalignmentdistributionspacing 的组合确定。相反,使用imageStack 的约束,当您固定四个边时,您不需要添加尺寸约束,因为这将由引脚约束决定。

另外,请注意控制台记录布局错误。如果有的话,你可以试试wtf autolayout 让它们更具可读性。

【讨论】:

  • 也许您可以发布更多代码。从发布的内容很难判断。
  • 我发布了。也许它会有用,但我不确定
【解决方案2】:

这是因为我将 imageStack 添加到垂直 stackView 两次:

//here i did it first time 
//(part of addMultiFileField method you can see above, in first post)
self.dynamicView.addMultiFileField(forProperty: property)
let scrollView = self.dynamicView.subviews.first(where: { $0 is UIScrollView } ) as! UIScrollView
let stackView = scrollView.subviews.first(where: { $0 is UIStackView }) as! UIStackView
let addButton = stackView.subviews.first(where: { $0 is UIButton } ) as! UIButton
addButton.isUserInteractionEnabled = true
self.oneFileOnly = false
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.addFiles))
addButton.addGestureRecognizer(tapRecognizer)

//and here i did it second time. this line stay here from previous realization and i forgot comment it
self.dynamicView.addArrangedSubview(stackView)

最后我删除了最后一行,现在滚动工作正常

感谢大家的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-29
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多