iOSでタブ順序を設定するにはどうすればいいですか? 質問する

iOSでタブ順序を設定するにはどうすればいいですか? 質問する

ビュー内のテキスト フィールド間のタブ順序を設定する方法 (IB またはコードのいずれか) はありますか?

ここで注意していただきたいのは、リターン (または「次へ」) ボタンが押された後の次のフォーム フィールドについて話しているのではないということです。多くの Bluetooth キーボードにはタブ キーがあり、フィールドをまったく異なる順序で循環するようです。私の場合、この順序はビュー内のフィールドの位置や、フィールドが追加された順序と一致しません。xib ファイルを手動で変更して NSNextKeyView を変更しても、違いはないようです。

この順序を変更する方法を知っている人はいますか?

ベストアンサー1

@sprocketの回答は、少しだけ役に立った。何かがすぐに使えるからといって、より良い方法を考えるのをやめるべきではない。正しい方法-- 何かをすること。彼が気づいたように、その動作は文書化されていないが、ほとんどの場合私たちのニーズに適合します。

しかし、これは私にとって十分ではありませんでした。RTL 言語を考えてみると、タブは依然として左から右に移動します。言うまでもなく、動作はシミュレータごとにまったく異なります (デバイスはタブで最初の入力にフォーカスしません)。しかし最も重要なのは、Apple の文書化されていない実装では、ビュー階層に現在インストールされているビューのみが考慮されるように見えることです。

テーブル ビュー形式のフォームを考えてみましょう (しゃれではありません)。各セルには 1 つのコントロールが保持されるため、すべてのフォーム要素が同時に表示されるとは限りません。Apple は、一番下の (画面上の!) コントロールに到達すると、さらに下にスクロールするのではなく、上に戻るだけです。この動作は、私たちが望んでいるものではありません。

そこで私が思いついたのがこれです。フォームはビュー コントローラによって管理される必要があり、ビュー コントローラはレスポンダ チェーンの一部です。したがって、次のメソッドを自由に実装できます。

#pragma mark - Key Commands

- (NSArray *)keyCommands
{
    static NSArray *commands;

    static dispatch_once_t once;
    dispatch_once(&once, ^{
        UIKeyCommand *const forward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(tabForward:)];
        UIKeyCommand *const backward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(tabBackward:)];

        commands = @[forward, backward];
    });

    return commands;
}

- (void)tabForward:(UIKeyCommand *)command
{
    NSArray *const controls = self.controls;
    UIResponder *firstResponder = nil;

    for (UIResponder *const responder in controls) {
        if (firstResponder != nil && responder.canBecomeFirstResponder) {
            [responder becomeFirstResponder]; return;
        }
        else if (responder.isFirstResponder) {
            firstResponder = responder;
        }
    }

    [controls.firstObject becomeFirstResponder];
}

- (void)tabBackward:(UIKeyCommand *)command
{
    NSArray *const controls = self.controls;
    UIResponder *firstResponder = nil;

    for (UIResponder *const responder in controls.reverseObjectEnumerator) {
        if (firstResponder != nil && responder.canBecomeFirstResponder) {
            [responder becomeFirstResponder]; return;
        }
        else if (responder.isFirstResponder) {
            firstResponder = responder;
        }
    }

    [controls.lastObject becomeFirstResponder];
}

事前に表示されているオフスクリーンのレスポンダをスクロールするための追加ロジックが適用される場合があります。

このアプローチのもう1つの利点は、表示したいすべての種類のコントロール(UITextFieldsなど)をサブクラス化する必要がなく、代わりにコントローラーレベルでロジックを管理できることです。正直に言うと、適切な場所そうするために。

おすすめ記事