Center collection view cells in 1 column via custom UICollectionViewFlowLayout - ios

I have a screen with UICollectionView. This is layout of my screen in portrait:
| cell1 |
| cell2 |
| cell3 |
| cell4 |
| cell5 |
Now when I rotate device to landscape here is how it looks.
| cell1 cell2 |
| cell3 cell4 |
| cell5 |
The problem is that I need cells to stay in 1 column and have specific width and this is something I cannot achieve.
The collection view is using IGListKit for layout and self-sizing cells like in IGListKit example project, due to this and specific project structure I have to use custom subclass of UICollectionViewFlowLayout for any custom layout as I cannot override delegates. As soon as I increase the width of cell they align properly in 1 column. However, it seems that because cell width takes such small amount of space it automatically makes 2 columns in collection view. How do I keep one column after rotation while still having desired cell width using custom UICollectionViewFlowLayout?

Related

How to calculate the height of cell with tagViews?

Now, I have one UITableviewCell like this:
|--------------------|
| TitleLabelxxxxxx |
| SubtitleLabelxxx |
| tagView(Labels ) |
|____________________|
Tagview : https://github.com/ElaWorkshop/TagListView
TitleLabel and subtitleLabel are not one line.
I receive data from the backend and set the data to tagViews, titleLabel and subtitleLabel.
I used a storyboard to make this TableviewCell.
I used autoLayout to preset the height of the Tagview.
The value of height is more than or Equal 34( one line height).
If the tagViews has one line label, the TableviewCell renders perfectly.
If the tagViews has several tags:
When the TableviewCell first shows, the TableviewCell does not render all tags which are rendered in the tagView.
When I scroll this tableView, all TableviewCell will render perfectly after they scroll into the screen.
I used the tableView.rowHeight = UITableView.automaticDimension to set the height of TableviewCell.
This way can't calculate the perfect height value when the cell first renders.
The answer:
https://github.com/ElaWorkshop/TagListView/issues/191
I used this way to fix the bug.

UICollectionView Left align cells with dynamic widths

So I have a collection view like shown below:
----------- ----------------
| some text | | Some more text |
----------- ----------------
----------------------- -----------------------
| Some really Long text | | Some longer text here |
----------------------- -----------------------
And I would like it to be:
----------- ----------------
| some text | | Some more text |
----------- ----------------
----------------------- -----------------------
| Some really Long text | | Some longer text here |
----------------------- -----------------------
I was able to get my cells to dynamically adjust their width to allow for a label to display its text, but I would like all of the cells to be left aligned with their section insets instead of being centered.
Edit:
I've tried a lot of things so far, but here is the last thing (doesn't actually work)
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
for attributes in attributesForElementsInRect! {
let refAttributes = attributes
refAttributes.frame.origin.x = self.sectionInset.left + 8
newAttributesForElementsInRect.append(refAttributes)
}
return newAttributesForElementsInRect
}
}
I'm not sure if it would be easier to set the widths of each cell in a section equal to each other instead, that would force all of the cells in the section to aligned with each other instead of centering inside of the section. I'm not sure how to approach this though - the sizeForItemAt seems like palace to start, but I don't want to override auto layout setting the widths dynamically for the labels.

Horizontally align UILabel and UIImageView together inside of a full width UIView

I have a UIView in my layout that is pinned to the sides of my VC. Inside of that I have an icon UIImageView and a UILabel that is next to that. I would like both of those to be center aligned inside of the UIView no matter how long the text inside of the label is. (Similar to how you would use text-align:center; in CSS to align both image and text center).
| UIView |
| |
| |
| |
| |image| |label| |
| |
| |
| |
| |
Sometimes the label might be long, but I still need them centered:
| UIView |
| |
| |
| |
| |img| |label is long| |
| |
| |
| |
| |
I know how to use Autolayout but this one has me stumped since I can't created a "holder" UIView and center that. I need some help figuring out the constrains to add in IB.
Ideas?
Building on #Mahmoud Adam's answer, we can do this entirely in the storyboard.
Horizontal and vertical align the UIView relative to its superview.
Add constraints to the UIImage and UILabel so that they are pinned to the edges of the UIView.
The UIView will grow as the UIImage and UILabel grow inside of it.
Create a new UIView inside main view and put the UUImageView and UILabel inside it, this view should have the following constraints
using interface builder
Horizontal align inside the main view
Vertical align inside the main view (same as imageView now)
using code in the view controller
width = image.width + label.width + horizontal space between imageView & label
height = Max (image.height, label.height)
This is very simple i guess...using storyboard....
If you not found solution yet...then check this image and follow...
Here...green color background is UIView in image
and i select update constraints for view from resolve autolayout views

