I have an already existing table view in my app which I'm trying to add a new cell to. The new cell will display a variable amount of buttons, each of which has a title (and thus a dynamic width). The new cell is supposed to look like this:
┃┃ ┃┃ <---- existing cells above
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
┃┃┏━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━┓ ┃┃
┃┃┃ 632 ┃ ┃ 12345678901728933 ┃ ┃┃
┃┃┗━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━┛ ┃┃
┃┃┏━━━━━━━━━━━┓ ┏━━━━━━┓ ┏━━━━━━┓ ┃┃
┃┃┃ 123345573 ┃ ┃ jhkl ┃ ┃ dasd ┃ ┃┃ <---- new cell
┃┃┗━━━━━━━━━━━┛ ┗━━━━━━┛ ┗━━━━━━┛ ┃┃
┃┃┏━━━┓ ┏━━━━━━━━━━━━━━┓ ┏━━━┓ ┃┃
┃┃┃ 1 ┃ ┃ 128732434554 ┃ ┃ 1 ┃ ┃┃
┃┃┗━━━┛ ┗━━━━━━━━━━━━━━┛ ┗━━━┛ ┃┃
┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃
┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃
┃┃ ┃┃ <---- existing cells below
The buttons should file on one line until the next one would overflow the cell, at which point it should wrap on to the next line (similar to a UILabel with word wrapping).
UITableViewAutomaticDimension
from my tableView:heightForRowAtIndexPath
method and the cell needs to calculate its own height. cellForRowAtIndexPath
. beginUpdates/endUpdates
on the table view to resize its cells. [UIScreen mainScreen]
to calculate the ideal width of the cell. intrinsicContentSize
. This implementation would return the collection view's contentSize
, or the collection view's UICollectionViewFlowLayout's collectionViewContentSize()
(I tried both). The issue here is that these values don't return the actual content size until after the collectionView has been laid out, at which point my UITableView has already cached the cell height as 0. layoutSubviews
is called, at which point UITableView has already cached the height of the cell. I tried using something like https://github.com/xhacker/TagListView where the custom view manually calculates the frames of everything when layoutSubviews
is called and reports (the number of rows) * (the height of each row) as its intrinsic content height, but the problem is that by the time this calculation happens, the frame of the view is 0 (since it's being laid out inside a UITableViewCell) and thus the intrinsic content size is calculated wrong, resulting in something like this:
┃┃ ┃┃ <---- existing cells above ┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃ ┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃ ┃┃┏━━━━━┓ ┏━━━━━━━━━━━━┓ ┃┃ ┃┃┃ 632 ┃ ┃ 6327237842 ┃ ┃┃ ┃┃┗━━━━━┛ ┗━━━━━━━━━━━━┛ ┃┃ ┃┃┏━━━━━━━━━━━━━━━━━━━┓ ┃┃ ┃┃┃ 12345678901728933 ┃ ┃┃ ┃┃┗━━━━━━━━━━━━━━━━━━━┛ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ <---- new cell ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┃ ┃┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛┃ ┃┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓┃ ┃┃ ┃┃ <---- existing cells below
In general, UITableView caching the height of the cell causes there to be a constraint called UIView-Encapsulated-Layout-Height, which has a constant of 0, and is well documented in many SO posts. As far as I can tell there's no way to re-calculate this height from the cell level: setNeedsUpdateConstraints
, setNeedsLayout
, layoutIfNeeded
, invalidateIntrinsicContentSize
, and any combination thereof that I've tried have not helped.
This has been really baffling me for the past two days. I'm wondering if anyone has implemented anything like this before and has found a good way to do it reliably, or can offer any advice as to how to tackle this problem.
Write this in table cellforRowAtIndexPath method.
y=20;
x=20;
for (int i=0; i<[arrAssignUsers count]; i++) {
CGRect screenRect=[[UIScreen mainScreen]bounds];
CGFloat screenWidth=screenRect.size.width;
[arrBtnStatus addObject:[NSNumber numberWithBool:NO]];
NSString *strNames=[arrAssignUsers objectAtIndex:i];
stringsize=[strNames sizeWithAttributes:
@{NSFontAttributeName: [UIFont systemFontOfSize:20.0f]}];
btn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
CGFloat m=x+stringsize.width+10;
CGFloat n=screenWidth-20;
if (m<=n) {
btn.frame=CGRectMake(x, y,stringsize.width,stringsize.height);
x=x+stringsize.width +10;
}
else
{
y=y+stringsize.height+10;
x=20;
btn.frame=CGRectMake(x, y,stringsize.width,stringsize.height);
x=x+stringsize.width+10;
}
[btn setTitle:self.arrAssignUsers[i] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
btn.tag=i;
[btn addTarget:self
action:@selector(notifyButtonPressedInEditTask:) forControlEvents:UIControlEventTouchUpInside];
btn.backgroundColor=[UIColor whiteColor];
btn.layer.cornerRadius=10;
[btn.layer setMasksToBounds:YES];
btn.layer.borderWidth=2.0f;
btn.layer.borderColor=[UIColor orangeColor].CGColor;
[self checkNotifybtnStatus:btn];
[cell addSubview:btn];
return cell;
Then write this method:
-(void)checkNotifybtnStatus:(UIButton *)clicked{
state = [[arrBtnStatus objectAtIndex:clicked.tag]boolValue];
if ((clicked.tag>=0)&&(state==YES)) {
clicked.backgroundColor=OS_ORANGE_COLOR;
}
else
clicked.backgroundColor=[UIColor clearColor];
}
Then write this.
-(void)notifyButtonPressedInEditTask:(id)sender{
UIButton *clicked = (UIButton *) sender;
NSLog(@"%ld",(long)clicked.tag); //Here you know which button has pressed
for (UserListData *taskData in arrAssignUserInfoList) {
[arrNotifyUsers addObject:taskData.strUniqID];
}
state = [[arrBtnStatus objectAtIndex:clicked.tag]boolValue];
if ((clicked.tag>=0)&&(state==NO)) {
[arrBtnStatus replaceObjectAtIndex:clicked.tag withObject:[NSNumber numberWithBool:!state]];
clicked.backgroundColor=[UIColor colorWithRed:254.0/255.0 green:139.0/255.0 blue:26.0/255.0 alpha:1];
[arrNotifySelectedUsers addObject:[arrNotifyUsers objectAtIndex:clicked.tag]];
NSLog(@" arr new--%@",arrNotifySelectedUsers.description);
}
else
{
clicked.backgroundColor=[UIColor clearColor];
[arrBtnStatus replaceObjectAtIndex:clicked.tag withObject:[NSNumber numberWithBool:!state]];
[arrNotifySelectedUsers removeObject:[arrNotifyUsers objectAtIndex:clicked.tag]];
NSLog(@" arr new--%@",arrNotifySelectedUsers.description);
}
}
Change the variable according to your project. This will may help you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.