带有TextFields的iPhone TableView - 接下来,上一个按钮问题

时间:2022-08-23 23:01:24

I have a table view which has a good number of cells in it used to create a form. I have created a custom TableViewCell. This cell contains a label and a text field, so for example, each row will look something like this

我有一个表视图,其中有大量的单元格用于创建表单。我创建了一个自定义的TableViewCell。此单元格包含标签和文本字段,因此,例如,每行将看起来像这样

带有TextFields的iPhone TableView  - 接下来,上一个按钮问题

I also have a custom table cell which contains a label and a text view, looks the same as image above, just cell is larger to allow room for the textview.

我还有一个自定义表格单元格,其中包含标签和文本视图,看起来与上面的图像相同,只是单元格更大,以便为textview提供空间。

Now each of these text fields and text views has a tool bar added, so when text field becomes first responder, a tool bar is shown with the buttons, done, previous and next buttons.

现在,每个文本字段和文本视图都添加了一个工具栏,因此当文本字段成为第一个响应者时,会显示一个工具栏,其中包含按钮,完成,上一个和下一个按钮。

  UIBarButtonItem *doneButton = [[UIBarButtonItem alloc]initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneWithTextField:)];

        UIBarButtonItem *nextButton = [[UIBarButtonItem alloc]initWithTitle:@"Next" style:UIBarButtonItemStyleDone target:self action:@selector(nextTableTextField:)];

        UIBarButtonItem *previousButton = [[UIBarButtonItem alloc]initWithTitle:@"Previous" style:UIBarButtonItemStyleDone target:self action:@selector(previousTableTextField:)];


        UIToolbar *numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
        numberToolbar.barStyle = UIBarStyleBlackTranslucent;
        numberToolbar.items = [NSArray arrayWithObjects:
                               previousButton,
                               nextButton,
                               [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil],
                               doneButton,
                               nil];

        [numberToolbar sizeToFit];

        field.inputAccessoryView = numberToolbar;

The issue I am having is, say I have 10 table rows like this, the screen can only show about 5 full rows and a bit of the 6th row. I should add I also have added the code to the text field delegates so that when a text field becomes first responder, screen scrolls to allow the text field to be fully shown. See my older post here for code.

我遇到的问题是,假设我有10个像这样的表行,屏幕只能显示大约5个完整行和第6行的一些。我应该添加我还将代码添加到文本字段委托中,以便当文本字段成为第一响应者时,屏幕滚动以允许完全显示文本字段。在这里查看我的旧帖子以获取代码。

So when screen loads I press the first cell, and click next, works fine, moves onto the 2nd text field in the next cell. Then I hit the next button again, and it goes to the 3rd cell, then 4th, then 5th. Now at this point the problem occurs. When I am on the 5th cell, and I click next, the 6th text field becomes the first responder but the screen does not scroll for some reason. Now the bigger problem is, when I click next again, it does not move onto the 7th text field, as the 7th cell is not in memory yet as it is not visible on the screen. So if I hit next, it won't do anything, text field 6 will remain as the first responder. So I need to scroll down a bit first, so cell 7 is visible before the next button will work and make the next text field the first responder.

因此,当屏幕加载时,我按下第一个单元格,然后单击下一步,工作正常,移动到下一个单元格中的第二个文本字段。然后我再次点击下一个按钮,然后进入第3个单元格,然后是第4个单元格,然后是第5个单元格。此时此问题就出现了。当我在第5个单元格上,然后单击下一步,第6个文本字段成为第一个响应者,但屏幕由于某种原因不滚动。现在更大的问题是,当我再次单击时,它不会移动到第7个文本字段,因为第7个单元格不在内存中,因为它在屏幕上不可见。因此,如果我点击下一步,它将不会执行任何操作,文本字段6将保留为第一响应者。所以我需要先向下滚动一下,这样在下一个按钮工作之前,单元格7是可见的,并使下一个文本字段成为第一个响应者。

It is the same issue when hitting the previous button, if hit previous button and the previous cell is not in screen, then it will not do anything until that cell is visible on the screen.

点击上一个按钮时是同样的问题,如果点击前一个按钮而前一个单元格不在屏幕上,那么在屏幕上显示该单元格之前它不会做任何事情。

This has been causing me quite a headache as can't seem to figure out a way around this. Has anyone else had similar problems like this? Is there a good work around to this problem?

这让我非常头疼,似乎无法找到解决方法。还有其他人有类似的问题吗?对这个问题有好的解决方法吗?

Thanks in advance

提前致谢

Edit:

编辑:

I should also add this makes saving data a problem because say I have a button that when clicked loops through each table cell and saves the data in each field, it will only loop through the table cells that are visible on screen and ignore the rest.

