你如何设置iOS中的标签顺序?

有没有一种方法(无论是在IB或代码)设置视图中的文本字段之间的标签顺序?

请注意,按下回车键(或“下一步”)button后,我不是在谈论下一个表单字段 – 许多蓝牙键盘都有一个制表键,它似乎以完全不同的顺序在字段中循环。 在我的具体情况下,这个顺序并不对应于字段在视图中的位置,甚至不是字段添加的顺序。 用手修改xib文件来改变NSNextKeyView似乎也没有什么不同。

有谁知道如何改变这个命令?

我对解决同样的问题很感兴趣,尽pipe到目前为止默认顺序似乎是从左到右,然后从上到下是我想要的。

我testing了这样一个假设,即光标通过子视图和超视图树的深度优先顺序移动,但事实并非如此。 改变子视图的顺序而不改变它们的位置并不会改变由标签按压所遍历的字段的顺序。

一个可能有用的function是,文本字段委托的textFieldShouldBeginEditing方法似乎被调用应用程序的窗口中的每个文本字段。 如果返回NO,那么文本字段将不会被选中,所以如果你可以定义你想要的顺序,只做正确的返回YES,那可能会解决你的问题。

@链轮的答案只是有点帮助。 只是因为有些东西可以用来开箱,并不意味着你应该停止思考一个更好的方法,甚至是正确的做法。 当他注意到行为是无证的,但大部分时间符合我们的需要。

尽pipe如此,这还不够。 想象一下RTL语言,标签仍然是从左到右的标签,更不用说从模拟器到设备的行为完全不同了(设备不会将第一个input集中在标签上)。 但最重要的是,苹果公司没有logging的实现似乎只考虑当前安装在视图层次结构中的视图。

想想一个表格(无双关语)的表格视图。 每个单元格都拥有一个单独的控件,因此并不是所有的表单元素都可以同时显示。 一旦你到达最底层(屏幕上!)控制,苹果就会循环备份,而不是进一步向下滚动。 这种行为绝对不是我们所希望的。

所以这就是我所想的。 您的表单应由视图控制器pipe理,视图控制器是响应器链的一部分。 所以你完全可以自由地实现以下方法:

#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]; } 

用于滚动离屏响应者的其他逻辑可能适用。

这种方法的另一个优点是你不需要inheritance你想要显示的所有types的控件(比如UITextField ),而是可以在控制器级别pipe理逻辑,在那里,老实说,是正确的地方所以。

在ios中的Tab键行为将如下: – 当你按下外部键盘上的选项卡 – 控制遍历该屏幕中的所有文本字段通过只调用shouldBeginEditing方法,其返回值也是由苹果决定,不能被覆盖。 扫描完所有字段后,它将计算相对于当前文本字段偏移的最近x位置文本字段,然后计算最近的Y位置字段。

在控件来到textFieldDidBeginEditing方法之前,也不能做任何事情。

苹果限制的原因可能是让开发人员遵循UI的指导原则,下一个响应者应该是最接近定位的字段而不是任何其他字段。

注册一个UIKeyCommand来检测按下的Tab键。 我在我当前的视图控制器中做了这个。

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

在关键tabKeyPressed处理程序里面find你当前的活动字段,然后设置你的下一个响应者。 orderedTextFields是我想要的标签顺序中的一个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] } 

您可以通过为每个文本字段设置标签并在textfieldShouldReturn方法中处理此标签。

看到这个博客有关它: http : //iphoneincubator.com/blog/windows-views/how-to-create-a-data-entry-screen

唯一的办法,我发现唯一检测一个物理键盘的Tab键击,是实现UIKeyInput协议的insertText:方法的canBecomeFirstResponder自定义对象。

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

我没有得到这个工作,而inheritanceUITextField,不幸的是,因为UITextField不会允许insertText:协议方法被调用。

虽然可能会帮助你

我通过将UITextFieldinheritance为NextableTextField来解决这个问题。 该子类具有IBOutlet类的UITextField属性。

在IB中构build接口。 将文本字段的类设置为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; } 

顺便说一句 – 我没有拿出这个; 只记得看到别人的想法。