Wednesday 10 August 2011

TableView with Textfield


Today we are going to know how to use textfield in an tableview.Most of you may be knowing it but here I am going to explain most easiest and tricky way.


First let us create a new project by some name.



@interface SBSpeakerCustomCell : UITableViewCell {
UILabel *mLabel;
UITextField *mTextField;
}
@property (nonatomic, retain)UILabel *mLabel;
@property (nonatomic, retain)UITextField *mTextField;
@end


#import "SBSpeakerCustomCell.h"

@implementation SBSpeakerCustomCell
@synthesize mLabel,mTextField;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.

mLabel = [[UILabel alloc] initWithFrame:CGRectMake(15, 5, 100, 35)];
[mLabel setTextAlignment:UITextAlignmentRight];
[mLabel setBackgroundColor:[UIColor clearColor]];

[self addSubview:mLabel];

mTextField = [[UITextField alloc] initWithFrame:CGRectMake(mLabel.frame.origin.x + mLabel.frame.size.width+2, 5, self.frame.size.width - (mLabel.frame.size.width+mLabel.frame.origin.x)- 15, 35)];
[mTextField setBackgroundColor:[UIColor clearColor]];
[self addSubview:mTextField];
}
return self;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {

[super setSelected:selected animated:animated];

// Configure the view for the selected state.
}

- (void)dealloc {
[mLabel release];
[mTextField release];

[super dealloc];
}

@end


Here I have use TableViewWithTextFieldViewController for this example.

@interface TableViewWithTextFieldViewController : UIViewController {


NSMutableArray *mArrayList;

BOOL isEditMode;

int numberOfSectionPerRow;

NSMutableArray *mArray;

NSMutableArray *mDetailslist;

int count;
}
@end



Here I am using 3 array for different reason don't worry about it, we will concentrate only on how we are using textfield in tableview.

As you can notice I have used custom cell for the textfield. Copy & paste the code as it is.

#import "TableViewWithTextFieldViewController.h"

#import "SBSpeakerCustomCell.h"
#define kNavigationBar 104
@implementation TableViewWithTextFieldViewController


- (void)loadView {

UIView *mainView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];

[mainView setBackgroundColor:[UIColor clearColor]];

self.view = mainView;

[self.navigationController.navigationBar setHidden:NO];

UINavigationBar *theNavigationBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];

[theNavigationBar setTintColor:[UIColor colorWithRed:0.4039216041564941 green:0.6470588445663452 blue:0.062745101749897 alpha:1]];

UINavigationItem *theNavigationItem = [[UINavigationItem alloc] init];

theNavigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(EditAction:)];

[theNavigationBar setItems:[NSArray arrayWithObjects:theNavigationItem,nil]];

[theNavigationBar setTag:kNavigationBar];

[self.view addSubview:theNavigationBar];

[theNavigationItem release];

[theNavigationBar release];

UITableView *speakerTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40) style:UITableViewStyleGrouped];

speakerTable.delegate = self;

speakerTable.dataSource = self;

speakerTable.tag = 103;

[self.view addSubview:speakerTable];

[speakerTable release];

isEditMode = NO;

mArray = [[NSMutableArray alloc]initWithObjects:@"Bedroom",@"Cabinet",@"Bathroom",@"Hall",@"Mobile",@"Balcony",@"Others",nil];

mDetailslist = [[NSMutableArray alloc] initWithObjects:@"",@"",@"",@"",@"",@"",@"",nil];

count =0;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
count = 0;

return 2;
}

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

//if table is in editing mode return number of rows equivalent to number of items
if(section == 0)
numberOfSectionPerRow =5;

else 
numberOfSectionPerRow =2;


return numberOfSectionPerRow;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(!isEditMode)
{
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

}
int section1;

if(indexPath.section == 1)
section1 = 5;
else
section1 = 0;

int row =section1 + indexPath.row;


cell.textLabel.text=[NSString stringWithFormat:@"%@ : %@",[mArray objectAtIndex:row],[mDetailslist objectAtIndex:row]];

