私のアプリでは、私はかなり大きなフォームに記入する必要があります。フォーム自体は、テーブルビューとスタティックセルモードで作成されます。各セルにはラベルとテキストフィールドが含まれています。キーボードの上にツールバーを追加して、テキストフィールド間を移動できるようにしたかったのです。私はそれをしましたが、それは非常に奇妙な行動です(少なくとも私は考える)。iOS 5:TextFieldsの間でジャンプするときの不思議な動作
次のテキストフィールドにジャンプする際に問題はありませんが、前のテキストフィールドにジャンプすることは表示されている場合にのみ可能です。表示されていない場合、古いテキストフィールドは最初のレスポンダのままですが、テーブルビューをスクロールして目的のテキストフィールドが表示されると、最初のレスポンダになります(私はクリックしません)。まあ、これはもちろん、私が望む行動ではありません。
私の質問です:この種の動作は正常ですか?何とかそれを回避できますか?
この種の動作を確認したい場合は、問題を示すXcodeプロジェクトをアップロードしました。 zipプロジェクトはdownloadからダウンロードできます。コードの主要部分を以下に説明します。
スタティックセルでグループ化されたテーブルビューを設定しました。それぞれにラベルとtextfield
が入っています。私はすべてのテキストフィールド用のアウトレットを作成してアクセスしました。私のviewDidLoadメソッドでは、ツールバーとそのボタンを作成し、テキストフィールドを配列に格納し、テキストフィールドの代理人になるようにコントローラを設定します。
- (void)viewDidLoad
{
[super viewDidLoad];
// create the keyboard toolbar with navigation elements
self.keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];
UIBarButtonItem *prevButton = [[UIBarButtonItem alloc] initWithTitle:@"Previous" style:UIBarButtonItemStyleBordered target:self action:@selector(prevClicked:)];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextClicked:)];
[self.keyboardToolbar setItems:[NSArray arrayWithObjects:prevButton, nextButton, nil]];
// create the field chain
self.fields = [NSArray arrayWithObjects:self.aField, self.bField, self.cField, self.dField, self.eField, self.fField, nil];
// for scrolling and keeping track of currently active field
NSInteger max = [self.fields count];
for(NSInteger i = 0; i < max; i++) {
UITextField *curr = (UITextField *)[self.fields objectAtIndex:i];
curr.delegate = self;
}
}
テキストフィールドデリゲートメソッドは、アクティブテキストフィールドの参照を格納し、改行が挿入されないようにします。
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
textField.inputAccessoryView = self.keyboardToolbar;
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// set the current active textfield
self.currentField = textField;
// scroll this textfield to top
UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
[self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
self.currentField = nil;
return NO;
}
最後に、ツールバーボタンのセレクタと次のテキストフィールドを取得するロジックがあります。
- (void)moveResponderByStep:(NSInteger)step
{
// only move if a textfield is the current responder
if(![self.currentField isEditing]) {
return;
}
// where we are and where to move
NSInteger max = [self.fields count];
NSInteger moveToNumber;
for(NSInteger i = 0; i < max; i++) {
if(self.currentField == [self.fields objectAtIndex:i]) {
moveToNumber = i + step;
}
}
// stay in bounds
if(moveToNumber >= max || moveToNumber < 0) {
[self.currentField resignFirstResponder];
return;
}
// move on
UITextField *next = [self.fields objectAtIndex:moveToNumber];
[next becomeFirstResponder];
}
- (void)prevClicked:(id)sender
{
[self moveResponderByStep:-1];
}
- (void)nextClicked:(id)sender
{
[self moveResponderByStep:1];
}
ありがとうございます!
最初のレスポンダを変更する前に、前のセルが表示されるようにテーブルビューをスクロールしようとしましたか? – dasdom
@dasdomとrobに感謝します。私は、私が試したことを言及すべきだった。問題は、cellが見えない場合、indexPathForCellはnullを返します。私のアプリケーションでは、すべての行にテキストフィールドが含まれているわけではないので、私は自分の位置を他の場所で把握しなければなりません。それはもちろん、私の意見では理想的な解決策ではありません。 – patman