UICollectionReusableView Header not resizing on rotation - constraints? - ios

I have a UICollectionReusableView for a UICollectionView Header Section in code as follows:
var headingLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
headingLabel = UILabel(frame: CGRectMake(12.0,12.0,frame.width,21.0))
headingLabel.numberOfLines = 1
headingLabel.textAlignment = NSTextAlignment.Center
headingLabel.textColor = UIColor.blackColor()
self.backgroundColor = UIColor.whiteColor()
self.addSubview(headingLabel)
}
I just want the heading to be centered in the display. This is fine so long as I don't rotate the device. If I rotate the device, the label is no longer in the center of the screen.
My guess is this is super simple, I just can't seem to find the answer. My assumption is that I could just programatically add constraints, but I can't quite work out how to do that.
Alternatively, I think there might be some way to force it to redo the headers on a layout change, but I couldn't get that working either.
Any pointers in the right direction would be hugely appreciated.
Many thanks.

You have to invalidate the layout BEFORE the collectionView is re-laid out (which happens in viewDidLayoutSubviews), therefore you must invalidate it in viewWillLayoutSubviews.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// Handle rotation
collectionView.collectionViewLayout.invalidateLayout()
}

import Foundation
import UIKit
import MaterialComponents
class SectionHeaderAppointment:UICollectionReusableView {
var sectionHeaderlabel: UILabel!
var nameflatButton:MDCButton!
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
print("Rotation")
sectionHeaderlabel.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
nameflatButton.frame = CGRect(x: (frame.width - (frame.width/3))/2, y: 6, width: frame.width/3, height: frame.height - 8)
}
}

Related

Swift custom xib file is not centered correctly

I am having problems with my Xib UIView.I created an xib view, added it to a uiview class, and then called this class in the main viewcontroller. In my xib view I created a label which is centered there directly in the center. Only when I start my project is the view no longer displayed in the center:
Look
But this is what my view looks like in the xib file:
Look
Could it be that it is because of the navigation controller? Although I don't think so, because I also added the navigation controller to my xib file. By the way, my custom view is added to a scrollview in my main viewcontroller.
This is my custom view class:
import UIKit
class TimerView: UIView {
#IBOutlet var contentView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
private func commonInit() {
Bundle.main.loadNibNamed("TimerView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = bounds
contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
}
and there I added it to the scrollview:
func setUpScrollView() {
sequenzeScrollView.contentSize = CGSize(width: view.frame.size.width * 3, height: 0)
sequenzeScrollView.isPagingEnabled = true
sequenzeScrollView.showsVerticalScrollIndicator = false
sequenzeScrollView.showsHorizontalScrollIndicator = false
sequenzeScrollView.delegate = self
for i in 0..<3 {
let timerView = TimerView(frame: CGRect(x: view.frame.size.width * CGFloat(i), y: 0, width: view.frame.size.width, height: view.frame.size.height))
sequenzeScrollView.addSubview(timerView)
}
}
can someone help me with this? I would be really happy about that! Love greetings

Collection Cell Content Size

I added a view as parent red view in CollectionViewCell and the next blue subview at the center of the parent view. It works correctly and the sub view goes at the center of the parent view before collection cell size is not changed. But, The cell size is changed by conforming the method from UICollectionViewDelegateFlowLayout protocol and the view is not centered of the cell correctly. How I can solve this issue ?
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
self.circularView.center = self.parentView.center
}
}
1]2
Try this code
self.circularView.center = CGPoint(x: self. parentView.bounds.midX, y: self. parentView.bounds.midY)
self.parentView.addSubview(self.circularView)
self.addSubview(parentView)
Try doing:
self.circularView.center = CGPointMake(CGRectGetMidX(self.parentView.bounds), CGRectGetMidY(self.parentView.bounds))
Why this should work? Try checking values of self.parentView.center for each cell, they might not be what you want them to be, because center property gives values with respect to parent view coordinate system.
Remove the following line from updateView()
self.circularView.center = self.parentView.center
Please add it to the following method:
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
e.g.
class ItemCollectionViewCell: UICollectionViewCell {
var parentView: UIView!
var circularView: UIView!
var itemImage: UIImageView!
var itemName: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
// self.updateView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.updateView()
}
func updateView(){
self.clipsToBounds = true
self.parentView = UIView(frame: CGRect(x: 0.0, y: 0.0, width:
self.frame.size.width, height: self.frame.size.height))
self.parentView.backgroundColor = UIColor.red
self.circularView = UIView(frame: CGRect(x: 0, y: 0, width:
self.parentView.frame.size.width / 4 , height:
self.parentView.frame.size.width / 4 ))
self.circularView.backgroundColor = UIColor.blue
self.addSubview(parentView)
self.parentView.addSubview(self.circularView)
}
override func layoutSubviews() {
super.layoutSubviews()
self.circularView.center = self.parentView.center
}
}

Error "EXC BAD ACCESS"with subclass in Swift

