UICollectionView loaded from Storyboard is NOT resizing correctly - ios

I'm using a UICollectionView created with storyboard, I have applied constraints { .left = 0 .top = 0 .bottom = 0 .right = 0 } to it and expecting it can layout by viewcontroller.view's width and height.
But in viewDidLoad I found that it's width and height equal to the default value specified in the size inspector panel instead of the real screen size.
Now, I need to layout collection view cell by the real size. In sizeForItemAtIndexPath if I return the screen size, it will throw a warning
the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.
Is there any way to get the correct size of it? Or what is the right way to layout it? Thanks!

You are trying to set the height if an individual cell to be bigger than the height of the collection view itself.
The error message is pretty straightforward.
Can you provide some context as to why you need a cell to cover the whole screen?

Related

UITableViewCell contentView inset on iPhone X

Any UITableViewCell created on iPhone X has a 44 points inset for content view. This means width of contentView of UITableViewCell is by default 44pts less than the cell width. I do not need to have this behavior. How do I get contentView width same as cell width (or like it is there on other iPhone models)?
Update: I solved the problem by setting tableView.insetsContentViewsToSafeArea = NO. Now working on same issue for other elements such as UINavigationBar items. Unable to find an equivalent was for UIBarButtonItem for navigation bar. Any insight is appreciated.
Maybe you could use additionalSafeAreaInsets on your view controller, it's there to reduce the actual usable space but with negative Insets it should do the opposite.
https://developer.apple.com/documentation/uikit/uiviewcontroller/2902284-additionalsafeareainsets
In your table view set insetsContentViewsToSafeArea to false.
tableview.insetsContentViewsToSafeArea = false

if content size > actual height then fixed height and if content size < actual height then dynamic of tableview swift 3?

In storyBoard i have given top, bottom, leading and trailing constraints to tableview in a view.
i have given tableview height as contentSize.height. As per tableview height, no of cells that can visible in tableview 3 or 4 or etc(depending upon content size it may vary). But the problem is table view height is increasing as per content size.
if no of cells are more, then it should compare actual height of the table view with content size and if contentSize is lesser than tableview Actual height then only it should change the height of tableview.
if tableViewActualHeight > contentSize {
// then only change tableview height
tableViewActualHeight = contentSize
}
How can we get & where to place that code?
OK here is an idea for that
First get height of tableview by yourTableView.frame.size.height.
Now calculate height of your tableView cells.
Lets assume the cases.
Assuming cell is of height 50 and tableview if height 200
First case
If you have 2 cell, then total cell height is 100. Now check if 100<200
bottomConstraint of tableView will be 200 - 100, that is 100.So here tableView height becomes 100
Second Case
If you have 5 cells ,then total cell height is 250 .Now check if 250<200
bottomConstraint will be ZERO
Please let me know if its helps you or having trouble to understand
You need to set one more constraint to your tableview - Fixed height.
Now take(or connect) outlet of that constraint and then set constant of that outlet as per your condition. If your content size is greater then your tableview do nothing else set your height constraint's constant as content size like,
heightConstraint.constant = 20 // Your contentsize instead of 20
You need to do that after your tableview successfully reload, other wise it will not give correct content size.
If your cell or row's height is fixed then you can count content height your self. You can multiply row height with number of row (array count)!

Dynamic UILabel size for view before uitableview

I am having abit of trouble here trying to make this post description label to grow and shrink based on content size on IOS9. I have a view (I will refer it topView) that I am using as a header for the tableview (So when I scroll up the header disappears). Inside the topView, there are a bunch of stack views. I wish to grow and shrink the post description label in height based on content size. I do know how to do it in simple case where everything is inside the prototype cell (i.e. set estimated row height and set uitableviewautomaticDimensions, set sizetoFit on label and change number of lines to 0). However, this is a different case because the post description label is not really inside the cell, it is in its view before the table view cells.
Note that all items in the view has static height except the postdescription label. Post description label is inside a stack view that is pinned only left and right (So that top and bottom would grow?). Also, the main stack view that contains all elements is pinned towards the four sides with the topview that contains the main stack view also pinned towards the four sides. With this setup, I would expect the topview to grow and shrink based on the content size. However, I do not see that in the output. I dont know if it is the stackview that is holding the label refusing to grow or the top view refusing to grow to allow more space for the stackview for the label. Thanks
UPDATE
Thanks Riadluke, I tried doing something as suggested which is resizing the headerview after calculating the required height. I have placed the following code in viewDidLayoutSubview and it works with an issue
postDescriptionLbl.sizeToFit()
let headerView = commentTableView.tableHeaderView!
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
let height = TopStackView.frame.size.height + ImageStackView.frame.size.height + postDescriptionLbl.frame.size.height + SpacerStackView.frame.size.height + BottomStackView.frame.size.height
headerView.frame.size.height = height
commentTableView.tableHeaderView = headerView
The issue I now have with this method is that when the view controller appears, I can physically see the postDescription label height grow from the default height in storyboard to the required height. For example, when the VC first appears, I see a line of label with some string being cut off, however after 0.5 second, the headerview and the label grow to the size that I wanted. I know this would be expected because I was calling the manipulation after the viewDidLayout Subview. I was wondering if there is a better way such that I dont see that transition and the view appears to be the right height straight away. Ie. let the view know exactly how high the label is to determine how high the headerview needs to be before appearing on screen?
I'm afraid the view set as tableHeaderView of a UITableView does not get resized automatically. Its height will be fixed to the height it had in IB.
What you have to do is set its size manually and then reassign it as the tableHeaderView so it is displayed in the height you want.
It could take only few lines since you're using autolayout.
You can try this code right after you've set the header view's contents:
//for the target size you have set the width as your tableView's width when it is already displayed on screen.
//note that when it is accesed inside viewDidLoad the tableView's bounds
//may be different to the actual bounds it will be displayed with,
//here I am just using the screen bounds
let targetSize = CGSize(width: UIScreen.mainScreen().bounds.width, height: 10000)
//set the tableHeader's size to its size after its layout constraints are resolved
tableHeader.bounds.size = tableHeader.systemLayoutSizeFittingSize(targetSize)
//reassign it as the tableHeaderView to update the height it will be displayed in
tableView.tableHeaderView = tableHeader
After many many attempts, I could not get anything to work with the original setup. The best I achieved was to resize it after view did appear which is not idea as you see the previous layout.
It is now working with a complete different approach. I have created two prototype cell and have one as "HeaderViewCell" and implemented the following functions
commentTableView.estimatedSectionHeaderHeight = 400
commentTableView.sectionHeaderHeight = UITableViewAutomaticDimension
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
Everything works like a charm after that.

