Dynamically resizes an optional UICollectionView (containing a multi-line UILabel)

In the optional UICollectionView (header), I have a multi-line label that I want to trim to 3 lines.

enter image description here

When the user backs down anywhere above the header (optional) view, I want to switch the UILabel to 0 lines so that all the text is displayed, and accordingly increase the size of the additional collectionView (preferably animated). Here's what happens after clicking on the title:

enter image description here

Here is my code:

// MyHeaderReusableView.m // my gesture recognizer action - (IBAction)onHeaderTap:(UITapGestureRecognizer *)sender { self.listIntro.numberOfLines = 0; // force -layoutSubviews to run again [self setNeedsLayout]; [self layoutIfNeeded]; } - (void)layoutSubviews { [super layoutSubviews]; self.listTitle.preferredMaxLayoutWidth = self.listTitle.frame.size.width; self.listIntro.preferredMaxLayoutWidth = self.listIntro.frame.size.width; [self layoutIfNeeded]; CGFloat height = [self systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; self.frame = ({ CGRect headerFrame = self.frame; headerFrame.size.height = height; headerFrame; }); NSLog(@"height: %@", @(height)); } 

When I register height at the end of layoutSubviews , its value is 149, while the label is truncated and numberOfLines is 3. After clicking headerView, setting numberOfLines to 0 and forcing the layout, the height is then written as 163.5. Fine!

The only problem is that the whole header file does not grow and the cells are not dumped.

How can I dynamically change the height of my additional collectionView (preferably animated)?

I know UICollectionViewFlowLayout headerReferenceSize and collectionView:layout:referenceSizeForHeaderInSection: but I'm not quite sure how I will use them in this situation.

+7
ios objective-c autolayout uicollectionview
source share
2 answers

I have something working, but I admit that he feels stupid. I feel this can be achieved using the standard CollectionView API (and related elements) API +, connecting to the standard layout / display invalidation, but I just couldn't get it to work.

The only thing that would change the size of my header is setting up my presentation view stream of the collection headerReferenceSize collection. Unfortunately, I cannot access the collection view or its layout from my UICollectionReusableView instance, so I had to create a delegate method to pass the correct height back.

Here is what I have now:

 // in MyHeaderReusableView.m // // my UITapGestureRecognizer action - (IBAction)onHeaderTap:(UITapGestureRecognizer *)sender { self.listIntro.numberOfLines = 0; } - (void)layoutSubviews { [super layoutSubviews]; self.listTitle.preferredMaxLayoutWidth = self.listTitle.frame.size.width; self.listIntro.preferredMaxLayoutWidth = self.listIntro.frame.size.width; CGFloat height = [self systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; self.frame = ({ CGRect headerFrame = self.frame; headerFrame.size.height = height; headerFrame; }); if (self.resizeDelegate) { [self.resizeDelegate wanderlistDetailHeaderDidResize:self.frame.size]; } } // in my viewController subclass which owns the UICollectionView: - (void)wanderlistDetailHeaderDidResize:(CGSize)newSize { UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout; // this is the key line flowLayout.headerReferenceSize = newSize; // this doesn't look beautiful but it the best i can do for now. I would love for just the bottom of the frame to animate down, but instead, all the contents in the header (the top labels) have a crossfade effect applied. [UIView animateWithDuration:0.3 animations:^{ [self.collectionView layoutIfNeeded]; }]; } 

As I said, not the solution I was looking for, but nonetheless a working solution.

+4
source share

I came across the same question as you, so I'm just wondering: did you ever get the solution without the crossfade effect that you mentioned in the sample code ?. My approach was almost the same, so I have the same problem. One more comment: I managed to implement the solution without the need for delegation: what I did was from "MyHeaderReusableView.m". You can reference the UICollectionView (and therefore the UICollectionViewLayout):

 //from MyHeaderReusableView.m if ([self.superview isKindOfClass:UICollectionView.class]) { //get collectionView reference UICollectionView * collectionView = (UICollectionView*)self.superview; //layout UICollectionViewFlowLayout * layout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout; //... perform the header size change } 
0
source share

All Articles