我试图在键盘上升时移动视图时找到哪个文本字段处于活动状态。我正在尝试从scrollview的子视图中设置我的viewcontroller中的属性。
这是我用来在滚动视图中显示视图的代码
-(void)displayView:(UIViewController *)viewController{
[[viewFrame subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
[viewFrame scrollRectToVisible:CGRectMake(0, 0, 1, 1)
animated:NO];
[viewFrame addSubview: viewController.view];
_currentViewController = viewController;
}
- 编辑 -
我改变了对这个问题的思考方式。对不起,我发布时问题含糊不清。我当时很累,这在我脑海里是有意义的。
一个不同但相似的问题:UITextArea和UITextView的公共子类是否会给我firstResponder的起源?或者,在找到原点之前,还需要检查firstResponder的类吗?
答案 0 :(得分:35)
您需要搜索已成为第一响应者的对象。第一响应者对象是使用键盘的对象(实际上,他是一个具有用户输入焦点的对象)。要检查哪个文本字段使用键盘,请迭代文本字段(或仅覆盖所有子视图)并使用isFirstResponder
方法。
编辑: 根据要求,示例代码,假设所有文本字段都是视图控制器视图的子视图:
for (UIView *view in self.view.subviews) {
if (view.isFirstResponder) {
[self doSomethingCleverWithView:view];
}
}
答案 1 :(得分:22)
我做了一个扩展。
public extension UIResponder {
private struct Static {
static weak var responder: UIResponder?
}
public static func currentFirst() -> UIResponder? {
Static.responder = nil
UIApplication.shared.sendAction(#selector(UIResponder._trap), to: nil, from: nil, for: nil)
return Static.responder
}
@objc private func _trap() {
Static.responder = self
}
}
使用:
if let activeTextField = UIResponder.currentFirst() as? UITextField {
// ...
}
答案 2 :(得分:2)
为什么不给所有UITextfields单独的标签textfield.tag = 1
然后你回复代表DidBeginEditing。并检查哪个textfield.tag是活动的?
答案 3 :(得分:2)
我第一次使用Xilexio的解决方案,但速度很慢。我最终使用标签。这是我的代码并设置为一个例子。
@property (nonatomic) NSInteger currentFormField;
typedef NS_ENUM(NSInteger, IOUFormField) {
IOUFormFieldName,
IOUFormFieldAmount,
IOUFormFieldDescription,
IOUFormFieldDate
};
...
self.nameField.tag = IOUFormFieldName;
self.amountField.tag = IOUFormFieldAmount;
self.descriptionField.tag = IOUFormFieldDescription;
self.dateField.tag = IOUFormFieldDate;
-(void)keyboardWillShow:(NSNotification *)notification {
// Move the scroll view to a position where the user can see the top and bottom form fields
// For example, if the user is on the description field, they should be able to see the date field and the amount field.
// The keyboard rect value comes as a NSValue * (a wrapped NSRect) with origin and size.
// The origin is using screen coordinates which is pixel based so don't use it.
// Use the size. Seems like it is density based.
CGFloat viewableScreenHeight = self.view.frame.size.height - keyboardFrameBeginRect.size.height;
// When the user is on a form field, get the current form field y position to where the scroll view should move to
CGFloat currentFormFieldYPosition = 0;
switch (self.currentFormField) {
case IOUFormFieldName:
{
currentFormFieldYPosition = self.nameField.frame.origin.y;
// If the scroll view is at the bottom and the user taps on the name field, move the scroll view to the top.
// This is so that users can see the give/get segments.
[self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
break;
}
case IOUFormFieldAmount:
{
currentFormFieldYPosition = self.amountField.frame.origin.y;
break;
}
case IOUFormFieldDescription:
{
currentFormFieldYPosition = self.descriptionField.frame.origin.y;
break;
}
case IOUFormFieldDate:
{
currentFormFieldYPosition = self.dateField.frame.origin.y;
break;
}
default:
break;
}
// I want the current form field y position to be 100dp from the keyboard y position.
// 50dp for the current form field to be visible and another 50dp for the next form field so users can see it.
CGFloat leftoverTopHeight = viewableScreenHeight - 100;
// If the current form field y position is greater than the left over top height, that means that the current form field is hidden
// We make the calculations and then move the scroll view to the right position
if (currentFormFieldYPosition > leftoverTopHeight) {
CGFloat movedScreenPosition = currentFormFieldYPosition - leftoverTopHeight;
[self.scrollView setContentOffset:CGPointMake(0, movedScreenPosition) animated:YES];
}
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
switch (textField.tag) {
case IOUFormFieldName:
self.currentFormField = IOUFormFieldName;
break;
case IOUFormFieldAmount:
self.currentFormField = IOUFormFieldAmount;
break;
case IOUFormFieldDescription:
self.currentFormField = IOUFormFieldDescription;
break;
case IOUFormFieldDate:
self.currentFormField = IOUFormFieldDate;
default:
break;
}
return true;
}
如果您有任何问题,请告诉我,我会澄清。请注意,评论适合我。还要注意一些代码或为简洁而省略。
答案 4 :(得分:2)
假设您的文本字段完全相同(即所有货币或文本)并且不需要任何特殊格式,我建议如下:
首先,有一个可选的textField变量。例如:
C2 -> =COUNTIF($B$2:B2;B2)
D2 -> =B2&"|"&C2
G2 -> =IFERROR(INDEX($A:$A;MATCH($F2&"|"&COLUMN(A1);$D:$D;0));"")
然后添加以下内容:
var currentTextField: UITextField?
现在,您可以通过“活跃”来做任何您想做的事情。文本字段,除非您需要某些特定的格式化操作,否则无需跟踪任何标记。
答案 5 :(得分:1)
在swift 3中,在if else语句中使用以下函数:
if (textField.isEditing)
[iOS] [swift3]
答案 6 :(得分:0)
基于Xilexio's answer但迭代所有视图以查找请求的FirstResponder
视图
-(UIView*)getFirstResponderInView:(UIView*)parentView{
UIView* requestedView = nil;
for (UIView *view in parentView.subviews) {
if (view.isFirstResponder) {
[view resignFirstResponder];
} else if (view.subviews.count > 0) {
requestedView = [self getFirstResponderInView:view];
}
if (requestedView != nil) {
return requestedView;
}
}
return nil;
}
像这样使用:
UIView *view = [self getFirstResponderInView:self.view];
if(view != nil){
[self doSomethingCleverWithView:view];
}