【问题标题】:iPhone TableView with TextFields - next, previous button issue带有 TextFields 的 iPhone TableView - 下一个,上一个按钮问题
【发布时间】:2013-02-25 09:29:55
【问题描述】:

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

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

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

  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;

我遇到的问题是,假设我有 10 个这样的表格行,屏幕只能显示大约 5 个完整的行和第 6 行的一部分。我应该添加我还向文本字段委托添加了代码,以便当文本字段成为第一响应者时,屏幕滚动以允许文本字段完全显示。有关代码,请参阅我的旧帖子 here

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

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

这让我很头疼,因为似乎无法解决这个问题。有没有其他人遇到过类似的问题?这个问题有什么好的解决办法吗?

提前致谢

编辑:

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

【问题讨论】:

    标签: objective-c xcode uitableview


    【解决方案1】:

    它对我有用,我使用的是在按下键盘上的“完成”按钮将焦点移动到下一个文本字段单元格时触发的块:

    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;
    

    块类型定义:

    /* 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 代码:

    .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:

        #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
    

    【讨论】:

    • 您是否尝试过使用 10 个单元格的代码,即使该单元格尚未加载到内存中,它是否仍会转到下一个文本字段?
    • 是的,因为它会通过调用行 [self_.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:(indexPath.row + 1) inSection:0]] 在 didEndOnExitHandler 中加载
    • 你能告诉我你是如何将块代码功能添加到你的表格单元格的,所以我可以看看你是如何实现它的,例如你能告诉我你用来设置 didEndOnExitAction 的代码吗.
    • 我试过你的代码,但我仍然遇到同样的问题。它适用于屏幕上的表格单元格,但是当尝试转到尚不可见的单元格时,它不会做任何事情,因为它没有加载到内存中
    • 好的!然后尝试:[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];在从 tableView 获取下一个单元格并且它的文本字段成为第一响应者之前执行此操作
    【解决方案2】:
    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];
    

    【讨论】:

    • 您阅读我的问题了吗?这没有回答我的问题,这只是设置下一个上一个和完成按钮的不同方式,我已经知道如何设置
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2016-11-10
    相关资源
    最近更新 更多