How to make UITableviewCell Dynamic Height and Expand iOS

Many application has dynamic contents to show from the server. Also many applications has a design to show some controls/views when the user selects the cell to expand.

So, we need to calculate the tableview cell height dynamic and assign to the UITableView Datasource and Delegates.

1. Calculate Table Cell Height

CGFloat height = 5.0f;

    // We are calculating the height based on the value..

    if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@”6.0″)) {

      NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];

        paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

        height += [dynamicString boundingRectWithSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width20, 9999) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont fontWithName:@”Helvetica” size:16], NSParagraphStyleAttributeName:paragraphStyle} context:nil].size.height;

}

    else {

        height += ceilf([dynamicString sizeWithFont:[UIFont fontWithName:@”Helvetica” size:16] constrainedToSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width20, 9999) lineBreakMode:NSLineBreakByWordWrapping].height);

    }

Here is a sample view controller with Tableview integrated..

#import “ViewController.h”

#import “DemoTableViewCell.h”

@interface ViewController ()

@property (nonatomic, unsafe_unretained) IBOutlet UITableView *demoTV;

@property (nonatomic, strong) NSMutableArray *heightArray;

@property (assign) BOOL isNeedToExpand;

@end

static NSString *demoTableCellID = @”DemoTableViewCellIdentifier”;

#define IS_IPHONE5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height – ( double )568 ) < DBL_EPSILON )

#define SYSTEM_VERSION_EQUAL_TO(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)

#define SYSTEM_VERSION_GREATER_THAN(v)             ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

#define SYSTEM_VERSION_LESS_THAN(v)                ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)    ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

@implementation ViewController

– (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    self.title = @”Home”;

    self.isNeedToExpand = NO;

    

}

#pragma mark- Webservice Call

– (void) fetchDataFromServer {

    

    // Storing the dynamic height in an array…

    CGFloat height = 0;

    CGFloat captionHeight = [ViewController calculateDynamicCellHeight:@”Value from server”];

    height = height + captionHeight + 10;

    [self.heightArray addObject:[NSString stringWithFormat:@”%f”,captionHeight]];

}

#pragma mark- UITableview Delegate

– (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {

    return 1;

}

– (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return 4;

}

– (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    

    // Here you can handle the dynamic height from an heightArray values..

    

    if (self.isNeedToExpand) {

        if ((indexPath.row == 2) || (indexPath.row == 1)) {

            return 110;

        } else {

            return 50;

        }

    }

    return 50;

}

– (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    

    DemoTableViewCell *cell = (DemoTableViewCell *) [tableView dequeueReusableCellWithIdentifier:demoTableCellID forIndexPath:indexPath];

    

    if ((indexPath.row == 2) || (indexPath.row == 1)) {

        cell.hiddenLabel.hidden = NO;

    } else {

        cell.hiddenLabel.hidden = YES;

    }

    

    return cell;

}

– (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    

    // Here you have to handle the indexPath which needs to be expand based on the height..

    

    [self.demoTV beginUpdates];

    if ((indexPath.row == 2) || (indexPath.row == 1)) {

        self.isNeedToExpand = YES;

    } else {

        self.isNeedToExpand = NO;

    }

    [self.demoTV endUpdates];

}

// We are calculating the dynamic cell height based on the string…

#pragma mark- Calcualte Cell Height

+ (CGFloat) calculateDynamicCellHeight: (NSString *) dynamicString {

    

    CGFloat height = 5.0f;

    // We are calculating the height based on the value..

    if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@”6.0″)) {

        

        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];

        paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;

        

        height += [dynamicString boundingRectWithSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width20, 9999) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont fontWithName:@”Helvetica” size:16], NSParagraphStyleAttributeName:paragraphStyle} context:nil].size.height;

        

    }

    else {

        height += ceilf([dynamicString sizeWithFont:[UIFont fontWithName:@”Helvetica” size:16] constrainedToSize:CGSizeMake([[UIScreen mainScreen] bounds].size.width20, 9999) lineBreakMode:NSLineBreakByWordWrapping].height);

    }

    

    return height;

}

– (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end

The above source code is just for an idea about dynamic height and expanding cells. Ourself we have to manage the cell views as per our requirement.

Hope it will help someone. Happy Coding. Thanks.

How to insert a row in UITableView with reloadData in iOS?

Hi Friends,

Good Day!

After a long time am come back with new information. Yes we all know very well to insert and add rows in UITableView.
I faced one scenario while my development that was to insert a last row in UITableView without reload it. Yes i have done with the new flow.
Am going to share that simple code with your all for your reference

Before that we have to read about UITableView from here.

First we have to take the indexpath using your data count which is stored in NSMutableArray, NSArray or something else.

NSArray *indexPathArray = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:[messagesArray count] inSection:0];

messagesArray is my NSMutableArray.

Now am going to add new data in my messagesArray from UITextView text.

[messagesArray addObject:messageTextView.text];