我还应该添加这使得保存数据成为一个问题,因为我说有一个按钮,当点击循环每个表格单元格并将数据保存在每个字段中时,它只会循环显示在屏幕上可见的表格单元格而忽略其余的。

2 个解决方案

#1


1  

It works for me, I'm using blocks which is fired when "done" button on keyboard pressed to move focus into next text fielded cell:

它适用于我,我正在使用块,当按下键盘上的“完成”按钮将焦点移动到下一个文本屏幕单元格时触发:

FRTextFieldTableViewCell *textFieldCell = [tableView_ dequeueReusableCellWithIdentifier:[FRTextFieldTableViewCell reuseIdentifier]];
        if(textFieldCell == nil) {
            textFieldCell = [[FRTextFieldTableViewCell alloc] initWithStyle:
                             UITableViewCellStyleDefault reuseIdentifier:[FRTextFieldTableViewCell reuseIdentifier]];
        }

        [textFieldCell.textField initialize];
        textFieldCell.textField.secureTextEntry = (indexPath.row == 3);

        __weak FRSignUpViewController *self_ = self;
        __weak FRTextFieldTableViewCell *textFieldCell_ = textFieldCell;
        if(indexPath.row == 1) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"name", @"");
            textFieldCell.object = self.regUser.name;
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setName:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setName:textFieldCell_.object];
                FRTextFieldTableViewCell *nextCell = (FRTextFieldTableViewCell *)[self_.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
                [nextCell.textField becomeFirstResponder];
            };
        }
        if(indexPath.row == 2) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"email", @"");
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setLoginString:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setLoginString:textFieldCell_.object];
                FRTextFieldTableViewCell *nextCell = (FRTextFieldTableViewCell *)[self_.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]];
                [nextCell.textField becomeFirstResponder];
            };
        }
        if(indexPath.row == 3) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"password", @"");
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setPasswordString:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setPasswordString:textFieldCell_.object];
                [self_ signUp];
            };
        }
        [textFieldCell reloadData];
        return textFieldCell;

BlocksTypedefs:

BlocksTypedefs:

/* type defenition for blocks, can be used by any app class */
typedef void (^CompletionBlock)(id, NSError *);
typedef void (^SimpleBlock)(void);
typedef void (^InfoBlock)(id);
typedef void (^ConfirmationBlock)(BOOL);

TableViewCell code:

TableViewCell代码:

.h file:

.h文件:

#import "FRTableViewCell.h"
#import "BlocksTypedefs.h"
#import "FRTextFieldWithPadding.h"

@interface FRTextFieldTableViewCell : FRTableViewCell <UITextFieldDelegate>

@property (nonatomic, copy) SimpleBlock didEndOnExitAction;
@property (nonatomic, copy) SimpleBlock didEndEditingAction;
@property (nonatomic, copy) InfoBlock didChangedValueAction;
@property (nonatomic, strong) IBOutlet FRTextFieldWithPadding *textField;

@end

.m:

.M:

    #import "FRTextFieldTableViewCell.h"

@implementation FRTextFieldTableViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    self.backgroundColor = [UIColor clearColor];
}

- (void)reloadData {
    self.textField.text = self.object;
}

- (IBAction)textFieldValueDidChanged:(UITextField *)sender {
    self.object = sender.text;
    if (self.didChangedValueAction) {
        self.didChangedValueAction(self.object);
    }
}

- (IBAction)textFieldDidEndOnExit:(UITextField *)sender {
    self.object = sender.text;
    if (self.didEndOnExitAction) {
        self.didEndOnExitAction();
    }
}

#pragma mark - UITextFieldDelegate

- (void)textFieldDidEndEditing:(UITextField *)textField {
    self.object = textField.text;
    if (self.didEndEditingAction) {
        self.didEndEditingAction();
    }
}

@end

#2


0  

CGRect frame = CGRectMake(0.0, self.view.bounds.size.height, self.view.bounds.size.width, 44.0);
fieldAccessoryView = [[UIToolbar alloc] initWithFrame:frame];
fieldAccessoryView.barStyle = UIBarStyleBlackOpaque;
fieldAccessoryView.tag = 200;

[fieldAccessoryView setBarStyle:UIBarStyleBlack];

UIBarButtonItem *spaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone  target:self action:@selector(done:)];

UISegmentedControl* segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:NSLocalizedString(@"Previous", @""), NSLocalizedString(@"Next", @""), nil]];
[segmentedControl addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[segmentedControl setMomentary:YES];
UIBarButtonItem *segmentButton = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];

[fieldAccessoryView setItems:[NSArray arrayWithObjects:segmentButton, spaceButton, doneButton, nil] animated:NO];
[segmentButton release];
[spaceButton release];
[doneButton release];
[segmentedControl release];

#1


1  

It works for me, I'm using blocks which is fired when "done" button on keyboard pressed to move focus into next text fielded cell:

