Autolayout of my UITableViewCell works as expected when viewing, but when I selecting a row, the UI will break, and the height of this cell will also back to default value.
For cell-related code, I just followed this tutorial "Using Auto Layout in UITableView for dynamic cell layouts & variable row heights"
Unfortunately, this tutorial doesn't cover selection part of UITableViewCell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell = ...
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController pushViewController:MyViewController animated:YES];
}
Related
I create a custom table view cell using autolayout as this picture below
When the app launch, every thing be fine. but when i scroll tableview or select a view, cell's layout will be changed.
Whats happen?
code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdent];
[cell.textLabel setText: textToSHow];
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
[cell setNeedsLayout];
[cell layoutIfNeeded];
CGSize fitSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return fitSize.height;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdent];
[cell.textLabel setText:textToSHow];
return cell;
}
run app:
when a cell is selected:
Many thanks!
iOS 8+ solution (using autolayout):
Add this to your viewDidLoad:
self.tableView.estimatedRowHeight = 44;
self.tableView.rowHeight = UITableViewAutomaticDimension;
And remove the tableView:heightForRowAtIndexPath: method.
I think you need to change some codes in your existing implementation. Try this by replacing your existing code.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGSize fitSize = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return fitSize.height;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdent forIndexPath:indexPath];
[cell layoutIfNeeded];
[cell.textLabel setText:textToSHow];
return cell;
}
I'm trying to achieve airbnb look for my UITableViewController.
separators are not in the full width of the screen
each cell has a unique size and background color
I've managed to tackle #2 using static table and setting each cell size in IB but have the following problems:
setting a background color in IB didn't take (changed both background color as well as tint)
I wish to "delete" a cell programmatically when it has no content but the only function that returns cell height - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
is generic for all cells and is called prior to populating the cells with data, so at this method I can't decide if the cell should be deleted or not.
I think you should use the delegate method willDisplayCell: forRowAtIndexPath: of the table view. This delegate method is called just before the cell is ready to be displayed on the table view. In this delegate you will have the cell created, if you need some modifications you can do here, which will be reflected just before the cell is displayed.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[cell setBackgroundColor:[UIColor redColor]];
// and all other cell customizations
}
You could set separatorInset and layoutMargins properties of table view before layout subviews and cell's separatorInset and layoutMargins properties before displaying cell.
For setting custom cell's height you may get needed cell by calling a table view data source method instead of call cellForRowAtIndexPath: method of table view.
Example:
// 1. Make full width separators:
- (void)viewWillLayoutSubviews {
if ([self.tableView respondsToSelector:#selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:#selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
#pragma mark - Table view data source
// 2.Customize cells background color and height
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = [NSString stringWithFormat:#"s%ld-r%ld", indexPath.section, indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
if (indexPath.row % 2) {
cell.backgroundColor = [UIColor redColor];
cell.contentView.backgroundColor = [UIColor whiteColor];
cell.textLabel.text = cellIdentifier;
} else {
cell.backgroundColor = [UIColor cyanColor];
cell.contentView.backgroundColor = [UIColor whiteColor];//background color of contentView overlaps cell's background color
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath]; //getting cell at indexPath
if ([self isCellEmpty:cell]) {
return 22;
}
return 44;
}
- (BOOL)isCellEmpty:(UITableViewCell *)cell {
return !cell.textLabel.text.length; //Place your code for checking cell's content
}
I want to resize a UITableViewCell when it is selected. In iOS 7 I designed two table view cells of different heights and replaced the one with the other when selected:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
// ...
}
I set the height correspondingly:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([self.tableView.indexPathForSelectedRow isEqual:indexPath]) {
return 163.0f;
}
else {
return 60.0f;
}
}
Problem:
When selecting the row on iOS 8 it will load the new cell but it won't change the height of the cell. Instead it will break one of my constraints, enforcing the systems "<NSLayoutConstraint:0x7f9fdb72b1f0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f9fdb7009f0(60.6667)]>" constraint.
My first solution was to use - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath instead of - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath but this doesn't work on iOS 7.
Implementing both methods will not produced the desired result on either OS.
I have a problem with swipe delete function in UITableView with cell loaded from an XIB. As you can see below, when I swipe the cell to left image moves left but label doesn’t. So label covers delete button. Below you can find the code I have implemented:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
//remove the deleted object from your data source.
//If your data source is an NSMutableArray, do this
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"MostKadroCell";
MostKadroCell *cell = (MostKadroCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell.contentView setUserInteractionEnabled: NO]; //
cell.lblKadroName.text = [arrKadroName objectAtIndex:indexPath.row];
[cell.imageView setImage:[UIImage imageNamed:strImage]];
return cell;
}
- (void)viewDidLoad
{
[super viewDidLoad];
UINib *nib = [UINib nibWithNibName:#"MostKadroCell" bundle:nil];
[self.tableMostKadro registerNib:nib forCellReuseIdentifier:#"MostKadroCell"];
....
Keep label under(inside) the content view of the UITableView cell. Please check if its not out side the content view.
and add
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
View should seems likes
What's the label "Office" called in the following image?
And how do you set that programmatically?
That appears to be the detailTextView of a table cell with the UITableViewCellStyleValue1 style.
You would set the text in tableView:cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [table dequeueReusableCellWithIdentifier:#"MyCellIdentifier"];
cell.textLabel.text = #"Ringtone";
cell.detailTextLabel.text = #"Office";
return cell;
}