[cell.textLabel setTextAlignment:UITextAlignmentRight];

cell.textLabel.backgroundColor = [UIColor clearColor] ; 

cell.detailTextLabel.backgroundColor = [UIColor clearColor] ;

count++;

return cell;

}

else {

static NSString *CellIdentifier = @"Cell1";

SBSpeakerCustomCell *cell =(SBSpeakerCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[SBSpeakerCustomCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];

}

[cell.mTextField setTag:(indexPath.section *10)+ indexPath.row];//(indexPath.section *10)+ indexPath.row

cell.mTextField.delegate = self;

int section1;

if(indexPath.section == 1)
section1 = 5;
else
section1 = 0;

int row =section1 + indexPath.row;


[cell.mLabel setText:[NSString stringWithFormat:@"%@ : ",[mArray objectAtIndex:row]]];
[cell.mTextField setText:[mDetailslist objectAtIndex:row]];

count++;

return cell;
}

}



Whenever an Edit button is pressed I am animating the table and reloading it.



-(void)EditAction:(id)sender {


UINavigationBar *theNavigationBar = (UINavigationBar *) [self.view viewWithTag:kNavigationBar];

if(!isEditMode)
[[theNavigationBar topItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStylePlain target:self action:@selector(DoneAction:)]];

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103];

isEditMode = YES;

for (int i=0 ;i < numberOfSectionPerRow ; i++) {

[speakerTable beginUpdates]; [speakerTable deleteSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom];

[speakerTable insertSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; 

[speakerTable endUpdates]; 
}

-(void)DoneAction:(id)sender {
UINavigationBar *theNavigationBar = (UINavigationBar *) [self.view viewWithTag:kNavigationBar];

if(isEditMode){ 
[[theNavigationBar topItem] setRightBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@"Edit" style:UIBarButtonItemStylePlain target:self action:@selector(EditAction:)]];
}

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103]; 
isEditMode = NO;

for (int i=0 ;i < numberOfSectionPerRow ; i++) {

[speakerTable beginUpdates]; 

[speakerTable deleteSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; 

[speakerTable insertSections:[NSIndexSet indexSetWithIndex:i ] withRowAnimation:UITableViewRowAnimationBottom]; [speakerTable endUpdates]; 

[speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40)];

NOTE: Here I am going to explain how to scroll the table as and when we switch to next textfield.As you know that keyboard is an event which differ from tableview events. You can try without using below logic and find the difference. Did you find any difference or problem without using below logic. Let me explain you briefly if you have not understood. Once you press on Edit button table get's animate & return into edit mode, Where we find the textFields in the Tableview. Now comes the play when you tap on any textfield within the cell and try to switch to another the textfield by pressing TAB or retrun it cursor move to the next textfield but the tableview will not scroll and the textfield is behind the keyboard which cannot be visible to the user. Now copy below code and run it.


- (void)textFieldDidBeginEditing:(UITextField *)textField {
int row = [textField tag]%10;
int section = [textField tag] /10;

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103]; [speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, 210)]; 

NSIndexPath *indPath = [NSIndexPath indexPathForRow:row inSection:section];
[speakerTable scrollToRowAtIndexPath:indPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

- (void)textFieldDidEndEditing:(UITextField *)textField{ 

int row = [textField tag] %10; int section = [textField tag] /10; int index = 0; if(section >= 1)

index = 5;

index = index + row;

[mDetailslist insertObject:[textField text] atIndex:index];

}

- (BOOL)textFieldShouldReturn:(UITextField *)textField 
{

UITableView *speakerTable = (UITableView *) [self.view viewWithTag:103];

[textField resignFirstResponder];

[speakerTable setFrame:CGRectMake(0, 40, self.view.frame.size.width, self.view.frame.size.height+ 40)];

return YES;
}

Did you see the difference the table was scrolling to the top of view which can be visible & it not getting hidden behind the keyboard.

- (void)dealloc {

[mArray release];

[mDetailslist release];

[super dealloc];
}

@end

Did you enjoyed it.Please post comments on this post. :)

Download the code Here.