在多行中将UIStackView中的项目包裹起来

问题描述 投票:0回答:1

我正在使用显示UITableView项的iOS应用。每行将显示具有不同宽度的标签列表(由​​标签的文本长度决定)。我可以将所有标签放置在水平UIStackView中,但我希望将它们包装在多行上,而不是一个可滚动的标签上。基本上,我对类似于FlexBox的flex-wrap属性的功能感兴趣。

我已附上图片以供参考。

enter image description here

任何想法如何实现这一目标?

ios autolayout uistackview
1个回答
0
投票

有很多不同的方法可以解决这个问题。

一种方法-not使用堆栈视图:

  • 将标签添加到“容器”视图中
  • x = 0y = 0开头
  • 循环遍历标签,计算新的x值(标签宽度+标签之间的期望间距)
  • 如果新的x将超过容器的边缘,请重置x = 0并将所需的高度添加到y以“移至下一行”
  • 放置标签后,设置容器视图的高度

这是一个简单的示例:

class TagLabelsViewController: UIViewController {

    let containerView: UIView = {
        let v = UIView()
        return v
    }()

    let tagNames: [String] = [
        "First Tag",
        "Second",
        "Third Tag",
        "Fourth",
        "The Fifth Tag",
        "Sixth",
        "Seventh",
        "Tag Eight",
        "Here are some Letter Tags",
        "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
        "Nine",
        "Ten",
        "Eleven",
        "Tag Twelve",
        "Tag 13",
        "Fourteen",
        "Fifteen",
        "Sixteen",
        "Seventeen",
        "Eightteen",
        "Nineteen",
        "Last Tag",
    ]

    var tagLabels = [UILabel]()

    let tagHeight:CGFloat = 30
    let tagPadding: CGFloat = 16
    let tagSpacingX: CGFloat = 8
    let tagSpacingY: CGFloat = 8

    // container view height will be modified when laying out subviews
    var containerHeightConstraint: NSLayoutConstraint = NSLayoutConstraint()

    override func viewDidLoad() {
        super.viewDidLoad()

        // add the container view
        view.addSubview(containerView)

        // give it a background color so we can see it
        containerView.backgroundColor = .yellow

        // use autolayout
        containerView.translatesAutoresizingMaskIntoConstraints = false

        // initialize height constraint - actual height will be set later
        containerHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: 10.0)

        // constrain container safe-area top / leading / trailing to view with 20-pts padding
        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            containerView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            containerView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            containerHeightConstraint,
        ])

        // add the buttons to the scroll view
        addTagLabels()

    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        // call this here, after views have been laid-out
        // this will also be called when the size changes, such as device rotation,
        // so the buttons will "re-layout"
        displayTagLabels()

    }

    func addTagLabels() -> Void {

        for j in 0..<self.tagNames.count {

            // create a new label
            let newLabel = UILabel()

            // set its properties (title, colors, corners, etc)
            newLabel.text = tagNames[j]
            newLabel.textAlignment = .center
            newLabel.backgroundColor = UIColor.cyan
            newLabel.layer.masksToBounds = true
            newLabel.layer.cornerRadius = 8
            newLabel.layer.borderColor = UIColor.red.cgColor
            newLabel.layer.borderWidth = 1

            // set its frame width and height
            newLabel.frame.size.width = newLabel.intrinsicContentSize.width + tagPadding
            newLabel.frame.size.height = tagHeight

            // add it to the scroll view
            containerView.addSubview(newLabel)

            // append it to tagLabels array
            tagLabels.append(newLabel)

        }

    }

    func displayTagLabels() {

        let containerWidth = containerView.frame.size.width

        var currentOriginX: CGFloat = 0
        var currentOriginY: CGFloat = 0

        // for each label in the array
        tagLabels.forEach { label in

            // if current X + label width will be greater than container view width
            //  "move to next row"
            if currentOriginX + label.frame.width > containerWidth {
                currentOriginX = 0
                currentOriginY += tagHeight + tagSpacingY
            }

            // set the btn frame origin
            label.frame.origin.x = currentOriginX
            label.frame.origin.y = currentOriginY

            // increment current X by btn width + spacing
            currentOriginX += label.frame.width + tagSpacingX

        }

        // update container view height
        containerHeightConstraint.constant = currentOriginY + tagHeight

    }

}

结果:

enter image description here

enter image description here

非常简单,使用代码中的注释,您应该能够将其适应您的需求。

如果您想使用“预先构建的”解决方案,也许具有更多功能,请搜索

swift left aligned tags view

产生很多匹配项。这个(与我无关)看起来很有趣:https://github.com/ElaWorkshop/TagListView

© www.soinside.com 2019 - 2024. All rights reserved.