UITextField, автоматически переходит к следующему после 1 символа
Сценарий: у меня есть 4 UITextFields, которые принимают только 1 символ. Легко.
Проблема: после ввода символа 1 я хочу, чтобы следующий TextField стал активным автоматически, не нажимая дальше (т.е. я использую UIKeyboardTypeNumberPad, а не кнопку NEXT. (Я ЗНАЮ, что могу создать следующий, но я не хочу заходить так далеко, просто нужно, чтобы следующее поле активировалось автоматически после ввода 1 символа.
#define MAX_LENGTH 1
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSCharacterSet *myCharSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
for (int i = 0; i < [string length]; i++) {
unichar c = [string characterAtIndex:i];
if (![myCharSet characterIsMember:c]) {
return NO;
}
}
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 1) ? NO : YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == pc1) {
[pc2 becomeFirstResponder];
}else if (textField == pc2) {
[pc3 becomeFirstResponder];
}else if (textField == pc3) {
[pc4 becomeFirstResponder];
}else if (textField == pc4) {
[textField resignFirstResponder];
}
return YES;
}
Ответы
Ответ 1
Я пришел к решению, изменив код, который я нашел здесь:
http://www.thepensiveprogrammer.com/2010/03/customizing-uitextfield-formatting-for.html
Сначала установите ваш контроллер представления как делегат текстовых полей.
Затем сделайте что-то вроде этого:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
BOOL shouldProcess = NO; //default to reject
BOOL shouldMoveToNextField = NO; //default to remaining on the current field
int insertStringLength = [string length];
if(insertStringLength == 0){ //backspace
shouldProcess = YES; //Process if the backspace character was pressed
}
else {
if([[textField text] length] == 0) {
shouldProcess = YES; //Process if there is only 1 character right now
}
}
//here we deal with the UITextField on our own
if(shouldProcess){
//grab a mutable copy of what currently in the UITextField
NSMutableString* mstring = [[textField text] mutableCopy];
if([mstring length] == 0){
//nothing in the field yet so append the replacement string
[mstring appendString:string];
shouldMoveToNextField = YES;
}
else{
//adding a char or deleting?
if(insertStringLength > 0){
[mstring insertString:string atIndex:range.location];
}
else {
//delete case - the length of replacement string is zero for a delete
[mstring deleteCharactersInRange:range];
}
}
//set the text now
[textField setText:mstring];
[mstring release];
if (shouldMoveToNextField) {
//
//MOVE TO NEXT INPUT FIELD HERE
//
}
}
//always return no since we are manually changing the text field
return NO;
}
Ответ 2
Я знаю, что это очень старый вопрос, но здесь мой подход для предоставления единственного числового значения только для четырех UITextFields и автоматического "табуляции" на следующий (pin1-pin4 каждый представляет цифру PIN-кода lol и сохраняются как свойства):
-(BOOL)textFieldShouldReturn:(UITextField*)textField;
{
if (textField == pin1)
{
[pin2 becomeFirstResponder];
}
else if (textField == pin2)
{
[pin3 becomeFirstResponder];
}
else if (textField == pin3)
{
[pin4 becomeFirstResponder];
}
return NO;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
// This allows numeric text only, but also backspace for deletes
if (string.length > 0 && ![[NSScanner scannerWithString:string] scanInt:NULL])
return NO;
NSUInteger oldLength = [textField.text length];
NSUInteger replacementLength = [string length];
NSUInteger rangeLength = range.length;
NSUInteger newLength = oldLength - rangeLength + replacementLength;
// This 'tabs' to next field when entering digits
if (newLength == 1) {
if (textField == pin1)
{
[self performSelector:@selector(setNextResponder:) withObject:pin2 afterDelay:0.2];
}
else if (textField == pin2)
{
[self performSelector:@selector(setNextResponder:) withObject:pin3 afterDelay:0.2];
}
else if (textField == pin3)
{
[self performSelector:@selector(setNextResponder:) withObject:pin4 afterDelay:0.2];
}
}
//this goes to previous field as you backspace through them, so you don't have to tap into them individually
else if (oldLength > 0 && newLength == 0) {
if (textField == pin4)
{
[self performSelector:@selector(setNextResponder:) withObject:pin3 afterDelay:0.1];
}
else if (textField == pin3)
{
[self performSelector:@selector(setNextResponder:) withObject:pin2 afterDelay:0.1];
}
else if (textField == pin2)
{
[self performSelector:@selector(setNextResponder:) withObject:pin1 afterDelay:0.1];
}
}
return newLength <= 1;
}
- (void)setNextResponder:(UITextField *)nextResponder
{
[nextResponder becomeFirstResponder];
}
Ответ 3
ОБНОВЛЕННЫЙ КОД ДЛЯ SWIFT 3
@IBOutlet weak var tf1: UITextField!
@IBOutlet weak var tf2: UITextField!
@IBOutlet weak var tf3: UITextField!
@IBOutlet weak var tf4: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
tf1.delegate = self
tf2.delegate = self
tf3.delegate = self
tf4.delegate = self
tf1.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
tf2.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
tf3.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
tf4.addTarget(self, action: #selector(self.textFieldDidChange(textField:)), for: UIControlEvents.editingChanged)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
tf1.becomeFirstResponder()
}
func textFieldDidChange(textField: UITextField){
let text = textField.text
if text?.utf16.count==1{
switch textField{
case tf1:
tf2.becomeFirstResponder()
case tf2:
tf3.becomeFirstResponder()
case tf3:
tf4.becomeFirstResponder()
case tf4:
tf4.resignFirstResponder()
default:
break
}
}else{
}
}
Ответ 4
Хотя это старый вопрос, я просто пересек его, и я пришел с более простым решением. предполагая, что мы делаем это для кода прохода, поэтому максимальная длина каждой ячейки (UITextField) равна char.
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
if (![string isEqualToString:@""]) {
textField.text = string;
if ([textField isEqual:self.txtField1]) {
[self.txtField2 becomeFirstResponder];
}else if ([textField isEqual:self.txtField2]){
[self.txtField3 becomeFirstResponder];
}else if ([textField isEqual:self.txtField3]){
[self.txtField4 becomeFirstResponder];
}else{
[textField resignFirstResponder];
}
return NO;
}
return YES;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField.text.length > 0) {
textField.text = @"";
}
return YES;
}