Now am going to update the tableview,

[messagesTableView beginUpdates];

And now am going to insert new row in the selected indexpath,

[messagesTableView insertRowAtIndexpaths:indexPathArray withRowAnimation:UITableViewRowAnimationTop];

After that finally just terminate the tableview updation,

[messagesTableView endUpdates];

Above the way i was used to update the UITableView without Reloading it. I hope it will help you little bit.
If you feel anything about this jsut let me know. Am waiting for your thoughts. Thanks.

Happy Coding

Warm Regards,
Yuvaraj.M

How handle UITableView Edit option using Swipe in iOS apps?

Hi Friends,

Today am going to post to handle UITableView Editing mode with Swipe control.

We have to add a bar button item named as “Edit” in left hand side of UINavigationBar. When the user clicks on the button we have to change the “Edit” button to “Done” and add the edit mode to the tableview.

UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editingTable)];
self.navigationItem.leftBarButtonItem = editButton;

Add the method for UIBarButtonItem action,

-(void)editingTable
{
// Here we are using a single button to two purposes edit and done…

if (TableView.editing)
{
isTableEditMode = NO;

[TableView setEditing:NO animated:YES];
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editingTable)];
self.navigationItem.leftBarButtonItem = editButton;
[TableView reloadData];
}
else
{
if ([NameArray count] >0)
{
isTableEditMode = YES;

[TableView setEditing:YES animated:YES];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(editingTable)];
self.navigationItem.leftBarButtonItem = doneButton;
[TableView reloadData];
}
}
}

Add the delegates which are going to help us to edit the tableview.

-(BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

– (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Detemine if it’s in editing mode
if (TableView.editing)
{
return UITableViewCellEditingStyleDelete;
}
else
{
self.navigationItem.rightBarButtonItem = nil;
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(editingTable)];
self.navigationItem.leftBarButtonItem = doneButton;
isTableEditMode = YES;
tableViewIsInEdit = YES;
return UITableViewCellEditingStyleDelete;
}
}

If condition will be called when the user select the “Edit” button from the navigation bar. Else condition will be called when the user swipe the tableview to delete the items from the tableview.

editingStyleForRowAtIndexPath: is the delegate decide the editing mode for example the tableview should me delete or editing.

When the user selects the Delete button from the editing mode the below delegate will be called. Here we can find the indexpath and we can delete the data from NSMutableArray, NSArray and Core Data.

-(void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSString *selectedName = [NameArray objectAtIndex:indexPath.row];

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@”customerName == %@”,selectedName];
NSEntityDescription *entity = [NSEntityDescription entityForName:@”Messages” inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setPredicate:predicate];

NSError *error;
NSArray *items = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
[fetchRequest release];

for (NSManagedObject *managedObject in items)
{
[managedObjectContext deleteObject:managedObject];
}
if (![managedObjectContext save:&error])
{
NSLog(@”Error  :%@”,[error description]);
}
}
}

I have deleted the selected indexpath item from CoreData. You can modify the able code in the If condition block from NSMutableArray or etc.,

If the user delete the data from Swipe control we have to use below code to terminate the Swipe editing mode.

-(void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
isTableEditMode = NO;

[TableView setEditing:NO animated:YES];
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(editingTable)];
self.navigationItem.leftBarButtonItem = editButton;
[TableView reloadData];

tableViewIsInEdit = NO;
}

I hope this will help you little bit and save some of your valuable time. Happy coding.

Thanks.

Warm Regards,

Yuvaraj.M

How to get UITableviewCell index by UIButton Click in iOS app?

Hi Friends,
Today am going to post to get current UITableviewCell indexPath by UIButton Action.

– (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString *CellIdentifier = @”Cell”;

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

UIButton *getInfoButton = [UIButton buttonWithType:UIButtonTypeCustom];
getInfoButton.titleLabel.textAlignment = UITextAlignmentRight;
getInfoButton.titleLabel.font = [UIFont systemFontOfSize:13];
[getInfoButton addTarget:self action:@selector(getUserInfo:) forControlEvents:UIControlEventTouchUpInside];
getInfoButton.tag = 100;
[cell.contentView addSubview: getInfoButton];
}
else
{
UIButton * getInfoButton = (UIButton *) [cell.contentView viewWithTag:105];
}
return cell;
}

-(void)getUserInfo:(id) sender
{
UITableViewCell *clickedCell = (UITableViewCell *)[[sender superview] superview];
NSIndexPath *clickedButtonIndexPath = [messagesTableView indexPathForCell:clickedCell];

int selectedIndexPath = clickedButtonIndexPath.row;
NSLog(@”SelectedIndexPath: %d”, selectedIndexPath);

NSString *userInfo = [userInformationArray objectAtIndex:selectedIndexPath];
NSLog(@”userInfo : %@”, userInfo);
}

I hope it will help anyone. Happy coding. Thanks.

Warm Regards,
Yuvaraj.M