Setting UICollectionView frame at runtime - ios

I am trying to set the frame of my UICollectionView at runtime.
I tried using
mainCollectionView.frame = CGRect(x: 20, y: 20, width: self.view.frame.width-20, height: self.view.frame.width-20)
in my viewDidLoad but unfortunately it will always stay as in IB.
I am not yet using constraints.
Otherwise resizing my cells is working in cellForItem:
collectionCell.frame.size.width = self.view.frame.width/8 * 3

Try to set frame in viewDidLayoutSubviews

you are wrong write height because you are set width at height.
try this line without navigation bar:
mainCollectionView.frame = CGRect(x: 20, y: 20, width: UIScreen.mainScreen().bounds.size.width - (20 * 2), height: UIScreen.mainScreen().bounds.size.height - (20 * 2))

Run the following in one of the LayoutSubviews overrides. This will tell collection view to update its frame.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
mainCollectionView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
mainCollectionView.collectionViewLayout.invalidateLayout()
}

Related

Wrong position UIScrollView content with statusbar

I'm trying to position UIScrollView at the top of screen to display a popup like Facebook Messenger
The Subview of UIScrollview is under the StatusBar.
How to position it correctly?
Issue:
If I place UIScrollview under the StatusBar, it works
let StatusbarHeight = UIApplication.shared.statusBarFrame.height
super.init(frame: CGRect(x: 0, y: 0, width: Util.getScreenSize().width, height: StatusbarHeight + 50))
self.contentSize = CGSize(width: self.frame.width, height: self.frame.height * 2)
let sub = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height))
self.addSubview(sub)
I expect that the subview is at the top of UIScrollView
Like this.
You might want to try this on the UIScrollView()
self.contentInsetAdjustmentBehaviour = .never

UITableView header align with cell bounds

I am generating a custom header view for my UITableView which has two horizontal lines up & down and a UILabel in between.
let lineWidth = tableView.bounds.width //This is not correct, will never align with UITableViewCell
let offset = (tableView.bounds.width - lineWidth)/2 //This will always yield 0, but my question is to compute line width that aligns with UITableViewCell as shown in the image attached to this question.
let topLine = UIView(frame: CGRect(x: offset, y: 0, width: lineWidth, height: 1))
topLine.backgroundColor = UIColor.white
let bottomLine = UIView(frame: CGRect(x: offset, y: 49.0, width: lineWidth, height: 1))
bottomLine.backgroundColor = UIColor.white
let label = UILabel(frame: CGRect(x: 0, y: 1.0, width: tableView.bounds.width, height: 48.0))
label.textColor = UIColor.white
let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.width, height: 50))
headerView.addSubview(topLine)
headerView.addSubview(label)
headerView.addSubview(bottomLine)
Problem: I need the top & bottom lines to align with UITableViewCell bounds in the section as shown in the picture below. What I get with the code above is horizontal lines that cover the entire width of UITableView. How do I achieve it?
EDIT: Some answers here describe an arbitrary offset value, but the heart of the problem is how to compute offset that aligns with UITableViewCell bounds in the section? In other words, I need exact width of UITableViewCell's that go into the section.
Your Offset will be practically zero as you are subtracting the same things
let lineWidth = tableView.bounds.width
let offset = (tableView.bounds.width - lineWidth)/2
let topLine = UIView(frame: CGRect(x: offset, y: 0, width: lineWidth, height: 1)) // this line gonna give offset as zero and width of full tableview width
Change this to the below code and try
let lineWidth = tableView.bounds.width - 20
let topLine = UIView(frame: CGRect(x: 10, y: 0, width: lineWidth, height: 1))
It seems the issue with the position of your top & bottom lines. As per the calculation of offset it always set to 0 for top & bottom lines. So it would be better to remove that offset calculation and you can add some desired static value as a x for CGRect of top & bottom lines.
As far as we are going to move the position of x for the top & bottom line don't forget to remove the added value for x position from the width of the top & bottom lines.
let yourLine = UIView(frame: CGRect(x: some_value, y: 0, width: Int(lineWidth - (some_value * 2)), height: 1))
The best practice is you can use some variables to achieve this.

