Как перемещаться по текстовым полям (кнопки «Далее» / «Готово») - PullRequest
475 голосов
/ 28 августа 2009

Как я могу перемещаться по всем моим текстовым полям с помощью кнопки «Далее» на клавиатуре iPhone?

Последнее текстовое поле должно закрывать клавиатуру.

Я настроил IB кнопки (Далее / Готово), но теперь я застрял.

Я реализовал действие textFieldShouldReturn, но теперь кнопки Next и Done закрывают клавиатуру.

Ответы [ 34 ]

9 голосов
/ 29 августа 2009

После выхода из одного текстового поля вы вызываете [otherTextField intoFirstResponder], и следующее поле получает фокус.

Это на самом деле может быть сложной задачей, поскольку часто вам также нужно прокрутить экран или иным образом отрегулировать положение текстового поля, чтобы его было легко увидеть при редактировании. Просто убедитесь, что вы много тестируете, входя и выходя из текстовых полей по-разному, а также уходя рано (всегда дайте пользователю возможность отклонить клавиатуру вместо перехода к следующему полю, обычно с помощью кнопки «Готово» в навигационная панель)

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

Меня удивляет, как много ответов здесь не в состоянии понять одну простую концепцию: навигация по элементам управления в вашем приложении - это не то, что сами представления должны делать. контроллер должен решить, какой элемент управления сделать следующим первым респондентом.

Также большинство ответов относится только к навигации вперед, но пользователи также могут захотеть вернуться назад.

Итак, вот что я придумала. Ваша форма должна управляться контроллером представления, а контроллеры представления являются частью цепочки респондента. Так что вы совершенно свободны для реализации следующих методов:

#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), но вместо этого вы можете управлять логикой на уровне контроллера, где, честно говоря, правильное место для этого.

7 голосов
/ 23 марта 2012

Очень простой способ отменить клавиатуру при нажатии кнопки «Готово»:

Создать новый IBAction в шапке

- (IBAction)textFieldDoneEditing:(id)sender;

В файле реализации (файл .m) добавьте следующий метод:

- (IBAction)textFieldDoneEditing:(id)sender 
{ 
  [sender resignFirstResponder];
}

Затем, когда вы придете, чтобы связать IBAction с текстовым полем - ссылка на событие «Закончено ли при выходе».

6 голосов
/ 26 ноября 2013

Сначала установите клавишу возврата клавиатуры в xib, в противном случае вы можете написать код в viewdidload:

passWord.returnKeyType = UIReturnKeyNext;

-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if(textField == eMail) {
        [textField resignFirstResponder];
        [userName becomeFirstResponder];
    }
    if (textField==userName) {
        [textField resignFirstResponder];
        [passWord becomeFirstResponder];
    }
    if (textField==passWord) {
        [textField resignFirstResponder];
        [country becomeFirstResponder];
    }
    if (textField==country) {
        [textField resignFirstResponder];
    }
    return YES;
}
4 голосов
/ 11 марта 2011

Привет всем, пожалуйста, смотрите этот

- (void)nextPrevious:(id)sender
{

  UIView *responder = [self.view findFirstResponder];   

  if (nil == responder || ![responder isKindOfClass:[GroupTextField class]]) {
    return;
  }

  switch([(UISegmentedControl *)sender selectedSegmentIndex]) {
    case 0:
      // previous
      if (nil != ((GroupTextField *)responder).previousControl) {
        [((GroupTextField *)responder).previousControl becomeFirstResponder];
        DebugLog(@"currentControl: %i previousControl: %i",((GroupTextField *)responder).tag,((GroupTextField *)responder).previousControl.tag);
      }
      break;
    case 1:
      // next
      if (nil != ((GroupTextField *)responder).nextControl) {
        [((GroupTextField *)responder).nextControl becomeFirstResponder];
        DebugLog(@"currentControl: %i nextControl: %i",((GroupTextField *)responder).tag,((GroupTextField *)responder).nextControl.tag);
      }     
      break;    
  }
}
4 голосов
/ 08 февраля 2013

Я попытался решить эту проблему, используя более сложный подход, основанный на назначении каждой ячейке (или UITextField) в UITableView уникального значения тега, которое может быть впоследствии получено: активировать-следующего UITextField-в-UITableView-КСН

Надеюсь, это поможет!

4 голосов
/ 24 июня 2012

