Collection View cell height reverting back to default size - swift

I have 3 different collectionViewCells all which should be different sizes, I've set them all to have a custom size but the cell size reverts back to the default size set by the collectionView during runtime. I've tried this within my cellForIndexPath
cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, 200)

collectionView(_:cellForItemAtIndexPath:) is a member of UICollectionViewDataSource which means it deals with data population of the cell, not visual presentation. The Apple documentation on this method states: "You do not need to set the location of the cell inside the collection view’s bounds. The collection view sets the location of each cell automatically using the layout attributes provided by its layout object." Most likely you're setting the frame and the layout object is overriding that value.
What you're looking for is UICollectionViewDelegateFlowLayouts collectionView(_:layout:sizeForItemAtIndexPath:) method. Here you can specify the frame size of individual cells. If you want to get really crazy, you can even write your own layout.

Related

Large text not displaying as multiple lines for UILabel in a custom tableview cell

Setting up the UILabel on the attributes inspector as follow expands the cell and display the large text as multiple lines correctly for a Subtitle tableview cell:
Lines = 0
Line Break = Word wrap
But this doesn't work in a custom tableview cell for some reasons. In the custom cell, I added new labels and setup the attributes the same way but the cell doesn't expand.
It could be a matter of constraint.
Check to see if there are any conflicting constraints or fixed settings.
In order for elements of a cell to be set flexibly, the height of the cell must be set to the automatic value.
When I set it up like this, I was able to get the results I wanted.

Override tableView.separatorStyle for a single cell or section

I'm trying to set the tableView.separatorStyle to UITableViewCellSeparatorStyleNone for a single section (or row, I suppose), but allow it to be set to the default for every other section.
As an example (of the unintended behavior):
While the rows at the bottom (and top) of the image should display the default gray line surrounding each section, for this particular section, even though I have set the backgroundColor of the cell to [UIColor clearColor], I would also like to remove the separator from this particular section.
There don't seem to be any delegate/datasource methods that allow overriding this on a per-section basis. The documentation for the separatorStyle property mentions:
UITableView uses this property to set the separator style on the cell returned from the delegate in tableView:cellForRowAtIndexPath:.
So it sounds like it's applied after I've built my cell, and the setter is only at the UITableView level, it is not visible at the ..Cell level.
the separatorStyle property can't be used for a specific cell. It will be used for all the cells. If you want to add separators just for some cells, add a UIView inside the cell's vie that will act as a separator and set the separatorStyle to UITableViewCellSeparatorStyleNone.
In cellForRow.. you can check the cell that will be provided to the table view and decide if the separator should be visible or not.
Just set a custom separator inset of 1000 for cells that you don't want to have separators.

UITableViewCell content moving around

