0

I wan't to draw tags on the screen and put them from left to the right and in the case where there are too many for 1 line go to the newline. Like this :

Image of example of what I need

Currently I'm stuck I don't know how to get the width of label after it's compute by constraints. I need to find tagWidth

enum TagPosition {
    case left_top
    case left
    case top
    case other
}

func createProductTags() {
    var lineWidth: CGFloat = 8.0
    var line = 0
    var lastTag: UIView = self.contentView
    var position = TagPosition.other
    var viewAbove = self.contentView

    for i in 0..<menu.tagName.count {
        if (line == 0 && lineWidth == 8.0) {
            position = TagPosition.left_top
        } else if (line == 0) {
            position = TagPosition.top
        } else if (lineWidth == 8.0) {
            position = TagPosition.left
        } else {
            position = TagPosition.other
        }
        self.tag = setTagSettings(named: menu.tagName[i], position: position)
        var tagConstraints = setTagConstraints(lastTag: lastTag, viewAbove: viewAbove, position: position)
        lineWidth += tagWidth + 8.0
        if (lineWidth > self.contentView.bounds.width - 16) {
            viewAbove = lastTag
            updateConstraintWhenNewLine(tagConstraints: &tagConstraints, viewAbove: viewAbove)
            line += 1
            lineWidth = tagWidth + 16.0
        }
        lastTag = self.tag
    }
    // To fit the contentView to the last line of tags
    lastTag.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor).isActive = true
}

func updateConstraintWhenNewLine(tagConstraints: inout [NSLayoutConstraint], viewAbove: UIView) {
    // Change constraints of last label of the line if it doesn't fit on the line
    //Remove old contraints
    topConstraint.isActive = false
    leftConstraint.isActive = false
    tagConstraints.remove(object: topConstraint)
    tagConstraints.remove(object: leftConstraint)
    self.tag.removeConstraints([topConstraint, leftConstraint])

    //Add old contraints
    topConstraint = self.tag.topAnchor.constraint(equalTo: viewAbove.bottomAnchor, constant: 8)
    leftConstraint = self.tag.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 16)
    tagConstraints.append(contentsOf: [topConstraint, leftConstraint])
    NSLayoutConstraint.activate([topConstraint, leftConstraint])
}

func setTagSettings(named tagName: String, position: TagPosition) -> UIView {
    // tagContainer settings
    let tagContainer = UIView()
    tagContainer.backgroundColor = DiscoderyAppSettings.sharedInstance.primaryColor
    tagContainer.layer.masksToBounds = true
    tagContainer.layer.cornerRadius = self.tagHeight / 2
    tagContainer.translatesAutoresizingMaskIntoConstraints = false
    self.contentView.addSubview(tagContainer)

    // tagLabel settings
    let tagLabel = UILabel()
    tagLabel.text = tagName
    tagLabel.font?.withSize(16.0)
    tagLabel.textColor = UIColor.white
    tagLabel.textAlignment = .center
    tagLabel.translatesAutoresizingMaskIntoConstraints = false
    tagContainer.addSubview(tagLabel)

    // tagLabel constraints
    tagLabel.topAnchor.constraint(equalTo: tagContainer.topAnchor).isActive = true
    tagLabel.leftAnchor.constraint(equalTo: tagContainer.leftAnchor, constant: 8).isActive = true
    tagLabel.rightAnchor.constraint(equalTo: tagContainer.rightAnchor, constant: -8).isActive = true
    tagLabel.bottomAnchor.constraint(equalTo: tagContainer.bottomAnchor).isActive = true

    return tagContainer
}

func setTagConstraints(lastTag: UIView, viewAbove: UIView, position: TagPosition) -> [NSLayoutConstraint] {

    var tagConstraints: [NSLayoutConstraint] = [NSLayoutConstraint]()
    heightConstraint = self.tag.heightAnchor.constraint(equalToConstant: tagHeight)

    switch position {
    case .left_top:
        topConstraint = self.tag.topAnchor.constraint(equalTo: self.contentView.topAnchor)
        leftConstraint = self.tag.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 16)
    case .left:
        topConstraint = self.tag.topAnchor.constraint(equalTo: viewAbove.bottomAnchor, constant: 8)
        leftConstraint = self.tag.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 16)
    case .top:
        topConstraint = self.tag.topAnchor.constraint(equalTo: self.contentView.topAnchor)
        leftConstraint = self.tag.leftAnchor.constraint(equalTo: lastTag.rightAnchor, constant: 8)
    default:
        topConstraint = self.tag.topAnchor.constraint(equalTo: viewAbove.bottomAnchor, constant: 8)
        leftConstraint = self.tag.leftAnchor.constraint(equalTo: lastTag.rightAnchor, constant: 8)
    }
    tagConstraints.append(contentsOf: [heightConstraint, topConstraint, leftConstraint])
    NSLayoutConstraint.activate(tagConstraints)
    return constraints
}

createProductTags() is called in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)

If you need any other detail ask me. Thank you

bdurst
  • 3
  • 3
  • Please change your variable names to camelcasing. not self.Tag but self.tag. Not TabLabel but tagLabel. – J. Doe May 29 '18 at 10:07
  • You can simple use label.frame.width after the AutoLayout engine did its job. – Jan Erik Schlorf May 29 '18 at 10:14
  • 1
    You can use UICollectionView with custom cells. It will be less painful for you. – Maksym Musiienko May 29 '18 at 16:07
  • Yes. as @MaksymMusiienko pointed out. why don't you use [UICollectionView](https://developer.apple.com/documentation/uikit/uicollectionview?changes=_4) – Awais Fayyaz May 30 '18 at 05:56
  • You can get a lot of help regarding collection view. e.g [This](https://medium.com/@michaelrojas_66889/how-to-make-a-custom-collection-view-cell-in-swift-6d5783ab7c1c) Use horizontal layout of collection view. And implement `SizeForItemAtIndexPath` delegate function. And return size of each label in this function Calculate the width of label based on string. you will find plenty of solutions for this also. like [this](https://stackoverflow.com/a/26568136/7698092) And use a constant height like e.g 40, then `return CGSize(width: calculatedWidth`, height: constantHeight)' in function – Awais Fayyaz May 30 '18 at 06:02

0 Answers0