Как установить порядок вкладок в iOS? - PullRequest
45 голосов
/ 15 марта 2011

Есть ли способ (либо в IB, либо в коде) установить порядок табуляции между текстовыми полями в представлении?

Обратите внимание, что я не говорю о следующем поле формы после нажатия кнопки возврата (или «Далее») - на многих клавиатурах Bluetooth есть клавиша табуляции, которая, кажется, циклически перебирает поля в совершенно другом порядке. В моем конкретном случае этот порядок не соответствует положению полей в представлении или даже порядку, в котором поля были добавлены. Изменение файла xib вручную для изменения NSNextKeyView, похоже, тоже не имеет значения.

Кто-нибудь знает, как изменить этот порядок?

Ответы [ 8 ]

7 голосов
/ 16 июня 2015

@ ответ Звездочки был только несколько полезным.То, что что-то работает из коробки, не означает, что вы должны перестать думать о лучшем способе - или даже правильном способе - что-то делать.Как он заметил, поведение недокументировано, но большую часть времени соответствует нашим потребностям.

Хотя этого мне было недостаточно.Представьте, что язык RTL и вкладки будут по-прежнему вкладываться слева направо, не говоря уже о том, что поведение полностью отличается от симулятора к устройству (устройство не фокусирует первый ввод на вкладке).Однако самое важное то, что недокументированная реализация Apple, похоже, рассматривает только те представления, которые в настоящее время установлены в иерархии представлений.

Подумайте о форме в виде (без каламбура) табличного представления.Каждая ячейка содержит один элемент управления, поэтому не все элементы формы могут быть видны одновременно.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];
}

Может применяться дополнительная логика для прокрутки закадровых ответчиков, видимых заранее.

Другое преимущество этого подхода заключается в том, что вам не нужнодля создания подклассов всех видов элементов управления, которые вы можете отображать (например, UITextField s), но вместо этого можете управлять логикой на уровне контроллера, где, скажем честно, является правильным местом для этого.

4 голосов
/ 10 августа 2011

Я заинтересован в решении той же проблемы, хотя пока мне нужен порядок по умолчанию, который выглядит слева направо, а затем сверху вниз.

Я проверил гипотезу о том, что курсор перемещается в порядке глубины по дереву подпредставлений и суперпредставлений, но это не верно. Изменение порядка подпредставлений без изменения их местоположения не изменило порядок полей, пройденных при нажатии tab .

Одна, возможно, полезная особенность заключается в том, что метод textFieldShouldBeginEditing делегата текстового поля вызывается для каждого текстового поля в окне приложения. Если это возвращает NO, тогда текстовое поле не будет выбрано, поэтому, если вы можете определить желаемый порядок и сделать только правильный, верните YES, что может решить вашу проблему.

3 голосов
/ 13 ноября 2012

Вот как вы устанавливаете порядок вкладок на iOS:

http://weaklyreferenced.wordpress.com/2012/11/13/responding-to-the-tab-and-shift-tab-keys-on-ios-5-ios-6-with-an-external-keyboard/

3 голосов
/ 09 ноября 2012

Поведение клавиши Tab в ios будет следующим: - когда вы нажимаете клавишу tab на внешней клавиатуре - элемент управления пересекает все текстовые поля на этом экране, вызывая только метод shouldBeginEditing, где его возвращаемое значение также определяется Apple, что не может бытьпереопределения.После сканирования всех полей вычисляется ближайшее текстовое поле с позицией x относительно смещения представления от текущего текстового поля, а затем с ближайшим позиционированным полем Y.

Также ничего нельзя сделать, пока элемент управления не перейдет в метод textFieldDidBeginEditing.

Причиной ограничения Apple может быть то, что разработчики должны следовать указаниям пользовательского интерфейса, где следующим респондентом поля должно быть его поле с самым близким расположением, а не любое другое поле.

2 голосов
/ 11 августа 2016

Зарегистрируйте UIKeyCommand, чтобы обнаружить нажатие клавиши табуляции. Я сделал это в моем текущем контроллере представления.

    self.addKeyCommand(UIKeyCommand(input: "\t", modifierFlags: [], action: #selector(tabKeyPressed)))

Внутри ключевого обработчика tabKeyPressed найдите ваше текущее активное поле и установите следующего респондента. orderTextFields - это массив UITextField в порядке вкладок, который я хочу.

func tabKeyPressed(){
    let activeField = getActiveField()
    if(activeField == nil){
        return
    }
    let nextResponder = getNextTextField(activeField!)
    nextResponder?.becomeFirstResponder()
}

func getActiveField() -> UITextField? {
    for textField in orderedTextFields {
        if(textField.isFirstResponder()){
            return textField
        }
    }
    return nil
}

func getNextTextField(current: UITextField) -> UITextField? {
    let index = orderedTextField.indexOf(current)
    if(orderedTextField.count-1 <= index!){
        return nil
    }
    return orderedTextField[index! + 1]
}
0 голосов
/ 03 октября 2012

Я решил это, создав подкласс UITextField как NextableTextField.Этот подкласс имеет свойство класса UITextField с подключением IBOutlet.

Создание интерфейса в IB.Установите класс вашего текстового поля в NextableTextField.Используйте Инспектор соединений, чтобы перетащить соединение в «следующее» поле, в которое вы хотите вставить вкладку.

В своем классе делегата текстового поля добавьте этот метод делегата ...

- (BOOL)textFieldShouldReturn:(UITextField *) textField
{
    BOOL didResign = [textField resignFirstResponder];
    if (!didResign) return NO;

    if ([textField isKindOfClass:[NextableTextField class]])
        dispatch_async(dispatch_get_current_queue(), ^{ [[(NextableTextField *)textField nextField] becomeFirstResponder]; });

    return YES;
}

BTW- Я не придумал это;просто не забудь увидеть чужую идею.

0 голосов
/ 05 августа 2011

Единственный способ уникального обнаружения нажатия клавиши Tab на физической клавиатуре - это реализация метода insertText: метода UIKeyInput для пользовательского объекта canBecomeFirstResponder.

- (void)insertText:(NSString *)text {
    NSLog(@"text is equal to tab character: %i", [text isEqualToString:@"\t"]);
}

Я, к сожалению, не работал, когда создавал подклассы UITextField, поскольку UITextField не позволяет вызывать метод протокола insertText :.

Могу помочь тебе в пути, хотя ..

0 голосов
/ 20 апреля 2011

Вы можете сделать это, установив тег для каждого текстового поля и обработав его в методе textfieldShouldReturn.

См. Об этом в блоге: http://iphoneincubator.com/blog/windows-views/how-to-create-a-data-entry-screen

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...