【问题标题】:UIScrollViews and anchors swiftUIScrollViews 和快速锚点
【发布时间】:2017-01-19 09:03:24
【问题描述】:

我在设置滚动视图和实际向下滚动时遇到问题。我用一些文本字段填充滚动视图并使用锚点(topanchor、leftanchor...)将它们定位在滚动视图内。即使我将滚动视图高度设置为 1000,它实际上也不会移动,它会继续显示相同的项目,滚动指示器确实会下降,但内容本身不会,我已经将滚动视图设置为启用滚动,并委托给自己。

我认为问题可能出在锚点上,但是我将如何在滚动视图中排列我的项目,任何建议都会得到极大的赞赏。

编辑:下面的代码表示应用于滚动视图( inputContainer )的锚点,img 对应于 UIImageView,而 mainContainer 对应于包含 img 和 inputContainer 的 UIView。

inputContainer.topAnchor.constraintEqualToAnchor( img.bottomAnchor ).active = true
inputContainer.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true

inputContainer.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor ).active = true

inputContainerBottomConstraint = inputContainer.bottomAnchor.constraintEqualToAnchor( cancelButton.topAnchor )
inputContainerBottomConstraint?.active = true

编辑:这就是代码的样子:

class SView : UIView, UITextFieldDelegate, UIScrollViewDelegate {

let mainContainer : UIView = {
    let v = UIView()
    v.backgroundColor = .whiteColor()
    v.layer.cornerRadius = 8
    v.layer.masksToBounds = true
    v.translatesAutoresizingMaskIntoConstraints = false
    return v
}()

let Img : UIImageView = {
    let img = UIImageView()
    img.image = UIImage(named: "noImage")
    img.backgroundColor = .blueColor()
    img.translatesAutoresizingMaskIntoConstraints = false
    img.contentMode = .ScaleAspectFill
    img.clipsToBounds = true
    return img
}()

let inputContainer : UIScrollView = {
    let ic = UIScrollView()
    ic.backgroundColor = .whiteColor()
    ic.translatesAutoresizingMaskIntoConstraints = false
    return ic
}()

let datePickerTextField : UITextField = {
    let tf = UITextField()
    tf.placeholder = "Fecha"
    tf.textAlignment = .Center
    tf.translatesAutoresizingMaskIntoConstraints = false
    return tf
}()

let tagsTextField : UITextField = {
    let tf = UITextField()
    tf.placeholder = "Tags"
    tf.textAlignment = .Center
    tf.clearButtonMode = .Always
    tf.translatesAutoresizingMaskIntoConstraints = false
    return tf
}()

lazy var cancelButton : UIButton = {
    let button = UIButton()
    button.backgroundColor = UIColor.rgb(255, green: 65, blue: 65, alpha: 1)
    button.setTitle("Cancelar", forState: .Normal)
    button.tintColor = .whiteColor()
    button.translatesAutoresizingMaskIntoConstraints = false

    button.addTarget( self , action: #selector(handleCancelButtonPressed), forControlEvents: .TouchUpInside)

    return button
}()

lazy var publicarButton : UIButton = {
    let button = UIButton()
    button.backgroundColor = UIColor.rgb(0 , green: 204, blue: 102, alpha: 1)
    button.setTitle("Publicar", forState: .Normal)
    button.tintColor = .whiteColor()
    button.translatesAutoresizingMaskIntoConstraints = false

    button.addTarget( self , action: #selector(handlePublicarButtonPressed), forControlEvents: .TouchUpInside)

    return button
}()


override init(frame: CGRect)
{
    super.init(frame: frame)

    inputContainer.delegate = self


    datePickerTextField.delegate = self

    tagsTextField.delegate = self

    setupMainContainer()
    setupImg()
    setupButtons()
    setupInputContainer()

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

func setupMainContainer ()
{
    addSubview(mainContainer)

    mainContainer.centerXAnchor.constraintEqualToAnchor( centerXAnchor ).active = true
    mainContainer.centerYAnchor.constraintEqualToAnchor( centerYAnchor ).active = true

    mainContainer.widthAnchor.constraintEqualToAnchor( widthAnchor ).active = true
    mainContainer.heightAnchor.constraintEqualToAnchor( heightAnchor )
}

func setupImg ()
{
    mainContainer.addSubview(Img)

    Img.topAnchor.constraintEqualToAnchor( mainContainer.topAnchor ).active = true
    Img.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true

    Img.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor ).active = true
    Img.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor , multiplier: 0.3).active = true
}

var inputContainerBottomConstraint : NSLayoutConstraint?

func setupInputContainer ()
{
    mainContainer.addSubview(inputContainer)

    inputContainer.topAnchor.constraintEqualToAnchor( Img.bottomAnchor ).active = true
    inputContainer.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true
    inputContainer.rightAnchor.constraintEqualToAnchor( mainContainer.rightAnchor ).active = true
    inputContainerBottomConstraint = inputContainer.bottomAnchor.constraintEqualToAnchor( cancelButton.topAnchor )
    inputContainerBottomConstraint?.active = true



    inputContainer.addSubview( datePickerTextField )
    inputContainer.addSubview( tagsTextField )




    datePickerTextField.topAnchor.constraintEqualToAnchor( inputContainer.topAnchor ).active = true
    datePickerTextField.centerXAnchor.constraintEqualToAnchor( inputContainer.centerXAnchor ).active = true

    datePickerTextField.widthAnchor.constraintEqualToAnchor( inputContainer.widthAnchor ).active = true
    datePickerTextField.heightAnchor.constraintEqualToAnchor( inputContainer.heightAnchor, multiplier: 0.2 ).active = true


    tagsTextField.bottomAnchor.constraintEqualToAnchor( inputContainer.bottomAnchor ).active = true
    tagsTextField.centerXAnchor.constraintEqualToAnchor( inputContainer.centerXAnchor ).active = true

    tagsTextField.widthAnchor.constraintEqualToAnchor( inputContainer.widthAnchor ).active = true
    tagsTextField.heightAnchor.constraintEqualToAnchor( inputContainer.heightAnchor, multiplier: 0.2 ).active = true

}

func setupButtons()
{
    mainContainer.addSubview( cancelButton )
    mainContainer.addSubview( publicarButton )


    cancelButton.bottomAnchor.constraintEqualToAnchor( mainContainer.bottomAnchor).active = true
    cancelButton.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true

    cancelButton.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor, multiplier:  0.5 ).active = true
    cancelButton.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor, multiplier:  0.1).active = true