I made 3 files GameViewController, GameView, GameItemView but if GameItemView inherits GameView than
EXC BAD ACCESS error appeared
like below code.
class GameViewController: UIViewController {
var gameView: GameView!
override func viewDidLoad() {
super.viewDidLoad()
gameView = GameView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.view.addSubview(gameView)
gameView.gameViewController = self
}
//....
}
class GameView: UIView {
weak var gameViewController: GameViewController! //when GameViewController will appear, BAD ACCESS error appear and stop here
weak var gameItemView: GameItemView!
override init(frame: CGRect) {
super.init(frame: frame)
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
//....
}
class GameItemView: GameView {
override init(frame: CGRect) {
super.init(frame: frame)
//add some views
}
//...
}
I wrote some code of GameItemView on GameView before. But GameView's code became so long, so I moved a part of them to GameItemView. But then the error appeared. How can I solve it?
UPDATE:
I'll add the code where I got the error. I'm sorry I forgot to write it.
var gameGameViewController: GameViewController!
Why are you inheriting GamveViewItem from GameView? If you wanted to do so then why are coding like above which causes recursive calls to the init of GamveViewItem & GameView. Please either change the parent class of the GamveViewItem to UIView or some other or break the recursive pattern caused by the init.
GameView's init
override init(frame: CGRect) {
super.init(frame: frame)
// Here you're calling GameItemView's init, now go to GameItemView's init
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
GameItemView's init
override init(frame: CGRect) {
// You're calling GameView's init here and it goes back to
// there and then this keep on happening
super.init(frame: frame)
//add some views
}
try this:
class GameViewController: UIViewController {
var gameView: GameView!
override func viewDidLoad() {
super.viewDidLoad()
gameView = GameView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.view.addSubview(gameView)
gameView.gameViewController = self
}
//....
}
class GameView: UIView {
var gameViewController = GameViewController()
var gameItemView = GameItemView()
override init(frame: CGRect) {
super.init(frame:frame)
gameItemView = GameItemView.init(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 568))
self.addSubview(gameItemView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class GameItemView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
//add some views
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

IBDesignable inside UITableViewCell not rendered properly

I have a grid of custom "text below image" UIButtons inside a static UITableViewCell.
To make 8 UIButtons form 4x2 grid, I put them into 2 horizontal UIStackViews and wrapped them with a vertical UIStackView.
You can see details in the screenshots below.
It runs perfect on simulator and real devices, but not rendered properly in Storyboard. I'd like to know if these are something missing in my code or some settings I should check/uncheck in Storyboard.
Runtime behavior(works well)
In Storyboard(chaos)
Outline
Custom Button:
import UIKit
#IBDesignable class YPTextBelowImageButton: UIButton {
#IBInspectable var heightRatio: CGFloat = 0.8 {
didSet {
self.setNeedsDisplay()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = frame
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
return CGRect(x: 0, y: 0, width: contentRect.size.width, height: contentRect.size.height * heightRatio)
}
override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
return CGRect(x: 0, y: contentRect.size.height * heightRatio, width: contentRect.size.width, height: contentRect.size.height * (1 - heightRatio))
}
}
Preview:
func prepareForInterfaceBuilder not working
override func prepareForInterfaceBuilder() {
self.imageView?.contentMode = .scaleAspectFit
self.titleLabel?.textAlignment = .center
self.setNeedsDisplay()
self.setNeedsLayout()
}

Crashed when accessing property defined in BFPaperButton subclass

I am working on creating a customized button in Swift.
When I subclassed UIButton class, it works fine.
But it crashed when I replace super class with BFPaperButton (https://github.com/bfeher/BFPaperButton)
I have fixed the init method name conversion error with:
#define initFlat initWithFlat
#define initFlatWithFrame initWithFlatWithFrame
#define initRaised initWithRaised
#define initRaisedWithFrame initWithRaisedWithFrame
Then I got EXC_BAD_ACCESS when accessing the new defined property:
(An UserCountButton Instance).countLabel.text = ...
This is my implementation:
import UIKit
class UserButton: BFPaperButton {
let footerLabel = UILabel()
override init() {
super.init(flatWithFrame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width / 3, height: 100))
addSubview(footerLabel)
layer.contentsScale = UIScreen.mainScreen().scale
footerLabel.frame = CGRect(x: 0, y: 60, width: bounds.width, height: 40)
footerLabel.textColor = UIColor.grayColor()
footerLabel.textAlignment = .Center
footerLabel.font = UIFont.systemFontOfSize(12)
}
override init(raisedWithFrame frame: CGRect) {
super.init(raisedWithFrame: frame)
}
override init(flat: ()) {
super.init(flat: ())
}
override init(flatWithFrame frame: CGRect) {
super.init(flatWithFrame: frame)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
class UserCountButton: UserButton {
let countLabel = UILabel()
override init() {
super.init()
addSubview(countLabel)
countLabel.frame = CGRect(x: 0, y: 0, width: bounds.width, height: 90)
countLabel.textColor = UIColor.darkGrayColor()
countLabel.textAlignment = .Center
countLabel.font = UIFont.systemFontOfSize(32)
}
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override init(frame: CGRect) {
super.init(frame: frame)
}
}
Is that a bug or some what? How can I fix it? (I'm using Xcode 6 Beta 5)
From what I can tell, the problem is that you are trying to change stuff on your countLabel, but you have defined it via let which makes it immutable. Try changing that to var, and then setting all of it's properties.
Also, it should be noted that I believe you need to do all the subview initialization BEFORE you call addSubview, for both your UserCountButton and your UserButton.

Resources