iOS - Auto resizing table view cells - ios

I'm having some troubles with auto-resizing table view cells. I've been able to resize a cell's label based on its amount of text but I'm unable to adjust the cell height accordingly. Here's some code:
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
_cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (_cell == nil)
{
_cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PFObject *object = [_postsArray objectAtIndex:indexPath.row];
NSString *nameString = [object objectForKey:#"Name"];
_cell.cellLabel.text = [NSString stringWithFormat:#"Posted by %#", nameString];
_cell.cellPostLabel.text = [NSString stringWithFormat:#" %#", [object objectForKey:#"PostedDream"]];
[_cell.cellPostLabel sizeToFit];
[tableView setAutoresizesSubviews:YES];
NSLog(#"cell post label height: %f", _cell.cellPostLabel.frame.size.height);
return _cell;
}
Things to note are that I am using a custom table view cell called TableViewCell *cell subclassed from UITableViewCell and the cell and its labels were added through IB.
The label that's being adjusted is cellPostLabel and it adjusts perfectly depending on the amount of text, but it gets cut off due to the cell not adjusting as well.
I also tried calling [self.tableView setAutoresizesSubviews:YES]; and
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight; in viewDidAppear: but still nothing. Any suggestions would be appreciated.

Cell height is determined by heightForRowAtIndexPath method.
You can implement that method on your viewcontroller and return height you prefer.
If your cell should have different height you should implement that method and return different value each cells. Or not just return static value or set tableview's property rowHeight, in this case you don't need to implement that method.

Related

Cannot set text in textview in my custom tableView cell

I am trying to load my UITextView on UItableViewCell with data but unable to set text. UITextViewDelegate is also set and attached to view controller. The text string is not empty as I checked it using debugger.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CommentCellIdentifier];
//CommentCell is my custom cell with textView.
CommentCell *commentsCell = (CommentCell*)[tableView dequeueReusableCellWithIdentifier:CommentCellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CommentCellIdentifier];
}
//Setting the images for all buttons in service row.
[commentsCell.deletecomment setImage:deleteComment forState:UIControlStateNormal];
[commentsCell.editcomment setImage:editComment forState:UIControlStateNormal];
commentsCell.deletecomment.layer.borderColor = [UIColor blackColor].CGColor;
commentsCell.editcomment.layer.borderColor = [UIColor blackColor].CGColor;
NSInteger commentIndex = 2;
//CommentsArray is NSArray with data.
[commentCell.comments setText:[NSString stringWithFormat:#"%#",[[commentsArray objectAtIndex:indexPath.row] objectAtIndex:commentIndex]]];
return cell;
}
Try changing this line:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CommentCellIdentifier];
to this line:
CommentCell *cell = (CommentCell*)[tableView dequeueReusableCellWithIdentifier:CommentCellIdentifier];
I was using wrong cellname. Just replaced "commentCell" with "commentsCell" and everything starts working.
[commentsCell.comments setText:[NSString stringWithFormat:#"%#",[[commentsArray objectAtIndex:indexPath.row] objectAtIndex:commentIndex]]];`enter code here`
If you do not need scrolling the textview DISABLE SCROLLING in order for the text to appear.
I am not sure if this is caused by the fact that both the tableview and textview are descendants of UIScrollView, but it could be.
It helped me when I was experiencing the same issue

First 5 cells not showing image in custom TableView Cell - iOS

I have a UITableView which I have transformed into horizontal tableview, and a custom UITableViewCell which just has a UIImageView and a UILabel
The problem is, first 5 cells don't show the images, but when I scroll and come back to them, images are shown. No idea what the problem is :(
(picture below, please see the horizontal tableview, ignore the vertical one)
Here's my code in TableViewController Class:
-(void)viewDidLoad
{
//Rotating the tableview angle -PI/2 Rad = -90 Degrees
_friendsTableView.transform= CGAffineTransformMakeRotation(-M_PI_2);
_friendsTableView.translatesAutoresizingMaskIntoConstraints = YES;
CGRect frame = _friendsTableView.frame;
frame.origin.y= _segmentControl.frame.size.height;
frame.origin.x= 0;
frame.size.width = self.view.frame.size.width;
frame.size.height = 105.5;
_friendsTableView.frame= frame;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FriendsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (nil == cell) {
cell = [[FriendsTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
if(cell)
{
cell.user = cellsArray_[indexPath.row];
cell.transform =CGAffineTransformMakeRotation(M_PI_2);
}
return cell;
}
Now this is my custom cell class code where I set the image and label (_user is a property, so this setter method gets called automatically from cell.user):
-(void)setUser
{
_profileImageView.layer.cornerRadius = _profileImageView.frame.size.width/2;
_user = user;
_nameLabel.text = #"Hello";
[_profileImageView setImage:[UIImage imageNamed:#"placeholder_image"]];
}
Why dont you use Collection View controller instead. Transforming Tableview controller seems not good.
In your code your are not calling your setUser method.
For Custom table view cell you can add following code in
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:strID];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyCustomCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
}
For my experience this is strictly related to the reusability of the Cells, i had a similar problem once, my solution is before assigning something to an IBOulet, make sure to have it empty, after that, assign it and it should work.

Cell and TextField not showing serialwise in UITableView

I am using UITextField, and every row have a CellLable and TextField. Lable and TextField data comes from array. While running the app, all data are comes fine but when scrolling the Tableview, Last 2-3 Rows unorganized.
NSMutableArray
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ArrFieldData= [NSMutableArray arrayWithObjects:#"Fist Name", #"Last Name",#"User Name", #"Password",#"Confirm Password", #"Gender",#"DOB", #"Profile Pic",#"Deparment", #"Joining Date",#"Education", #"Role", nil];
Now cellForRowAtIndexPath Function
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
txtField = [[UITextField alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/3 + 40, 2, [UIScreen mainScreen].bounds.size.width/2, cell.layer.frame.size.height -5)];
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
[self UpdateCell:cell withIndexPath:indexPath withTextField:txtField];
return cell;
}
SetUp Cell Function
-(void)setUpCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath withTextField: (UITextField *)txtField {
cell.textLabel.text = [ArrFieldData objectAtIndex:indexPath.row];
cell.textLabel.font = [UIFont systemFontOfSize:12.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
txtField.tag = indexPath.row+1;
txtField.layer.borderColor = [UIColor grayColor].CGColor;
txtField.delegate = self;
txtField.layer.borderWidth = 1.0f;
txtField.layer.cornerRadius = 4.0f;
txtField.placeholder = cell.textLabel.text;
txtField.font = [UIFont systemFontOfSize:12.0];
[cell.contentView addSubview: txtField];
}
Update Cell Function
-(void)UpdateCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath withTextField: (UITextField *)txtField {
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
First time Running the application, It is showing all cell and textfield data are Serialize. but when scroll some cell and TextField are not serialize as per Array Value. I am attaching the Simulator Screenshot.
First Screenshot for First time running, and second for when i scroll the Tableview. See the last 4-5 cell and Textfield Placeholder text. They are un-organized. I want it shouldn't change.
As you are using reusable cells, like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
txtField = [[UITextField alloc]initWithFrame:CGRectMake([UIScreen mainScreen].bounds.size.width/3 + 40, 2, [UIScreen mainScreen].bounds.size.width/2, cell.layer.frame.size.height -5)];
[self setUpCell:cell withIndexPath:indexPath withTextField:txtField];
}
[self UpdateCell:cell withIndexPath:indexPath withTextField:txtField];
return cell;
}
UITableView uses the concept of reusable cell to achieve maximum performance by reducing the memory consumption, and to exploit this feature of reusing cells you can use the above UITableView's API's to achieve that.
But before using any feature it's very important to understand the working and the usage of any feature.
In your above implementation of tableView: cellForRowAtIndexPath: method, you have used the concept of cell reusability.
If the cells doesn't exist and are created for the first time, than they are allocated(every subview is created and added on the content view of the cell), customized and initialized with the data from the data source of the respective index path.
But in case the cells are reused(as they were already created for any other index path), there subviews exist with the data already filled for the previous index path for which it was created.
Now there are two things we can do to use already created cell for the current index path,
1) if the cells contain subview with data then remove the subviews and recreate the new ones, customize and populate them with the data.
2) rather than releasing the previous subviews and creating new ones, refill the data for the data model of the corresponding index path.
In your case, if the cell is being created for any index path, than the text filed for it is also created and if it's reused than the new text field is not created and it's being reused from the previously created cell thus the issue of the placeholder text not matching with the left text.
So, in order to solve your problem I think you should either create the textfield when the cell is created and if the cells are reused than refill the data in the text filed from the data source of the corresponding index path.
Your problem is due to a feature of UITableView. When you scroll a UITableView the indexPath is updated so you are not getting the index values you are expecting from the tableView.
Instead of adding a UITextField programmatically. Create a Custom UITableViewCell and from the method cellForRowAtIndexPath: update the placeHolder of your UITextField. The tableView will take care of scrolling for you.
Use this code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
UITextField *txtField ;
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
cell.textField.placeholder= cell.textLabel.text;
}
cell.textField.placeholder= cell.textLabel.text;
return cell;
}

UITableViewCell - ContentView overlapping when scrolling

I have added a UILabel as the content view of my tableview. The text in the UILabel is overlapping upon scrolling. Below is the code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.chatTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"Group"];
static NSString *CellIdentifier = #"Group";
UITableViewCell *cell = [self.chatTableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = self.latestTrimText;
UILabel *cellLabel = [[UILabel alloc]init];
cellLabel.text = self.dateOfLatestTrim;
cellLabel.frame = CGRectMake(15, 0, 150, 30);
[cell.contentView addSubview:cellLabel];
return cell;
}
I can fix this by changing to UITableViewCell *cell = [self.chatTableView dequeueReusableCellWithIdentifier:nil];
But then, the scrolling of the tableview won't be smooth. Is there another way to fix the issue?
The tableview cells are recycled and reused potentially an infinite amount of times. This is what the reuse identifier stands for.
Take care not to add any subview outside the if (cell==nil) block. Now you are just adding again and again a new label to the same cell instance. This is why your texts overlaps each other.
I would recommend you to read the documentation on how the cells are recycled and reused.
Your fix is not correct because by passing a nil reuse id, you are just preventing the recycling process to play. You create a new instance for each row of your tableview. This is why you have performance issues then.

How to show full text of a labelview in cell, when height is changed

I have a tableview with a customized cell in it, in my cell, I have one label and one image, text in label is long, so I just show first 2 lines and then show 3dots "..." using linebreaks, and then when user tap cell, it will expand to show full text of label
I change height of cell when taped, I do this like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView indexPathsForSelectedRows].count) {
if ([[tableView indexPathsForSelectedRows] indexOfObject:indexPath] != NSNotFound) {
MsgInfo *info = [_msgInfos objectAtIndex:indexPath.row];
NSString *displayString = info.msg;
CGRect boundingRect =
[displayString boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width - 2 * 10, 1000) options:NSStringDrawingUsesLineFragmentOrigin attributes:
#{ NSFontAttributeName : [UIFont fontWithName:#"B Yekan" size:18.0f]} context:nil];
CGFloat rowHeight = ceilf(boundingRect.size.height);
NSLog(#"Height = %f for '%#'", rowHeight, displayString);
return 54 + rowHeight + 2 * 10; // Expanded height
}
return 92; // Normal height
}
return 92; // Normal height
}
So when I tap a cell, it expands based on my label text font and size,
But now I want to show full text of label, I know I have to set label.numberofline =0 in didSelectRowAtIndexPath, but it doesnot work.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"MsgCell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
}
UILabel *nameLabel = (UILabel *)[cell viewWithTag:100];
nameLabel.numberOfLines =0;
[nameLabel sizeToFit];
[nameLabel setLineBreakMode:NSLineBreakByWordWrapping];
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
any help?
In didSelectRowAtIndexPath you're creating a new cell and changing its settings (not editing the existing cell and not any cell that will be used for display soon). What you should be doing is triggering a reload of the selected cell so that the new height is recalculated and the cell reloaded. In tableView:cellForRowAtIndexPath: you should have similar logic to check if the row is selected and then set the number of lines on the label.
Doing it in tableView:cellForRowAtIndexPath: will also prevent you from having issues on deselection as you must always set the number of lines for each cell whenever it is reused.

Resources