    publicarButton.bottomAnchor.constraintEqualToAnchor( mainContainer.bottomAnchor).active = true
    publicarButton.leftAnchor.constraintEqualToAnchor( cancelButton.rightAnchor ).active = true

    publicarButton.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor, multiplier:  0.5 ).active = true
    publicarButton.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor, multiplier:  0.1).active = true
} }

因此,当键盘出现时,滚动视图的底部锚常量会发生变化,因此键盘“顶部锚”是新的底部锚。

【问题讨论】:

  • 什么是imginputContainermainContainer?如果不了解更多有关视图层次结构的信息,很难知道您是否有正确的约束。如果这就是你设置的所有约束,它似乎不足以满足布局引擎。
  • input container是滚动视图本身,img是UIimageview,mainContainer是inputcontainer(scrollview)所在的uiview。
  • @beyowulf 感谢您的回复,我缺少什么限制?我以为我用这些约束设置了所有可能的歧义,topAnchor 代表 y,leftAnchor 代表 x,width 代表宽度,高度由顶部和底部约束推导出来。我仍然认为问题在于使用锚点设置 inputContainer 的内容,但我不知道我还有什么其他选择
  • 好的。这将满足滚动视图的框架,但是滚动视图的内容似乎是您的问题所在?
  • @beyowulf 滚动视图中的每个文本字段都有一个顶部、左侧、宽度和高度锚点。问题依赖于这些文本字段不响应对滚动视图框架所做的任何更改。换句话说,当尝试向下滚动时,滚动视图指示器实际上是向下滚动的,但它一直显示相同的文本字段,因此它并没有真正移动滚动视图的内容。

标签: ios uiscrollview swift2 autolayout nslayoutconstraint


【解决方案1】:

由于您描述的约束,布局引擎无法确定滚动视图的内容高度。您应该将底部文本字段固定到滚动视图的底部。这样,滚动视图的内容大小将调整为所有文本字段的最大值。下面是一些你可以放在操场上查看的代码:

import UIKit
import XCPlayground

let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
scrollView.backgroundColor = UIColor.whiteColor()

let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.backgroundColor = UIColor.purpleColor()

let otherTextField = UITextField()
otherTextField.translatesAutoresizingMaskIntoConstraints = false
otherTextField.backgroundColor = UIColor.purpleColor()

let otherOtherTextField = UITextField()
otherOtherTextField.translatesAutoresizingMaskIntoConstraints = false
otherOtherTextField.backgroundColor = UIColor.purpleColor()

scrollView.addSubview(textField)

textField.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
textField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
textField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true

scrollView.addSubview(otherTextField)

otherTextField.topAnchor.constraintEqualToAnchor(textField.bottomAnchor, constant: 60).active = true
otherTextField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
otherTextField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true

scrollView.addSubview(otherOtherTextField)
otherOtherTextField.topAnchor.constraintEqualToAnchor(otherTextField.bottomAnchor, constant: 60).active = true
otherOtherTextField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
otherOtherTextField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
otherOtherTextField.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true

scrollView.setNeedsLayout()

XCPlaygroundPage.currentPage.liveView = scrollView

这会将三个文本字段放置在滚动视图中,中心与顶部和底部之间有 60 个点。如果你注释掉:

otherOtherTextField.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true

助手编辑器中的滚动视图不会滚动,但会滚动。

【讨论】:

  • 我将最后一个文本字段底部锚点更改为滚动视图底部锚点,但仍然没有...也许它与您设置滚动视图框架矩形有关,而我只是锚定???跨度>
  • 如果不查看更多代码或视图层次结构的屏幕截图,很难知道发生了什么。您所做的与我发布的代码不相似吗?
  • 我的代码和你的唯一区别是我没有像你那样设置滚动视图框架,我只是为它设置了锚点。当尝试将框架设置为您但取决于设备框架时,它不会让我..当我打印框架时它说它是 0,我不知道它是否因为代码在 UIView 内而不是在 UIViewController 中。但它一直打印 0
  • 回家后我会更新帖子,添加更多代码。谢谢你帮助我!真的很感激
  • 我不明白你的布局。你希望你的输入容器看起来像什么?事实上,您的标签文本字段没有 y 位置,这就是它不显示的原因。此外,您将文本字段的高度设置为滚动视图框架高度的 20% 20 + 20 = 40。只有当滚动视图的内容超过其框架高度或宽度的 100% 时,滚动视图才会滚动。跨度>
猜你喜欢
  • 2016-12-30
  • 2019-06-03
  • 2020-04-01
  • 2011-06-07
  • 2018-05-13
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多