Dynamic height of two UIView's in a ViewController - swift

I have the following ViewController, with 3 UIViews and content inside. The red lines are my constraints.
The black one has always a fixed height.
The red UIView has a CollectionView inside, which will grow, depending on it's items.
The green is a UITableView which should shrink, depending on the size of the red UICollectionView.
I tried to set the height constraint of the red (UICollectionView) to greater than or equal, and the green (UITableView) height to less than or equal, but Swift is telling me to set a x or height value.
What is the correct approach to get two dynamic Views inside my ViewController?

Create NSLayoutConstraint for CollectionView Height,Then set the height on cellForItemAt function
var collHeight:NSLayoutConstraint? //In class scope
Assign CollectionView height anchor to collHeight
collHeight = collectionView.heightAnchor.constraint(equalToConstant: 0)
collHeight!.isActive = true
Then set the height on cellForItemAt function
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
collHeight.constant = collectionView.contentSize.height
}
it will expand the size of collectionview height according to item count. Next set the tableview top anchor to collectionview bottom anchor

Related

Auto-Layout for CollectionViewCell: Trailing/Leading constraints change cell size

I just can´t get familar with auto layout in Xcode. When I set trailing and leading constrains for Header Stack View, Bottom Stack View or the image between them, then the size (height/width) of my cell changes. Why does it happen and how can I avoid it? I think something isn´t right with the kind I build layouts. I am very grateful for any help.
I set the cell size with this code:
extension MainVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = view.frame.size.height
let width = view.frame.size.width
return CGSize(width: width * 0.42, height: height * 0.3)
}
}
My cell layout:
This is how the app looks when I use constrains for the Bottom Stack View.
This is without constrains for the Bottom Stack View (correct cell size).
Cells can now self-size with auto layout and ignore what you return in collectionView(_:layout:sizeForItemAt:). If you want to use collectionView(_:layout:sizeForItemAt:), change Estimate size to None in the storyboard.
https://stackoverflow.com/a/58369142/14351818

Corner Radius for UIImageView not working for UICollectionViewCell with dynamic size

I have cell which consist of a UIImageView which has a height of 70% of the cell size and the rest of the 30% is used up by the label.
The cell's have a dynamic size which is calculated according to the device width.
I have made sure the cells are are square and the UIImageView contained within the cell's also has 1:1 ratio for their height and width
I am setting the corner radius of the UIImage in the cellForItem delegate method of the Collection View
cell.userImage.layer.cornerRadius = cell.userImage.bounds.width / 2
cell.userImage.clipsToBounds = true
So can anyone point me in the right direction as why this is happening ?
When should I set the corner radius of the Image in the cell lifecycle ?
This doesn't happen if I give the image view static size, but I want the size to be dynamic according to the screen size
try cell.userImage.layer.maskToBounds = true
Better to wrap imageView inside a UIView . Then set UIView propertiesbound.size.width/2
You are taking the width of "bounds". Try taking the width/height of cell.userImage.
cell.userImage.layer.cornerRadius = cell.userImage.bounds.width / 2
Also, is the ratio of the image 1:1?
hey use this delegate UICollectionViewDelegateFlowLayout to set the size for each item in cell. something like below
...
collectionView.delegate = self
...
// then make your view controller confirm to the UICollectionViewDelegateFlowLayout
// then overide this method like below
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
CGSize(width: MyLayoutConstants.collectionViewItemWidth,
height: collectionView.frame.height)
}
this is just an example from my case. the main idea is that use the delagate above.

UICollectionView Cell with a thick border

I am attempting to create a round collection view cell.
In the cell I have a red UIView that is 0 from top, leading, trailing, and bottom. Inside of that cell I have another view which is white and it is 4 from the top, leading, trailing, and bottom. Within that view is a UILabel and a UIImageView.
The goal would be to have 2 cells per column and it is has a red ring around a white circle and text and an image.
To create the round UIViews I have an extension for UIView like this
extension UIView {
func createRoundView() {
layer.cornerRadius = frame.size.width/2
clipsToBounds = true
}
}
Inside of my cellForItemAt I say
cell.whiteBackgroundView.createRoundView()
cell.colorStatusView.createRoundView()
The goal is on the left, but what is happening is on the right.
Here is my Storyboard
The constraints are all blue, nothing red.
And to get the 2 cell per column I use this delegate method
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding: CGFloat = 25
let collectionCellSize = collectionView.frame.size.width - padding
return CGSize(width: collectionCellSize/2, height: collectionCellSize/2)
}
Any idea what I might be doing wrong?
In the end it doesn't matter if I have a view within a view. I change the ring or border color based on other data....so I just need to be able to easily change that border color.
This code is not enough, to tell what's going on there... try to set all
backgroundColors to .clear
then set those properties to your view
customView.layer.cornerRadius = half of your width
customView.layer.borderWidth = 5
customView.layer.borderColor = UIColor.red.cgColor
Using #blinkmeoff answer I figured it out mostly (although follow up question to come)
Inside the cell class I added the following
self.backgroundViewContainer.layoutIfNeeded()
self.backgroundViewContainer.layer.cornerRadius = min(backgroundViewContainer.frame.size.width, backgroundViewContainer.frame.size.height)/2
self.backgroundViewContainer.clipsToBounds = true
I kept getting weird shapes by just doing the /2 so I added the min(ba...
and that got me perfect circles

How to make a 2 row multicolumn UICollectionView that scrolls horizontally

I want to make a UICollectionView that looks like this:
[ - - - - - 0 - - - - - ] -> Scrolls Horizontally
[1][2][3][4][5][6][7][8] -> Scrolls Horizontally
How is it done?
I'd prefer not to place UICollectionView in a UITableViewCell as well.
Make your subclass inherit the CollectionViewFlowLayoutDelegate protocol
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
let size = CGSize(width: defaultWidth, height: collectionView.height / 2)
//The important thing here is the height of your item is half the height of collectionView and then your flowlayout will start to put them on top of eachother.
// Also make sure that height accounts for section and content insets
return size
}
Then just make sure in viewDidLoad() you set the scrolling properties of collectionView to only horizontal scrolling.

UITableView: automatically set height for the row and fix it with max height constant

I need automatically set the height for the row. I use
theTable.estimatedRowHeight = 60
theTable.rowHeight = UITableViewAutomaticDimension
but the height is not fixed. I need fixed height something like MAX 60 height, by default height is 40. With estimatedRowHeight the height is not fixed and when the string is long the cell takes all screen. How to fix it?
You will need to put all the content of table view cell in a single view (lets call it MainView) and set MainView top, leading and trailing edge constrains to container view. Also set a height constraint less than or equal to 60 with required priority. After that put your label in MainView set top, leading and trailing constrains to MainView and a bottom space to MainView constraint with high priority. Also on your label set number of lines to 0 and preferred width to explicit. This way if label content height is less than 60, MainView will shrink and that will still match height constraint of less than or equal to 60. Otherwise if content height is greater then 60 the bottom space to MainView constraint will break without causing problems since its priority is less then MainView height constraint.
Finally override tableview delegate methods as follow
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 40
}