I'm using a UICollectionViewCompositionalLayout to create a grid. Each cell contains a multi-line label. My goal is that, when 1 item in a group/row grows, all others in that group/row grow to the same height e.g. in the attached pic, I would like the cells in column 2 and 3, row 2, to match the height of the first cell that contains ("1000\ndetail").
I have tried various things like setting the height of the items to fractional(1) but that then prevented multi line. Other attempts such as changing the dimensions of the group did not help either. How can I set up my UICollectionViewCompositionalLayout to achieve my goal please?
Collection View:
NSCollectionLayoutSize *itemSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:0.333] heightDimension:[NSCollectionLayoutDimension fractionalHeightDimension:1]];
NSCollectionLayoutItem *item = [NSCollectionLayoutItem itemWithLayoutSize:itemSize];
NSCollectionLayoutSize *groupSize = [NSCollectionLayoutSize sizeWithWidthDimension:[NSCollectionLayoutDimension fractionalWidthDimension:1] heightDimension:[NSCollectionLayoutDimension estimatedDimension:40]];
NSCollectionLayoutGroup *group = [NSCollectionLayoutGroup horizontalGroupWithLayoutSize:groupSize subitem:item count:3];
NSCollectionLayoutSection *section = [NSCollectionLayoutSection sectionWithGroup:group];
UICollectionViewCompositionalLayout *compositionalLayout = [[UICollectionViewCompositionalLayout alloc] initWithSection:section];
UICollectionView *cv = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:compositionalLayout];
cv.translatesAutoresizingMaskIntoConstraints = NO;
cv.dataSource = self;
cv.delegate = self;
[self.view addSubview:cv];
[cv registerClass:[GridCVCell class] forCellWithReuseIdentifier:#"Cell"];
[cv.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:100].active = YES;
[cv.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:0].active = YES;
[cv.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:0].active = YES;
[cv.heightAnchor constraintEqualToConstant:300].active = YES;
CollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame {
if ([super initWithFrame:frame]) {
UILabel *titleL = [UIlabel new];
titleL.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addSubview:titleL];
[titleL.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:10].active = YES;
[titleL.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-10].active = YES;
[titleL.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor constant:-2].active = YES;
[self.contentView.heightAnchor constraintEqualToAnchor:titleL.heightAnchor constant:10].active = YES;
}
return self;
}
Related
I'm trying to implement a custom table cell using Auto Layout programmatically like below, but for some reason I didn't get the expected result.
Expected:
Actual:
My observation is:
The cell height doesn't grow as the content grows, and content overflows;
The bar element should be a vertical blue bar, but it's not properly showing up;
Setting background colors on the UIView elements doesn't work at all for some reason.
Please share some pointers on what I did wrong. Thanks in advance
UITableViewCell Code is below:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.infoContainer = [[UIView alloc] init];
self.title = [[UILabel alloc] init];
self.time = [[UILabel alloc] init];
self.bar = [[UIView alloc] init];
[self.infoContainer addSubview:self.bar];
[self.infoContainer addSubview:self.title];
[self.infoContainer addSubview:self.time];
[self.contentView addSubview:self.infoContainer];
self.infoContainer.translatesAutoresizingMaskIntoConstraints = NO;
self.title.translatesAutoresizingMaskIntoConstraints = NO;
self.time.translatesAutoresizingMaskIntoConstraints = NO;
self.bar.translatesAutoresizingMaskIntoConstraints = NO;
[self.infoContainer.leftAnchor constraintEqualToAnchor:self.contentView.leftAnchor constant:18].active = YES;
[self.infoContainer.rightAnchor constraintEqualToAnchor:self.contentView.rightAnchor constant:-18].active = YES;
[self.infoContainer.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:10].active = YES;
self.infoContainer.backgroundColor = [UIColor yellowColor];
[self.bar.leftAnchor constraintEqualToAnchor:self.infoContainer.leftAnchor constant:0].active = YES;
[self.bar.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.bar.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:0].active = YES;
[self.bar.heightAnchor constraintEqualToAnchor:self.infoContainer.heightAnchor].active = YES;
[self.bar.widthAnchor constraintEqualToConstant:10];
self.bar.backgroundColor = [UIColor blueColor];
[self.title.leftAnchor constraintEqualToAnchor:self.bar.rightAnchor constant:15].active = YES;
[self.title.rightAnchor constraintEqualToAnchor:self.infoContainer.rightAnchor constant:0].active = YES;
[self.title.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.time.leftAnchor constraintEqualToAnchor:self.title.leftAnchor constant:0].active = YES;
[self.time.rightAnchor constraintEqualToAnchor:self.title.rightAnchor constant:0].active = YES;
[self.time.topAnchor constraintEqualToAnchor:self.title.bottomAnchor constant:10].active = YES;
}
return self;
}
and in the table view, I have:
self.recentView.rowHeight = UITableViewAutomaticDimension;
self.recentView.estimatedRowHeight = 64.0f;
Thanks!
Automatic height completely depends on hooking constraints properly from top to bottom , so you miss 2 constraints
1-
[self.infoContainer.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:10].active = YES;
2-
[self.time.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:10].active = YES;
Tip : If you set top & bottom constraints here
[self.bar.topAnchor constraintEqualToAnchor:self.infoContainer.topAnchor constant:0].active = YES;
[self.bar.bottomAnchor constraintEqualToAnchor:self.infoContainer.bottomAnchor constant:0].active = YES;
Then no need for
[self.bar.heightAnchor constraintEqualToAnchor:self.infoContainer.heightAnchor].active = YES;
I have a view controller animating in from the left edge of screen, and this view controller has a UITableView subview.
On every device and orientation except for one (iPhone X in landscape), this table view shows properly.
On the iPhone X in landscape, the table view is in the correct place but its cells do not populate until you scroll the tableView. Once you scroll, the table view is as if it had been there the whole time but with invisible cells.
This constraint causes the cells to not load:
[tableView.leftAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leftAnchor].active = YES;
And when replacing this constraint with the following, the problem is solved as well:
[tableView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
I've made the background of the UITableView red to show that it is correctly placed, but no rows are showing even though they load in the portrait orientation.
I've also tried leaving it as:
[tableView.leftAnchor constraintEqualToAnchor:self.view.leftAnchor].active = YES;
but doing:
[tableView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
which solves the problem for header cells:
but not content cells:
This code causes the same issue:
[tableView setInsetsContentViewsToSafeArea:YES];
I am setting up my regular cells like this :
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if([reuseIdentifier isEqual: #"LayerCell"]) {
_titleLabel = [[UILabel alloc] init];
_imgView = [[UIImageView alloc] init];
_toggleView = [[UIImageView alloc] init];
[_imgView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:_imgView];
[_imgView.heightAnchor constraintEqualToAnchor:self.heightAnchor multiplier:0.8].active = YES;
[_imgView.widthAnchor constraintEqualToAnchor:self.heightAnchor multiplier:0.8].active = YES;
[_imgView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor].active = YES;
[_imgView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:8].active = YES;
[_imgView setContentMode:UIViewContentModeScaleAspectFit];
[self addSubview:_toggleView];
[_toggleView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_toggleView.heightAnchor constraintEqualToAnchor:_imgView.heightAnchor].active = YES;
[_toggleView.widthAnchor constraintEqualToAnchor:_imgView.widthAnchor].active = YES;
[_toggleView.centerYAnchor constraintEqualToAnchor:_imgView.centerYAnchor].active = YES;
[_toggleView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:-10].active = YES;
[_toggleView setContentMode:UIViewContentModeScaleAspectFit];
[self addSubview:_titleLabel];
[_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
[_titleLabel.heightAnchor constraintEqualToConstant:20].active = YES;
[_titleLabel.centerYAnchor constraintEqualToAnchor:_imgView.centerYAnchor].active = YES;
[_titleLabel.rightAnchor constraintEqualToAnchor:_toggleView.leftAnchor constant:-10].active = YES;
[_titleLabel.leftAnchor constraintEqualToAnchor:_imgView.rightAnchor constant:10].active = YES;
[self layoutIfNeeded];
}
return self;
}
I create a table view in story board. when i change my tableView frame it become horizontal scroll and stop vertical scrolling. i am using auto resizing.
Code on viewDidLoad for table:
_inviTableView.layer.cornerRadius = 5;
_inviTableView.backgroundColor = [UIColor whiteColor];
_inviTableView.layer.masksToBounds = NO;
_inviTableView.layer.shadowOffset = CGSizeMake(0, 0);
_inviTableView.layer.shadowRadius = 10.0;
_inviTableView.layer.shadowOpacity = 0.5;
_inviTableView.clipsToBounds = YES;
[_inviTableView.layer setShadowColor:[UIColor blackColor].CGColor];
_inviTableView.delegate = self;
_inviTableView.dataSource = self;
[self.inviTableView registerClass:[inviYourBoastTableViewCell class] forCellReuseIdentifier:#"inviCell1"];
[self.inviTableView registerNib:[UINib nibWithNibName:#"inviYourBoastTableViewCell" bundle:Nil] forCellReuseIdentifier:#"inviCell1"];
self.inviTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
ViewDidAppear code:
#pragma mark:didappear
-(void)viewDidAppear:(BOOL)animated{
orignalInviTblFrame = _inviTableView.frame;
}
Method where i changed my table frame:
-(IBAction)getYourTopBoastValue:(UIButton*)senders{
inviDetailViewDataIndex = -1;
inviTopDetailViewIndex = (int)senders.tag-1;
[_inviDetailTableView reloadData];
self.inviTableView.frame = CGRectMake(orignalInviTblFrame.origin.x,_inviSelectedView.frame.size.height, orignalInviTblFrame.size.width, orignalInviTblFrame.size.height-_inviSelectedView.frame.size.height);
_inviSelectedView.hidden = NO;
[_inviTableView reloadData];
}
Note:_inviSelectedView is another tableView
I'm having difficulty laying out my custom cell. I have an image view and two labels. A titleLabel and overview label.
My problem is the overviewLabel is extending outside of the cell and is inconsistent. I think this throws off the rest of the labels.
My goal is to fit the labels better to the cell and improve the layout.
My constraints are as follows.
Custom Cell Class
self.photoImageView.translatesAutoresizingMaskIntoConstraints = false;
[self.photoImageView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor].active = YES;
[self.photoImageView.widthAnchor constraintEqualToAnchor:self.photoImageView.heightAnchor].active = YES;
[self.photoImageView.topAnchor constraintEqualToAnchor:margins.topAnchor].active = YES;
[self.photoImageView.bottomAnchor constraintLessThanOrEqualToAnchor:margins.bottomAnchor constant:0].active = YES;
self.photoImageView.contentMode = UIViewContentModeScaleAspectFit;
self.photoImageView.layer.cornerRadius = 17;
self.photoImageView.layer.masksToBounds = YES;
self.titleLabel.translatesAutoresizingMaskIntoConstraints = false;
[self.titleLabel.leadingAnchor constraintEqualToAnchor:self.photoImageView.trailingAnchor].active = YES;
[self.titleLabel.trailingAnchor constraintLessThanOrEqualToAnchor:margins.trailingAnchor].active = YES;
[self.titleLabel.topAnchor constraintEqualToAnchor:margins.topAnchor].active = YES;
self.titleLabel.font = [UIFont fontWithName:#"Avenir-Book" size:13];
self.titleLabel.textAlignment = NSTextAlignmentLeft;
self.overviewLabel.translatesAutoresizingMaskIntoConstraints = false;
[self.overviewLabel.leadingAnchor constraintEqualToAnchor:self.photoImageView.trailingAnchor].active = YES;
[self.overviewLabel.trailingAnchor constraintEqualToAnchor:margins.trailingAnchor].active = YES;
[self.overviewLabel.topAnchor constraintEqualToAnchor:self.titleLabel.bottomAnchor constant:5].active = YES;
[self.overviewLabel.bottomAnchor constraintGreaterThanOrEqualToAnchor:margins.bottomAnchor constant:0].active = YES;
[self.overviewLabel sizeToFit];
In my viewdidLoad for mytableview I have the following
self.moviesTableView.estimatedRowHeight = 100;
self.moviesTableView.rowHeight = UITableViewAutomaticDimension;
I'm trying to implements this library without using storyBoard (first step for implementing this library) , because I'm creating my UIcollectionView programmatically.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.collectionView];
[_collectionView registerNib:[UINib nibWithNibName:#"myCell" bundle:nil] forCellWithReuseIdentifier:#"cell3"];
[_collectionView setBackgroundColor:[UIColor colorWithRed:0.945 green:0.945 blue:0.945 alpha:1] ];
[_collectionView setTransform:CGAffineTransformMakeScale(-1, 1)];
RFQuiltLayout* layout = (id)[_collectionView collectionViewLayout];
layout.direction = UICollectionViewScrollDirectionVertical;
layout.blockPixels = CGSizeMake(100, 100);
}
- (UICollectionView *)collectionView {
if (!_collectionView) {
CGRect collectionViewFrame = self.view.bounds;
collectionViewFrame.size.height -= (self.navigationController.viewControllers.count > 1 ? 0 : (CGRectGetHeight(self.tabBarController.tabBar.bounds))) + 0;
// FMMosaicLayout *mosaicLayout = [[FMMosaicLayout alloc] init];
//// _collectionView = [[UICollectionView alloc] initWithFrame:collectionViewFrame collectionViewLayout:mosaicLayout];
// RFQuiltLayout* layout = (id)[_collectionView collectionViewLayout];
// layout.direction = UICollectionViewScrollDirectionVertical;
// layout.blockPixels = CGSizeMake(100, 100);
_collectionView = [[UICollectionView alloc] initWithFrame:collectionViewFrame collectionViewLayout:[[RFQuiltLayout alloc] init]];
_collectionView.delegate = self;
_collectionView.dataSource = self;
}
return _collectionView;
}
But this didn't worked and nothing is shown in my view (no error and empty view that's all) Also using debugger I've notified that the UICollectionView Method are never called
First of all, your collectionView method is not called because you are using _collectionView instead self.collectionView in your viewDidLoad method. You need to write self for every property to call their setter and getter methods.
Second, if you want to add custom layout without Storyboard of XIB, then you need to set it programmatically:
RFQuiltLayout* layout = [[RFQuiltLayout alloc] init];
layout.direction = UICollectionViewScrollDirectionVertical;
layout.blockPixels = CGSizeMake(100, 100);
self.collectionView.collectionViewLayout = layout;