它适用于我,我正在使用块,当按下键盘上的“完成”按钮将焦点移动到下一个文本屏幕单元格时触发:

FRTextFieldTableViewCell *textFieldCell = [tableView_ dequeueReusableCellWithIdentifier:[FRTextFieldTableViewCell reuseIdentifier]];
        if(textFieldCell == nil) {
            textFieldCell = [[FRTextFieldTableViewCell alloc] initWithStyle:
                             UITableViewCellStyleDefault reuseIdentifier:[FRTextFieldTableViewCell reuseIdentifier]];
        }

        [textFieldCell.textField initialize];
        textFieldCell.textField.secureTextEntry = (indexPath.row == 3);

        __weak FRSignUpViewController *self_ = self;
        __weak FRTextFieldTableViewCell *textFieldCell_ = textFieldCell;
        if(indexPath.row == 1) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"name", @"");
            textFieldCell.object = self.regUser.name;
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setName:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setName:textFieldCell_.object];
                FRTextFieldTableViewCell *nextCell = (FRTextFieldTableViewCell *)[self_.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
                [nextCell.textField becomeFirstResponder];
            };
        }
        if(indexPath.row == 2) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"email", @"");
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setLoginString:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setLoginString:textFieldCell_.object];
                FRTextFieldTableViewCell *nextCell = (FRTextFieldTableViewCell *)[self_.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:0]];
                [nextCell.textField becomeFirstResponder];
            };
        }
        if(indexPath.row == 3) {
            textFieldCell.textField.placeholder = NSLocalizedString(@"password", @"");
            textFieldCell.didChangedValueAction = ^(NSString *object) {
                [self_ setPasswordString:object];
            };
            textFieldCell.didEndOnExitAction = ^{
                [self_ setPasswordString:textFieldCell_.object];
                [self_ signUp];
            };
        }
        [textFieldCell reloadData];
        return textFieldCell;

BlocksTypedefs:

BlocksTypedefs:

/* type defenition for blocks, can be used by any app class */
typedef void (^CompletionBlock)(id, NSError *);
typedef void (^SimpleBlock)(void);
typedef void (^InfoBlock)(id);
typedef void (^ConfirmationBlock)(BOOL);

TableViewCell code:

TableViewCell代码:

.h file:

.h文件:

#import "FRTableViewCell.h"
#import "BlocksTypedefs.h"
#import "FRTextFieldWithPadding.h"

@interface FRTextFieldTableViewCell : FRTableViewCell <UITextFieldDelegate>

@property (nonatomic, copy) SimpleBlock didEndOnExitAction;
@property (nonatomic, copy) SimpleBlock didEndEditingAction;
@property (nonatomic, copy) InfoBlock didChangedValueAction;
@property (nonatomic, strong) IBOutlet FRTextFieldWithPadding *textField;

@end

.m:

.M:

    #import "FRTextFieldTableViewCell.h"

@implementation FRTextFieldTableViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    self.backgroundColor = [UIColor clearColor];
}

- (void)reloadData {
    self.textField.text = self.object;
}

- (IBAction)textFieldValueDidChanged:(UITextField *)sender {
    self.object = sender.text;
    if (self.didChangedValueAction) {
        self.didChangedValueAction(self.object);
    }
}

- (IBAction)textFieldDidEndOnExit:(UITextField *)sender {
    self.object = sender.text;
    if (self.didEndOnExitAction) {
        self.didEndOnExitAction();
    }
}

#pragma mark - UITextFieldDelegate

- (void)textFieldDidEndEditing:(UITextField *)textField {
    self.object = textField.text;
    if (self.didEndEditingAction) {
        self.didEndEditingAction();
    }
}

@end

#2


0  

CGRect frame = CGRectMake(0.0, self.view.bounds.size.height, self.view.bounds.size.width, 44.0);
fieldAccessoryView = [[UIToolbar alloc] initWithFrame:frame];
fieldAccessoryView.barStyle = UIBarStyleBlackOpaque;
fieldAccessoryView.tag = 200;

[fieldAccessoryView setBarStyle:UIBarStyleBlack];

UIBarButtonItem *spaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone  target:self action:@selector(done:)];

UISegmentedControl* segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:NSLocalizedString(@"Previous", @""), NSLocalizedString(@"Next", @""), nil]];
[segmentedControl addTarget:self action:@selector(segmentAction:) forControlEvents:UIControlEventValueChanged];
segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[segmentedControl setMomentary:YES];
UIBarButtonItem *segmentButton = [[UIBarButtonItem alloc] initWithCustomView:segmentedControl];

[fieldAccessoryView setItems:[NSArray arrayWithObjects:segmentButton, spaceButton, doneButton, nil] animated:NO];
[segmentButton release];
[spaceButton release];
[doneButton release];
[segmentedControl release];