1

Alright, so Im working in Swift 3 here and Im new to uicollectionviews. I am trying to programmatically add a label as a subview of a header UICollectionReusableView in my collection view. I have added the label like any other view, but I cant for the life of me CENTER the label on the header.

Here is my label code in the custom header class, which is added to the header in the storyboard:

let pointsLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.customInit()
    }


    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        self.customInit()
    }

    func customInit() {

        //center inside content
        pointsLabel.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: 100)
    pointsLabel.center = CGPoint(x: self.bounds.width * 0.5, y: self.bounds.height * 0.5)
    pointsLabel.textColor = UIColor.darkGray
    pointsLabel.textAlignment = .center

        pointsLabel.text = "Testing 123"
        pointsLabel.font = UIFont(name: "Montserrat", size: 30)
        self.addSubview(pointsLabel)

    }

My Collectionview does have a margin on either side:

self.collectionView.contentInset = UIEdgeInsets(top: 0, left: 32.5, bottom: 0, right: 32.5)

However that should just affect the size of the header view, meaning the label should still be centered at the header.bounds.width * 0.5. And I centered the text alignment, yet the text is skewed to the left:

enter image description here

If it helps, my collection view is within an message app extension, but again I don't know how that would change things. What is wrong here?

Even with:

pointsLabel.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: 100)
    //pointsLabel.center = CGPoint(x: self.bounds.width * 0.8, y: self.bounds.height * 0.5)
        pointsLabel.center = self.center
        pointsLabel.textColor = UIColor.darkGray
        pointsLabel.backgroundColor = UIColor.blue

Or changing my width to less, I get:

enter image description here

Why?

blue
  • 7,175
  • 16
  • 81
  • 179
  • Have you tried `pointsLabel.center = self.center`? You may also want to solve this problem by not setting the center property at all. Since you are setting the text alignment to .center you are essentially already centering the text. The only thing missing is that the width of your label is not correct. You can check this be either setting the background color on `pointsLabel` or by using the Xcode UI debugger. – werm098 Oct 12 '16 at 05:32
  • Check my edit - still offset to left – blue Oct 12 '16 at 12:58
  • It looks like the offset is the same as the left and right padding in the contentInset (32.5). If you set the x coordinate of the `pointsLabel` frame to 32.5 and remove the line that sets the center property then you should have a centered label. – werm098 Oct 12 '16 at 13:16
  • If you added your label to your storyboard using auto layout constraints, then changing the frame won't work. – Lucho Oct 12 '16 at 13:32
  • @werm098 what do you mean set the x coordinate? You cant set just the center.x alone – blue Oct 12 '16 at 15:16
  • change `pointsLabel.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: 100)` to `pointsLabel.frame = CGRect(x: 32.5, y: 0, width: self.bounds.width, height: 100)` – werm098 Oct 12 '16 at 15:18
  • Nope, it is still skewed to one side – blue Oct 12 '16 at 15:23
  • You have removed `pointsLabel.center = self.center ` right? – werm098 Oct 12 '16 at 15:28
  • yes, I only included the frame – blue Oct 12 '16 at 15:39
  • If you want to upload source code that reproduces the issue I would take look at it for you. – werm098 Oct 12 '16 at 16:32

2 Answers2

1

If you have both header and footer so You may replace viewForSupplementaryElementOfKind function with below code

 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

       switch kind {
        case UICollectionElementKindSectionHeader:

            let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier:
            headerId, for: indexPath) as! CustomHeader
            return header

        default:
            return UIHeaderView()
        }
}
prachit
  • 365
  • 3
  • 10
0

You can use Swift anchoring system to have the label fill the header. You can create your own custom header class like such. The way the anchoring works it'll set constraints on the label to expand to the top, left, right and bottom of the view no matter the size. By adding the constants [32.5 and -32.5] to the left and right anchor it'll add the insets spacing you're looking for. Hope this helps.

Custom Header Class

class CustomHeader: UICollectionViewCell {

    let pointsLabel: UILabel = {
     let n = UILabel()
         n.textColor = UIColor.darkGray
         n.textAlignment = .center
         n.text = "Testing 123"
         n.font = UIFont(name: "Montserrat", size: 30)
     return n
   }()

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

     pointsLabel.translatesAutoresizingMaskIntoConstraints = false
     pointsLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 32.5).isActive = true
     pointsLabel.rightAnchor.constraint(equalTo: rightAnchor, constant: -32.5).isActive = true
     pointsLabel.topAnchor.constraint(equalTo: topAnchor).isActive = true
     pointsLabel.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
   }
}

ViewController that uses this header you can register and declare the width and height you would like the header to be like below. So which every class you have that's to use the custom header add the below functions to your file and it should give you what you're looking for. =]

class ControllerUsesHeader: UICollectionViewController {
  let headerId = "headerId"

  override func viewDidLoad() {
   super.viewDidLoad()

   collectionView?.register(CustomHeader.self, forSupplementaryViewOfKind:
        UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
  }


  override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind:
    String, at indexPath: IndexPath) -> UICollectionReusableView {
        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier:
            headerId, for: indexPath) as! CustomHeader
        return header
      }

} 

extension ControllerUsesHeader: UICollectionViewDelegateFlowLayout {
  func collectionView(_ collectionView: UICollectionView, layout 
    collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection 
    section: Int) -> CGSize {
    return CGSize(width: view.frame.width, height: 100)
}
antdwash
  • 516
  • 4
  • 10