statically change specific UITableView cell height without reloading

here's my issue:
I have a UITableView and in each cell I display some UILabels, like below:
----------------
| "A" |
----------------
| "B" |
----------------
| "C" |
----------------
Each cell is tap-able and when tap it pushes to another view to allow user to add some cell content. When user finish adding, the view pops back.
I want to see the UITable cell is statically updated with a new label that user added. For example, if user added some content to the first cell (previously with one label "a"), then after view pops back the cell should have two labels, which should look like:
----------------
| "A" |
| "New" |
----------------
| "B" |
----------------
| "C" |
----------------
I don't want to reload the entire table (which will drain data and lost previous cell position). Is there a way I can re-load this specific cell with new height/content? or statically adjust the cell-height?
Thank you
Yes you can reload particular cell in table view while relaoding the cell you can set cell height.
NSArray* rowsToReload = [NSArray arrayWithObjects:self.selectdIndexPath, nil];
[self.tableview reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationNone];

AutoLayout and UILabel resize animation not working properly on device rotation

i have a strange problem on a very simple task.
I needs a very small setup to reproduce the problem:
|--------------------------------------|
| Parent View |
| |
||------------------------------------||
|| UILabel ||
||------------------------------------||
| |
| |
||------------------------------------||
|| UIView ||
||------------------------------------||
| |
| |
|--------------------------------------|
In the example above we have a parent view with 2 subviews --> A UILabel and a simple UIView. Im using autolayout to apply the layout shown above:
Constraints for UILabel:
Leading Space to superview = 0
Trailing Space to superview = 0
Fixed Height constraint (e.g. 80pt)
Top Space constraint (e.g. 50pt)
The UIView subview has the same constraint types (the values for height and top space differs).
So what i expect with this setup, is that both subviews will adopt the full width of its parent as we defined that leading and trailing space should be zero. so if change the width of the parent view, the width of the subviews should change too, to stay aligned.
lets say the parent view has a dimension of 200x400 pt. when i build and run my example in portrait everything looks ok. when i rotate to landscape, everything still looks fine. the parent views width and even the subviews width got larger. but now when i rotate back to portrait the uilabels width immediately gets its target width without any animation:
|--------------------------------------|
| Parent View |
| |
| (immediately has target size) |
| |--------------| |
| | UILabel | |
| |--------------| |
| |
| (this subview is still |
| animating its width) |
| |------------------------------| |
|-->| UIView |<--|
| |------------------------------| |
| |
| |
|--------------------------------------|
the parent views width and the uiview subviews width are animated properly. its only the uilabel that has a strange behavior here and i cant find out what causes that issue.
My suggestions are:
If you've subclassed the parent view use the - (void)layoutSubviews:
- (void)layoutSubviews {
label.frame = CGRectMake(leftInset, labelY, parentView.frame.size.width - leftInset*2, labelHeight);
childView.frame = CGRectMake(leftInset, childViewY, parentView.frame.size.width - leftInset*2, childHeight);
}
if you didn't subclassed the parent view you can use autoresizingMask:
label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
childView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
The problem is not that the UILabel is not animating its resize but that the text does not animate. If you were to give the label a different background color, you would find that it does indeed animate, and it is just the text which jumps to position.
One way to fix this would be to change the width of the label with no animation and move it ober by X points, where X is half of the difference between the starting and ending width, and then just animate its position.
The only problem with this method for your code is that I do not believe you will be able to do it with auto layout.
As I remember, for constraints you should provide some more specs, but for such easy UI elements I would suggest using UIViewAutoresizing masks. They are much simpler and have shorter definitions. In your case just use UIViewAutoresizingFlexibleWidth.
Its better to set autolayout in story board. Please ensure that you are all the sub views is selected in your view controller when you are setting constraints. For that you should do the following:
Click on the view of your main view controller
Press Ctrl+A
Click Resolve Auto-layout Issues
Select Add missing constraints in Your View Controller
Then constraint will be set to all the subviews and will work perfectly during rotations.

Resources