3

各セルに UITextField を持つ UITableViewController があります。ユーザーがフィールドで Return キーを押すと、次のフィールドが自動的にファーストレスポンダーに設定され、テーブルがスクロールしてそのフィールドが表示されます。

- (BOOL) textFieldShouldReturn:(UITextField *)textField 
{  
    UITextField *nextTextField=nil;
    NSInteger row;
    NSInteger section;

    if(textField == self.txtFieldA) 
    {
        nextTextField = self.txtFieldB;
        row=1; section=0;
    }
    else if(textField == self.txtFieldB) 
    {
        nextTextField = self.txtFieldC;
        row=2; section=0;
    }
    else 
    {
        [textField resignFirstResponder];
    }

    if(nextTextField) 
    {        
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
        [nextTextField becomeFirstResponder];

        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];      
    }
}

この問題は、テキスト フィールド (txtFieldA など) を選択し、テーブルを下にスクロールして txtFieldB が表示されないようにしてから、Enter キーを押すと発生します。iOS5 では期待どおりに動作します (txtFieldB が新しいファーストレスポンダーになります)。ただし、iOS6ではそうではありません。テーブル内の正しい場所にスクロールしますが、txtFieldB は最初のレスポンダーになりません (そして、ナビゲーション コントローラーで [戻る] を押しても、キーボードが表示されたままになります)。

「戻る」を押すと、txtFieldB の didBeginEditing が起動されません。1秒ほど遅らせると[nextTextField becomeFirstResponder](スクロールアニメーションが終了してnextTextFieldが表示されるまで)、期待どおりに機能しますが、それを行うのはハックでスムーズではないため、そのようなものを実装するよりも何が問題なのかを理解したいと思います。

4

3 に答える 3

2

この問題の解決策として、UITableViewCell をサブクラス化してテキスト フィールド セルを作成しました。そのテキスト フィールド セルで、-setSelected:animated:.

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    if (selected) {
        [self.textField becomeFirstResponder];
    }
}

ビュー コントローラーに戻り、次のフィールドに進みたい場合は、そのフィールドが含まれている行を選択するだけです。

- (IBAction)advanceToNextTextField
{
    NSIndexPath *indexPath = [self nextIndexPathFromIndexPath:self.indexPathOfActiveField];

    [self.tableView selectRowAtIndexPath:indexPath
                                animated:YES scrollPosition:UITableViewScrollPositionNone];
    [self.tableView scrollToRowAtIndexPath:indexPath
                          atScrollPosition:UITableViewScrollPositionNone animated:YES];
}

これにより、リターン キーの処理が容易になります。

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    switch (textField.returnKeyType) {
        case UIReturnKeyNext: [self advanceToNextTextField]; break;
        case UIReturnKeyDone: [self resignFirstResponder]; break;
        default:              break;
    }

    return YES;
}

それが役立つことを願っています。

于 2012-10-05T12:39:43.233 に答える
0

また、iOS 6 より前で問題なく動作していた既存のプロジェクトもあります。私のユニバーサル アプリはUITableView、キーボード ツールバーに「次へ」ボタンと「前へ」ボタンを含むフォームを作成するために使用します (Safari に似ています)。UITableViewCellテーブルには、テキスト フィールドを含むサブクラスのインスタンスが表示されます。次/前の機能もラップするため、最後のフィールドの「次へ」はフォーカスをフォームの上部に戻します。

残念ながら、Jeffrey Thomas のソリューションは私にとってはうまくいきません。セルが画面外にある場合、advanceToNextField メソッドの select-and-scroll メソッドはセル自体に対して正常に機能します。メソッドではsetSelected、テキスト フィールドのビュー階層は正しいです: UITextField-> UITableViewCellContentView->UITableViewCellサブクラス -> UITableView.

ただし、このbecomeFirstResponder呼び出しは、フィールドの編集モード、 firetextFieldDidBeginEditingなどのアクティブ化にまだ失敗しています。キーボードは引き続き表示されますが、現在表示されているセルには影響しません。

今のところ、この問題を回避できる唯一の方法は、最初にアニメーションなしでスクロールすることです:

[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];

op での Ned の遅延テクニックと同様に、これにより、アプリが応答を求めたときにテキスト フィールドが表示されるようになります。それ以外の場合はbecomeFirstResponder、アニメーション中およびテキスト フィールドが (完全に) 表示される前に発火しているようです。どうやら iOS 6 のいくつかの変更点は、ファーストレスポンダーのメッセージと可視性に関してより厳格になっているようです!

悲しいことに、フィールドからフィールドへと移動する際に、滑らかなアニメーションが失われます。これが単なる iOS 6.0 のバグではないと仮定するとUITableView、将来的にはフォームとして使用しないようにする予定です。

于 2012-11-21T23:16:17.710 に答える
0

同僚の Charles の助けを借りて、この問題の解決策を見つけました (ありがとう!)。また、Jeffrey Thomas のソリューション (およびそのバリエーション) を試してみましたが、うまくいきませんでした。Ogel も説明しているように、テーブル セルが画面外にある場合、テキスト フィールドはファーストレスポンダーになりません。UITableViewDelegateテーブルビューのアニメーション化が完了したときに警告を発し、setSelected:それまでテキスト フィールドのメソッドの呼び出しを遅らせるメソッドを探しましたが、うまくいきませんでした。それから彼は私を指さした

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView

これは、テーブル ビュー メソッドに応答してスクロールが完了すると、テーブル ビュー (UITableViewDelegateに準拠)によっても起動されます。UIScrollViewDelegate

- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated

したがって、キーは、次/前の方法 (Jeffrey Thomas の方法のように) で選択する予定の行のインデックス パスを計算することですが- (IBAction)advanceToNextTextField、それを選択する代わりに、スクロールして ivar を設定するだけです。

[_table scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
_selectIndexPathOnAnimationEnd = nextIndexPath;

次に、スクロール ビュー デリゲート メソッドで、テーブル ビューがスクロールを終了した後、そのインデックス パスで行を選択します。

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if(_selectIndexPathOnAnimationEnd != nil) {
        [_table selectRowAtIndexPath:_selectIndexPathOnAnimationEnd animated:NO scrollPosition:UITableViewScrollPositionMiddle];
        _selectIndexPathOnAnimationEnd = nil;
    }
}

この時点で、テキスト フィールドはファーストレスポンダになります。

于 2013-06-21T18:08:18.173 に答える