Reduce height of a UIView from the top

I am simply trying to set frame of a UIView, but when you try to reduce the height of view, it will be reduced from the bottom of the view, not the top. How can I change hight of view from the top of it not bottom ?
customView = CGRect(x: 0, y:0 , width: self.view.frame.width , height: self.view.frame.height - reduceHeightSize)
You can update frame.origin.y as much as the height.
if reduceHeightSize is positive;
customView = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y + reduceHeightSize , width: self.view.frame.width , height: self.view.frame.height - reduceHeightSize)
if you store it negative reduceHeightSize;
customView = CGRect(x: self.view.frame.origin.x, y: self.view.frame.origin.y - reduceHeightSize , width: self.view.frame.width , height: self.view.frame.height + reduceHeightSize)
It would be better to just keep amount of the size not the direction.
You need to do like...
customView = CGRect(x: 0, y:reduceHeightSize , width: self.view.frame.width , height: self.view.frame.height - reduceHeightSize)
customView = CGRect(x: 0, y:0 , width: self.view.frame.width , height: self.view.frame.height - reduceHeightSize)
The problem of your code is that you change Height in CGRect. and you want to change top position of view so you need to change position of also y of your view so finally your code will be
customView = CGRect(x: 0, y: reduceHeightSize , width: self.view.frame.width , height: self.view.frame.height - reduceHeightSize)
If I understand your question correctly, that's probably because your view is not constrained/anchored at the bottom and thus defaulting to reduce on the top. Try adding a bottom constraint.
I just figured it out what I need:
customView.frame = CGRect(x: 0, y: self.view.frame.origin.y - reduceHeightSize , width: self.view.frame.width , height: self.view.frame.height + reduceHeightSize)

How can I set a variable header of a TableView (not of a section) programmatically?

How can I set a variable header of a TableView (not of a section) programmatically, without having to worry about the placement?
let headerView = UILabel()
headerView.text = x
headerView.textColor = UIColor.blueColor()
headerView.frame = CGRect(x: 0, y: 0, width: headerView.frame.width, height: 44)
tableView.tableHeaderView = headerView
I got this code, but I don't think I can place the header exactly like it is a 'real' header. Anybody knows how to do this?
As Dmitriy said, this is a normal way to do it:
tableView.tableHeaderView = headerView
Position is however defined by the frame you set in it, so if position is what you want different, you have to play with this line of your code:
headerView.frame = CGRect(x: 0, y: 0, width: headerView.frame.width, height: 44)
E.g., if you want the label to be centered, you can for example do it this way:
headerView.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 44)
headerView.textAlignment = .centered
This would span the label across the width of the tableView and the text alignment would place it to center. Of course, for this to work, the tableView frame has to be already calculated at this point (so maybe you would had to put the line with frame calculation in the layoutSubviews method).
I think this tableView.tableHeaderView = headerView - it's normal way to make header in UITableView.

Why doesn't view change when I change bounds?

If I change a UIView's bounds from...
v2.bounds = CGRect(0, 0, 70, 70)
to...
v2.bounds = CGRect(-2000, 0, 70, 70)
... nothing happens - the dimensions stay the same upon rendering. Why is this?
To help understand what bounds does, run this sample code in a view controller's viewDidLoad method:
let newView = UIView(frame: CGRect(x: 50, y: 100, width: 30, height: 30))
newView.backgroundColor = UIColor.blue
let secondView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
secondView.backgroundColor = UIColor.red
newView.addSubview(secondView)
view.addSubview(newView)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
newView.bounds = CGRect(x: 10, y: 0, width: 30, height: 30)
}
Here we're moving the bounds to the right by 10 points, so you'll see the "second view" (which is red) move to the left by 10 points.
Changing the origin of the bounds changes the coordinate system of the view, which affects the location of all of it's subviews. It doesn't affect its origin with respect to its super view, however. For that, you should change the origin of the frame.
Bounds only takes into account width and height, you are only changing the origin in your example, only changing x to be precise. To accomplish this use frame property:
v2.frame = CGRect(-2000, 0, 70, 70)

Resources