I have an iPhone app in which I'm using a UITableView to format a set of text responses, one per row. I've set up the cell in the storyboard to have a label inside it, and set up a constraint saying that the label should be 10 points from the edge of the cell. I then set up a custom subclass of UITableViewCell, set the cell in the storyboard to be of that class, and connected the outlet.
However, when I load the table, I see the text in the cell moving slightly to the right under some circumstances: when I select the cell, or when I load additional cells into the table. In fact, in the latter case, sometimes everything gets shifted to the right, even cells which were already there!
What the heck is going on here? The only changes I'm making in tableView:cellForRowAtIndexPath: are to the text in the label, and I'm always setting it. And I've unset "Indent While Editing" on the cell in the storyboard.
Answering some of the questions: I'm setting the view up using the storyboard. Xcode isn't reporting any ambiguity with the constraints. Also, here are the screenshots, before and after:
My guess is that the constraints for the label are ambiguous. Ambiguity can make UI components jump around for inexplicable reasons. You probably need to set more constraints for the label to define its position on both axes.
Or, maybe all you need to do is set the label to the "size that fits content" (intrinsic content size) under the Editor menu in IB.
Did you add a new label to the UITableViewCell, or are you working with the textLabel that already exists in it? If you added a new one, consider removing it and using the cell's existing textLabel property instead. If that's not an option for some reason, double-check that the label you've added is in the contentView of the cell, and that all the constraints are relative to the parent view, not to the cell itself.
Also, for debugging, you could set the cell's contentView background color to red (cell.contentView.backgroundColor = [UIColor redColor];) - this might give you a better sense of what's moving, the label or the whole view.
This is just a guess without seeing your code. I had a similar problem once, when the app reused an existing cell, the dimensions of the label were not correct. So, I had to remove the old label in my cellForRowAtIndexPath method, before adding a new label. Here's how I removed the old one:
UIView *oldLabel = [cell viewWithTag:3];
if (oldLabel != nil)
{
[oldLabel removeFromSuperview];
}
Then I added a new label like this:
[cell.contentView addSubview:newLabelOrWhatever];
It might be worth checking to see that your string content doesn't have a space prefixed on it. Also, you could verify the actual position of the label by setting the background color.
I had a similar issue when the label would move when the cell was selected. It was a custom cell that I was loading from a custom Nib.
In the Nib I had not set the backgroundView of the UITableViewCell (superclass) to any view. Once I set it (I set it to the ContentView) the issue stopped.
My auto-layout constrains seems fine and had no issues, so I'm assuming it was the above that fixed it.
If you have a custom subclass of UITableViewCell, try implementing layoutSubviews. Let me try from the top of my head:
static CGFloat const kLeftMargin = 10.0f;
- (void) layoutSubviews
{
[super layoutSubviews];
/* Prepare for processing */
CGSize cellSize = self.bounds.size;
/* Change the textLabel frame */
{
/* Compute the new label frame */
CGSize labelSize = self.textLabel.bounds.size;
CGFloat xCoor = kLeftMargin;
CGFloat yCoor = roundf((cellSize.height - labelSize.height) / 2.0f);
CGRect labelFrame = CGRectMake(xCoor, yCoor,
labelSize.width, labelSize.height);
/* Set the new label frame */
self.textLabel.frame = labelFrame;
}
}
Now, this isn't what is usually recommended (since a lot of people use Storyboards and NIBs), but from experience, if you want some correct layouting done, implement layoutSubviews.

Hide a UITableView by setting row height to 0?

I just inherited code which hides/shows rows a UITableView by using the delegate heightForRowAtIndexPath method and returning height 0 for "hidden rows".
The code works, but it has me concerned there might be fraught with unforeseen complications. Can someone either ease my concerns or give me good reasons why this could cause problems (I couldn't find any issues with initial testing).
The table is fairly small <10 rows total and would require custom row heights even without this hidden row solution.
I do the same thing in the code I just worked on. I am not happy with different behaviour for different table view settings.
The alternative in my case is more complex (a model that adapts to what is visible or not).
For now, I put a //HACK comment on it and document a few peculiarities.
This is what I have found (iOS 5.0 tested):
Set tableView.rowHeight = 1; Zero will give a cell with zero height (as returned by tableView:tableView heightForRowAtIndexPath:) some default height.
You must have a cell separator. If none is selected, then a default height is assigned to zero height rows. The height of 1 is included with the separator.
If your code works in a different way, it would be interesting to know how it is set up.
It would be cleaner to add and remove the rows between two beginUpdates and endUpdates calls, but I don't see why this 0-height method should not work.
If there are no UI-artifacts, that is (e.g. the Delete button showing up overflowing to the next cell).
I use this method of setting hidden cell heights to 0. It works well and also means I can animate the inclusion of new cells by expanding the cell height (such as adding a DatePicker Cell like the calendar app does).
A few things I have had to watch out for in iOS 7.1 are that very squashed text does still appear even when a cell height is = 0 so I've needed to remove cell text in that case. Also, I have change the size of the cell's separatorInset as that was appearing as well.

What state is preserved in the cell returned by UITableView:dequeueReusableCellWithIdentifier?

When using UITableView:dequeueReusableCellWithIdentifier, can I make any assumptions about the state of the cell that is returned? For instance, if my UITableView only displays UITableViewCells with a font size of 18, can I set the font size once on the initial alloc code and assume it will also be set to 18 when returned from dequeueReusableCellWithIdentifier? Is there any state I should never make assumptions about?
Yes there is, the contentView is never reset. Although all cells are automatically cleaned by the method:
- (void)prepareForReuse
when the cell is dequeued, the contentView is NOT cleaned.