I have some UITextfields in a UItableView. the textfields have been subclassed in a UITableViewCell that I have created. I would lke to know how to progress down to the next cell in its respective row after the return key is pressed on the keyboard.
So if the user was to start on width, they would continue down the width colum, or if they wanted to enter height each time they hit enter they would continue down that column.
currently whats happening is if i use the width colum, it works fine but if i select a height UItextField after hitting enter it jumps over to the next width cell.
This is my code for detecting the return key.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
return YES;
}
and this is what my tableview of cells looks like.
For more information this is how I add the custom celltextfields to UItextfield.
NSString *widthString = [currentFinishingDictionary objectForKey:#"w"];
if ((NSNull *) widthString != [NSNull null]) {
cell.widthTexField.text = widthString;
cell.widthTexField.delegate = self;
cell.widthTexField.tag = indexPath.row;
} else {
cell.widthTexField.text = #" ";
cell.widthTexField.delegate = self;
cell.widthTexField.tag = indexPath.row;
}
NSString *heightString = [currentFinishingDictionary objectForKey:#"h"];
if ((NSNull *) heightString != [NSNull null]) {
cell.heightTextField.text = heightString;
cell.heightTextField.delegate = self;
cell.heightTextField.tag = indexPath.row;
} else {
cell.heightTextField.text = #" ";
cell.heightTextField.delegate = self;
cell.heightTextField.tag = indexPath.row;
}
I think the issue might be in the way the tags are assigned to the UITextFields.
Please check if the tag values are actually what you have assumed.
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[yourtextfield resignFirstResponder];
// save state, etc if necessary
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyCell * cell = (MyCell *)[tableView cellForRowAtIndexPath:indexPath];
self.selectedField = cell.tf; // cell.tf is a UITextField property defined on MyCell
[yourtextfield becomeFirstResponder];
}
Make sure that you have set tag to UITextField
You should try in this way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
// Get here you cell seleted Refrecne
id obj = [cell.contentView viewWithTag:textField.tag+1];
if([obj isKindOfClass:[UITextField class]]) {
UITextField *nextField = (UITextField*)obj
[nextField becomeFirstResponder];
}
return YES;
}
Or you can use ELCTextFieldCell
It contents UITextField and UILabel in one cell. You can customizr as per your need.
you can use
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
UITableViewCell *cell = [self.myTableview cellForRowAtIndexPath:[NSIndexPath indexPathForRow: textField.tag+1 inSection:0]];
UITextField *tf = (UITextField*)[cell viewByTag:textField.tag+1]
[tf becomeFirstResponder];
return YES;
}
Did you try using collectionView instead of tableview, collection views design can be made similar to the image you added and you can add one textfield in one cell and then make first responder for width text field by doing this
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if ( [tableView.dataSource tableView:tableView numberOfRowsInSection:0] > tag + 2)
CustomCell *cell = [self.myTableview cellForRowAtIndexPath:[NSIndexPath indexPathForRow: textField.tag+2 inSection:0]];
[cell.textField becomeFirstResponder];
}
If you wanna still persist with this design then you can do this
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
int xPosition = (int)textField.frame.origin.x;
CustomCell *cell = [self.myTableview cellForRowAtIndexPath:[NSIndexPath indexPathForRow: textField.tag+1 inSection:0]];
if((int)cell.textField1.x == xPosition)
{
[cell.textField1.x becomeFirstResponder];
}
else
{
[cell.textField2.x becomeFirstResponder];
}
}
Code is not compiled. Only logic is written.Hope it helps :)
Change your assigning tag values as below that may help you.
NSString *widthString = [currentFinishingDictionary objectForKey:#"w"];
if ((NSNull *) widthString != [NSNull null]) {
cell.widthTexField.text = widthString;
cell.widthTexField.delegate = self;
cell.widthTexField.tag = indexPath.row;
} else {
cell.widthTexField.text = #" ";
cell.widthTexField.delegate = self;
cell.widthTexField.tag = indexPath.row;
}
NSString *heightString = [currentFinishingDictionary objectForKey:#"h"];
if ((NSNull *) heightString != [NSNull null]) {
cell.heightTextField.text = heightString;
cell.heightTextField.delegate = self;
cell.heightTextField.tag = indexPath.row + 2000;
} else {
cell.heightTextField.text = #" ";
cell.heightTextField.delegate = self;
cell.heightTextField.tag = indexPath.row + 2000;
}
Now your textfields tag looks like as below and may work as you desired.
0 2000
1 2001
2 2002
3 2003
4 2004
.. ........
Now your method work properly but need to think other idea as well because this will wrong when you have 2000 cells.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// i.e. textField.tag == 6 then next 6 + 1 == 7
// i.e. textField.tag == 20006 then next 2006 + 1 == 2007
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
return YES;
}
Related
In my ios app I have added on one button in UITableViewCell which is for check and un-check the TableViewCell products. For this I wrote below code but according to my code by default all are checked and when I scroll check boxes are un-checking
my code:
- (void)viewDidLoad {
[super viewDidLoad];
checkBoxesArray = [[NSMutableArray alloc]init];
for(int i = 0; i <15; i++){
[checkBoxesArray addObject:#""];
}
}
//TableList Delegate Methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return checkBoxesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"HistoryCell";
UITableViewCell *cell = (UITableViewCell *)[MaintableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
model1 = mainArray[indexPath.row];
cell.textLabel.text = model1.Name;
cell.detailTextLabel.text = model1.MasterId;
bool variable = checkBoxesArray[indexPath.row];
newBtn=[UIButton buttonWithType:UIButtonTypeCustom];
[newBtn setFrame:CGRectMake(250,5,30,30)];
[newBtn addTarget:self action:#selector(urSelector:) forControlEvents:UIControlEventTouchUpInside];
UIImage *btnImage;
if(variable == YES){
NSLog(#"1");
btnImage = [UIImage imageNamed:#"check.png"];
}else{
NSLog(#"2");
btnImage = [UIImage imageNamed:#"uncheck.png"];
}
[newBtn setImage:btnImage forState:UIControlStateNormal];
[cell addSubview:newBtn];
return cell;
}
-(void)urSelector :(UIButton*)sender{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:MaintableView];
NSIndexPath *indexPath1 = [MaintableView indexPathForRowAtPoint:buttonPosition];
NSInteger variable = indexPath1.row;
bool variablePosition = checkBoxesArray[variable];
if (variablePosition == YES){
variablePosition= NO;
[checkBoxesArray replaceObjectAtIndex:variable withObject:[NSString stringWithFormat:#"%d",variablePosition]];
}
else{
variablePosition = YES;
[checkBoxesArray replaceObjectAtIndex:variable withObject:[NSString stringWithFormat:#"%d",variablePosition]];
}
[MaintableView reloadData];
}
#end
1) Add one key to your model array. Like isSelected and set it's value to NO.
2) Now when you select any cell at that time set the value of that key to YES.
3) In cellForRow, access that key which we have added and check it's value. If it's YES then set Check Image else Uncheck image.
4) Don't maintain two array so remove your checkboxarray. It will create confusion for you.
First Please replace your line of code in cellForRowAtIndexPath
bool variable = checkBoxesArray[indexPath.row];
with
bool variable = [checkBoxesArray[indexPath.row] length] > 0;
Because in checkBoxesArray , there are NSString type objects. and you are storing them into a bool variable . It always returns a true value to your 'variable'. So first of all you need to have a proper condition for 'check' and 'uncheck' thing. I am assuming that you want all boxes unchecked for the first time. So I put blank string for uncheck button and some value string for check button.
Again you need to replace your code in urSelctor method
bool variablePosition = checkBoxesArray[variable];
if (variablePosition == YES){
variablePosition= NO;
[checkBoxesArray replaceObjectAtIndex:variable withObject:[NSString stringWithFormat:#"%d",variablePosition]];
}
with
bool variablePosition = [checkBoxesArray[variable] length] > 0;
if (variablePosition == YES){
variablePosition= NO;
[checkBoxesArray replaceObjectAtIndex:variable withObject:#""];
}
hope these things will help you.
Happy coding... :) :) :)
I have a UITableView that uses a custom UITableViewCell. My UITableVewCell has two textfields inside it, which I have added a tag to in my main ViewController that holds the UITableView which houses my custom UITableViewCell.
So this is the code inside my tableView:cellForRowAIndexPath:
static NSString *CellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomFCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *widthString = [currentFDictionary objectForKey:#"MM"];
if ((NSNull *) widthString != [NSNull null]) {
cell.widthTexField.text = widthString;
cell.widthTexField.tag = indexPath.row;
} else {
cell.widthTexField.text = #" ";
}
NSString *heightString = [currentFDictionary objectForKey:#"NM"];
if ((NSNull *) heightString != [NSNull null]) {
cell.heightTextField.text = heightString;
cell.heightTextField.tag = indexPath.row;
} else {
cell.heightTextField.text = #" ";
}
return cell;
I would like to know how to then use this .tag to scroll the UITableViewCell above the UIKeyboard that will now be shown in the view.
Anyhelp would be greatly apprecited.
A simple way i can think of is by using the -scrollToRowAtIndexPath:atScrollPosition:animated:
Set the delegate on the UITextField objects.
cell.widthTexField.delegate = self;
//...
cell.heightTextField.delegate = self;
Now, use -textFieldShouldBeginEditing: delegate method in this manner:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSIndexPath *currentSelectedIndexPath = [self.tableView indexPathForSelectedRow];
[self.tableView scrollToRowAtIndexPath:currentSelectedIndexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
//NOTE: this way we don't really need to work with the textField tag per se
//(unless you are using it elsewhere as well)
//Instead, we work with the entire cell and scroll it to the desired position
this may not be perfect since i haven't tested it here but it's the general idea
I am trying to dynamically resize some UITableViewCell's based on the height of UITextView's contained within them.
There's loads of solutions to this by keeping a pointer to the UITextView and getting it's content size in heightForRowAtIndexPath however when the whole table is created dynamically with an unknown number of rows and an unknown number of them rows contain UITextView's this just isn't possible.
It would be easy if I could call the cell in question during heightForRowAtIndexPath but that causes an infinite loop and crash as this method is called before any cell's are even created.
Any other solutions?
I am using a UITableViewCell subclass for my cell like this:
- (void)initalizeInputView {
// Initialization code
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.textView = [[UITextView alloc] initWithFrame:CGRectZero];
self.textView.autocorrectionType = UITextAutocorrectionTypeDefault;
self.textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.textView.textAlignment = NSTextAlignmentRight;
self.textView.textColor = [UIColor lightBlueColor];
self.textView.font = [UIFont fontWithName:#"HelveticaNeue-Light" size:17];
self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.textView.keyboardType = UIKeyboardTypeDefault;
[self addSubview:self.textView];
self.textView.delegate = self;
}
- (BOOL)resignFirstResponder {
if (_delegate && [_delegate respondsToSelector:#selector(tableViewCell:didEndEditingWithLongString:)]) {
[_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
}
return [super resignFirstResponder];
}
- (void)setKeyboardType:(UIKeyboardType)keyboardType
{
self.textView.keyboardType = keyboardType;
}
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self initalizeInputView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initalizeInputView];
}
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
if (selected) {
[self.textView becomeFirstResponder];
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
[self.textView becomeFirstResponder];
}
}
- (void)setStringValue:(NSString *)value {
self.textView.text = value;
}
- (NSString *)stringValue {
return self.textView.text;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
// For keyboard scroll
UITableView *tableView = (UITableView *)self.superview;
AppSetupViewController *parent = (AppSetupViewController *)_delegate;
parent.activeCellIndexPath = [tableView indexPathForCell:self];
}
- (void)textViewDidChange:(UITextView *)textView
{
if (textView.contentSize.height > contentRowHeight) {
contentRowHeight = textView.contentSize.height;
UITableView *tableView = (UITableView *)self.superview;
[tableView beginUpdates];
[tableView endUpdates];
[textView setFrame:CGRectMake(0, 0, 300.0, textView.contentSize.height)];
}
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
if (_delegate && [_delegate respondsToSelector:#selector(tableViewCell:didEndEditingWithLongString:)]) {
[_delegate tableViewCell:self didEndEditingWithLongString:self.stringValue];
}
UITableView *tableView = (UITableView *)self.superview;
[tableView deselectRowAtIndexPath:[tableView indexPathForCell:self] animated:YES];
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect editFrame = CGRectInset(self.contentView.frame, 10, 10);
if (self.textLabel.text && [self.textLabel.text length] != 0) {
CGSize textSize = [self.textLabel sizeThatFits:CGSizeZero];
editFrame.origin.x += textSize.width + 10;
editFrame.size.width -= textSize.width + 10;
self.textView.textAlignment = NSTextAlignmentRight;
} else {
self.textView.textAlignment = NSTextAlignmentLeft;
}
self.textView.frame = editFrame;
}
Which is created in cellForRowAtIndexPath like this:
else if ([paramType isEqualToString:#"longString"]) {
MyIdentifier = #"AppActionLongString";
LongStringInputTableViewCell *cell = (LongStringInputTableViewCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
cell.textLabel.text = [[[_selectedAction objectForKey:#"parameters"] objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.params = [[_selectedAction objectForKey:#"parameters"] objectAtIndex:indexPath.row];
cell.textView.text = [results objectAtIndex:indexPath.row];
return cell;
}
Simply passing back the height to a variable in my ViewController is no good because like I said, there could be several of these cells within the table.
Thanks
Use this method to dynamically resize your tableviewCell. First store the user input in NSMutable Array and after that reload table. Hope it will help you.
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *msg =[self.messages objectAtIndex:indexPath.row];
CGSize textSize = { 120, 10000.0 };
CGSize size = [msg sizeWithFont:[UIFont systemFontOfSize:15]
constrainedToSize:textSize
lineBreakMode:UILineBreakModeWordWrap];
return size.height+20;
}
I needed a dynamic table view cell height based on the amount of text to be displayed in that cell. I solved it in this way:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!isLoading)
{
if ([self.conditionsDataArray count]>0)
{
Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];
int height;
UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)]; //you can set your frame according to your need
textview.text = condition.comment;
textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[tableView addSubview:textview];
textview.hidden = YES;
height = textview.contentSize.height;
NSLog(#"TEXT VIEW HEIGHT %f", textview.contentSize.height);
[textview removeFromSuperview];
[textview release];
return height;
}
return 55; //Default height, if data is in loading state
}
Notice that the Text View has been added as Subview and then made hidden, so make sure you add it as SubView otherwise it's height will not be considered.
It would be easy if I could call the cell in question during heightForRowAtIndexPath but that causes an infinite loop and crash as this method is called before any cell's are even created. Any other solutions?
You can. I would guess you're attempting to call cellForRowAtIndexPath, which will cause an infinite loop. But you should rather be dequeuing the cell directly by calling dequeueReusableCellWithIdentifier.
See the table view delegate implementation of TLIndexPathTools. The heightForRowAtIndexPath method looks like this:
(EDIT Initially forgot to include the method prototypeForCellIdentifier that actually dequeues the cell.)
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id item = [self.dataModel itemAtIndexPath:indexPath];
NSString *cellId = [self cellIdentifierAtIndexPath:indexPath];
if (cellId) {
UITableViewCell *cell = [self prototypeForCellIdentifier:cellId];
if ([cell conformsToProtocol:#protocol(TLDynamicSizeView)]) {
id<TLDynamicSizeView> v = (id<TLDynamicSizeView>)cell;
id data;
if ([item isKindOfClass:[TLIndexPathItem class]]) {
TLIndexPathItem *i = (TLIndexPathItem *)item;
data = i.data;
} else {
data = item;
}
CGSize computedSize = [v sizeWithData:data];
return computedSize.height;
} else {
return cell.bounds.size.height;
}
}
return 44.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView prototypeForCellIdentifier:(NSString *)cellIdentifier
{
UITableViewCell *cell;
if (cellIdentifier) {
cell = [self.prototypeCells objectForKey:cellIdentifier];
if (!cell) {
if (!self.prototypeCells) {
self.prototypeCells = [[NSMutableDictionary alloc] init];
}
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//TODO this will fail if multiple tables are being used and they have
//overlapping identifiers. The key needs to be unique to the table
[self.prototypeCells setObject:cell forKey:cellIdentifier];
}
}
return cell;
}
This uses a protocol TLDynamicSizeView that any cell can implement to have it's height calculated automatically. Here is a working example project. The cell's implementation of the protocol looks like this:
#implementation DynamicHeightCell
- (void)awakeFromNib
{
[super awakeFromNib];
self.originalSize = self.bounds.size;
self.originalLabelSize = self.label.bounds.size;
}
- (void)configureWithText:(NSString *)text
{
self.label.text = text;
[self.label sizeToFit];
}
#pragma mark - TLDynamicSizeView
- (CGSize)sizeWithData:(id)data
{
[self configureWithText:data];
//the dynamic size is calculated by taking the original size and incrementing
//by the change in the label's size after configuring
CGSize labelSize = self.label.bounds.size;
CGSize size = self.originalSize;
size.width += labelSize.width - self.originalLabelSize.width;
size.height += labelSize.height - self.originalLabelSize.height;
return size;
}
#end
just comment
if (cell == nil)
Hope, this will help you.
I have ageTextField property in my TableViewController. I add it to the first section cell's subciew but I don't know why it is shown in another section (#3) when I scroll down..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
// Configure the cell...
switch (indexPath.section){
case 0:
{
[cell addSubview:self.ageTextField];
}
break;
case 1:
{
cell.textLabel.text = [screeningArray objectAtIndex:indexPath.row];
if (indexPath.row == 0) //no choice
cell.accessoryType = self.doneScreening ? UITableViewCellAccessoryNone:UITableViewCellAccessoryCheckmark;
else //yes choice
cell.accessoryType = self.doneScreening ? UITableViewCellAccessoryCheckmark:UITableViewCellAccessoryNone;
}
break;
case 2:
{
cell.textLabel.text = #"1 : ";
[cell addSubview:self.riskTextField];
}
break;
case 3:
{
cell.textLabel.text = [findingsArray objectAtIndex:indexPath.row];
cell.accessoryType = [[boolValuesArray objectAtIndex:indexPath.row] boolValue] ? UITableViewCellAccessoryCheckmark:UITableViewCellAccessoryNone;
}
break;
default:
break;
}
cell.textLabel.font = [UIFont systemFontOfSize:14];
return cell;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
if (textField == self.ageTextField)
return (newLength > 2) ? NO : YES;
else
return (newLength > 7) ? NO : YES;
}
Here is screenshot at the beginning..
http://dl.dropbox.com/u/30838210/Screen%20Shot%202012-08-07%20at%209.26.47%20PM.png
After scrolling down, notice how the placeholder of ageTextField was duplicated in Section3, cell3..
http://dl.dropbox.com/u/30838210/Screen%20Shot%202012-08-07%20at%209.27.28%20PM.png
When scrolling up again, the text of cell3 in section3 appears in the first cell..
dl.dropbox.com/u/30838210/Screen%20Shot%202012-08-07%20at%209.27.52%20PM.png
That's weird and I couldn't figure out what happened! please help..
The contents of a table view cell must be removed if they are reused (i.e, if cell != nil). Also, the subviews should be added to the table cell's contentView not to the cell itself, so the subviews adjust appropriately when entering/exiting editing mode.
[cell.contentView addSubview:self.ageTextField];
[cell.contentView addSubview:self.riskTextField];
The following code prepares the cell for reuse.
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
else
{
// Prepare cell for reuse
// Remove subviews from cell's contentView
for (UIView *view in cell.contentView.subviews)
{
// Remove only the appropriate views
if ([view isKindOfClass:[UITextField class]])
{
[view removeFromSuperview];
}
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = nil;
}
When the table gives you a reusable cell it doesn't care which section it was previously used in. Since you add a subview whether it's a new cell or one that previously had a subview added, it's quite possible to get more than one and of various kinds.
I have a custom grouped TableView with 5 sections and in total with 50 custom cells of type:
Label | XXX
where XXX can be UITextField, UITextView, UIButton, UILabel. Cells have mixed order in tableView.
To navigate through textFields & textViews i added Next/Prev buttons on my keyboard.
The problem is the when i select txtField and click Next or Prev button, the table scrolls to the needed cell position, but txtField doesn't get the cursor. In order to get the cell with textField/textView i use:
nextCell = [self tableView:_myTableView
cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
I need to search through all cells in tableView, not only through the visible ones.
As i tested, the problem is in this line of code, because if i call:
nextCell = [_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];
and the cell is visible, then the txtField gets cursor. However, if i need to jump from cell (section = 1, row = 6) to cell (section =0, row = 3) which is not visible, i get nil.
My full code of button function:
-(void) previousTextField:(id)sender
{
int curTagInd = _editingTextElement.tag;
NSIndexPath *curInd = [self getRowIndexOf:_editingTextElement];
int curSec = curInd.section;
int curRow = curInd.row;
id nextView = nil;
UITableViewCell *nextCell = nil;
do {
curRow--;
if (curRow >=0) {
nextCell = [self tableView:_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:curRow inSection:curSec]];//[_myTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:--curRow inSection:curInd.section]];
curTagInd--;
if ([nextCell isKindOfClass:[CustomCell class]] || [nextCell isKindOfClass:[CustomLongTextCell class]]) {
do {
nextView = [nextCell viewWithTag:curTagInd];
if ([nextView isEnabled]) {
nextCell = nil;
_editingIndexPath = [NSIndexPath indexPathForRow:curRow inSection:curSec];
break;
}else{
break;
}
} while (nextView != nil && ((![nextView isKindOfClass:[UITextField class]] && ![nextView isKindOfClass:[UITextView class]]) || ![nextView isEnabled]));
}
}
else if(curSec > 0){ //got to previous section
curSec--;
curRow = [self getNumberOfRowsInSection:curSec];
curTagInd = [self getNumberOfRowsInSection:curSec]+1;
}
else{
nextCell = nil;
}
} while (nextCell != nil);
if (nextView != nil) {
[self.myTableView scrollToRowAtIndexPath:_editingIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
Using this code i get inside method textFieldShouldBeginEditing:, but not in textFieldDidBeginEditing:
SOLUTION:
The problem was that the table began scrolling only after the function previousTextField: was finished, and thus, [textField becomeFirstResponder]; was called before the table was scrolled to the needed position. Due to the fact that needed cell is still not visible on the screen, delegate methods didn't call.
To avoid this, i added timer after table-scrolling line:
NSTimer *t = [NSTimer scheduledTimerWithTimeInterval: 0.2
target: self
selector:#selector(doneScrolling)
userInfo: nil repeats:NO];
and defined doneScrolling like:
-(void)doneScrolling
{
NSLog(#"done scrolling");
[self tableView:self.myTableView didSelectRowAtIndexPath:self.editingIndexPath];
}
where:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIView *nextView = [cell viewWithTag:indexPath.row+1];
if ([nextView isKindOfClass:[UITextView class]] || [nextView isKindOfClass:[UITextField class]]) {
if ([nextView isEnabled]) {
UITextField *textField = (UITextField *)nextView;
[textField becomeFirstResponder];
}
}
}