Я добавил к ответу PeyloW на тот случай, если вы хотите реализовать функции предыдущей / следующей кнопки:

- (IBAction)moveThroughTextFields:(UIBarButtonItem *)sender 
{
    NSInteger nextTag;
    UITextView *currentTextField = [self.view findFirstResponderAndReturn];

    if (currentTextField != nil) {
        // I assigned tags to the buttons.  0 represent prev & 1 represents next
        if (sender.tag == 0) {
            nextTag = currentTextField.tag - 1;

        } else if (sender.tag == 1) {
            nextTag = currentTextField.tag + 1;
        }
    }
    // Try to find next responder
    UIResponder* nextResponder = [self.view viewWithTag:nextTag];
    if (nextResponder) {
        // Found next responder, so set it.
        // I added the resign here in case there's different keyboards in place.
        [currentTextField resignFirstResponder];
        [nextResponder becomeFirstResponder];
    } else {
        // Not found, so remove keyboard.
        [currentTextField resignFirstResponder];

    }
}

Где вы подкласс UIView, как это:

@implementation UIView (FindAndReturnFirstResponder)
- (UITextView *)findFirstResponderAndReturn
{
    for (UITextView *subView in self.subviews) {
        if (subView.isFirstResponder){
            return subView;
        }
    }
    return nil;
}
@end
4 голосов
/ 25 апреля 2017

Решение в Swift 3.1, после подключения ваших текстовых полей IBOutlets установите делегата ваших текстовых полей в viewDidLoad, а затем перейдите к действию в textFieldShouldReturn

class YourViewController: UIViewController,UITextFieldDelegate {

        @IBOutlet weak var passwordTextField: UITextField!
        @IBOutlet weak var phoneTextField: UITextField!

        override func viewDidLoad() {
            super.viewDidLoad()
            self.passwordTextField.delegate = self
            self.phoneTextField.delegate = self
            // Set your return type
            self.phoneTextField.returnKeyType = .next
            self.passwordTextField.returnKeyType = .done
        }

        func textFieldShouldReturn(_ textField: UITextField) -> Bool{
            if textField == self.phoneTextField {
                self.passwordTextField.becomeFirstResponder()
            }else if textField == self.passwordTextField{
                // Call login api
                self.login()
            }
            return true
        }

    }
4 голосов
/ 21 августа 2015

Я только что создал новый Pod при работе с этим материалом GNTextFieldsCollectionManager . Он автоматически обрабатывает следующую / последнюю проблему textField и очень прост в использовании:

[[GNTextFieldsCollectionManager alloc] initWithView:self.view];

Захватывает все текстовые поля, отсортированные по иерархии представления (или по тегам), или вы можете указать свой собственный массив textFields.

3 голосов
/ 04 ноября 2014

У меня было около 10+ UITextField в моей раскадровке, и я включил следующую функциональность, создав массив UITextField и сделав следующий UITextField firstResponder.Вот файл реализации:

#import "RegistrationTableViewController.h"

@interface RegistrationTableViewController ()
@property (weak, nonatomic) IBOutlet UITextField *fullNameTextField;
@property (weak, nonatomic) IBOutlet UITextField *addressTextField;
@property (weak, nonatomic) IBOutlet UITextField *address2TextField;
@property (weak, nonatomic) IBOutlet UITextField *cityTextField;
@property (weak, nonatomic) IBOutlet UITextField *zipCodeTextField;
@property (weak, nonatomic) IBOutlet UITextField *urlTextField;
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *emailTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;
@property (weak, nonatomic) IBOutlet UITextField *confirmPWTextField;

@end
NSArray *uiTextFieldArray;
@implementation RegistrationTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"view did load");
    uiTextFieldArray = @[self.fullNameTextField,self.addressTextField,self.address2TextField,self.cityTextField,self.zipCodeTextField,self.urlTextField,self.usernameTextField,self.emailTextField,self.passwordTextField,self.confirmPWTextField];
    for(UITextField *myField in uiTextFieldArray){
        myField.delegate = self;
    }


}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
    long index = [uiTextFieldArray indexOfObject:textField];
    NSLog(@"%ld",index);
    if(index < (uiTextFieldArray.count - 1)){
        [uiTextFieldArray[++index] becomeFirstResponder];
    }else{
        [uiTextFieldArray[index] resignFirstResponder];
    }
    return YES;
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

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