How to manually change UICollectionView height in Swift

I'm hiding rows that are completed in a collectionView.
I call cell.hidden = isCellHidden in cellForItemAtIndexPath when needed.
After I hide 10 rows there is plenty of empty space left and I'd like to trim down the size of the collectionView to only fit the rows that are not hidden.
The collectionView's design is kind of like a tableView.
I know with the tableView all I had to do to achieve this is set:
func section1VisibilityButton(sender: UIButton){
isCellHidden = !isCellHidden
self.tableView.reloadData()
self.tableView.contentSize.height = CGFloat(500)
}
with a collectionView when I try this it will resize it correctly but as soon as I try to scroll down it resizes itself back to the original height including the cells hidden (the cells layer is still hidden but there's tons of empty space bellow the last visible row as if they were visible)
For your issue, there are two options to change the frame of your collectionView/tableView.
If you are using autolayout, you need to create IBOutlet of bottom constraint or IBOutlet of constant height constraint of your tableView (anyone of these constraints, which you are using).
After reload tableView data you need to update constraint by calculating its height.
Suppose you are using constant height constraint and your calculated height is 150(e.g. 3 rows and 50 height of each row).
constraintTableViewHeight.constant = 150;//this will change height
self.view.layoutIfneed(); // this will apply updated constraints to whole view
If you are not using autolayout, you can manually change the height by changing tableView.frame property.

runtime expansion of uitableview footerview using autolayout

I have a UIView that is a footerview of a uitableview. At run time, the user enters text into a uitextview within the footerview that should adjust to the size of the text content with a height constraint in autolayout.
All other objects in the view (labels, imageviews) have appropriate constraints to accommodate the expansion of the textview.
HOWEVER the height of the overall footerview will not change size, and it is impossible to use autolayout on the tableview footerview height.
Does anyone have a solution? Thanks
Haven't found an actual, elegant, solution yet, but I've postponed fixing this by using a workaround:
Setting the frame of the view used as a footer to be as large as you might possible need. In my case this meant giving it about 60px of spare vertical room. Since it's the footer and there's nothing below it to reposition the user won't be affected by the workaround.
The contents of the footer view are pinned to the top and have enough space to expand when needed.
For the record: my view is loaded from a nib file.
Although in theory the size one gives to the top level view in interface builder is just for design-time and the runtime size should be calculated based on constraints and the resulting intrinsic size, for this specific case I found the height stays the same as it was in IB.
We can change the height of the footer view run time by the following code:
func methodToChangeTableViewFooterHeight()
{
var footerView:UIView = self._tableView.tableFooterView! as UIView
var frame:CGRect = footerView.frame
frame.size.height = self.heightCollectionCS.constant + 10
footerView.frame = frame
self._tableView.tableFooterView! = footerView
}
Here , self.heightCollectionCS.constant is the height constraint for our Collection View.
We can use text content height on that place.
You may try to set again the footer view each time you footer height changes, to inform the table it should change the footer height. Or use inset. From within the footer view:
SetNeedsLayout()
LayoutIfNeeded()
ownertable.TableFooterView = this
Sorry about that, misread that question long ago. You can access the footer directly through the tableview's property tableFooterView.
What you could do is create your default footer in a xib or in your viewDidLoad:. Once you need to increase the size of the footer, you can pull out the UIView from that property and edit its frame if necessary to make it larger.
So make sure the tableFooterView gets assigned a UIView because it is nil by default. To just make the height taller, you can use self.tableView.tableFooterView.frame = CGRectMake(whatever rect you need);

Resources