27

当我在键盘上升时移动视图时,我试图找到哪个文本字段处于活动状态。我正在尝试从滚动视图的子视图在我的视图控制器中设置一个属性。

这是我用来在滚动视图中显示视图的代码

-(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 的类,然后才能找到原点?

4

7 回答 7

38

您需要搜索已成为第一响应者的对象。第一响应者对象是使用键盘的对象(实际上,他是专注于用户输入的对象)。要检查哪个文本字段使用键盘,请遍历您的文本字段(或仅遍历所有子视图)并使用该isFirstResponder方法。

编辑:根据要求,示例代码,假设所有文本字段都是视图控制器视图的子视图:

for (UIView *view in self.view.subviews) {
    if (view.isFirstResponder) {
        [self doSomethingCleverWithView:view];
    }
}
于 2012-08-29T08:48:41.457 回答
37

我为此做了一个扩展。

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 {
    // ...
}
于 2016-11-01T00:29:24.657 回答
3

假设您的文本字段都相同(即所有货币或文本)并且不需要任何特殊格式,我会建议以下内容:

首先,有一个可选的 textField 变量。例如:

var currentTextField: UITextField?

然后添加以下内容:

func textFieldDidBeginEditing(textField: UITextField) {

        currentTextField = textField

}

现在您可以使用“活动”文本字段做任何您想做的事情,并且您不需要跟踪任何标签,除非您需要一些特定的格式化操作。

于 2015-12-11T14:26:38.710 回答
2

为什么不给所有 UITextfields 单独的标签 textfield.tag = 1

然后您响应委托 DidBeginEditing。并检查哪个 textfield.tag 处于活动状态?

于 2012-08-29T09:41:50.533 回答
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;
}

如果您有任何问题,请告诉我,我会澄清。请注意,评论是给我的。另请注意,为简洁起见,有些代码或省略了。

于 2015-10-23T17:56:47.940 回答
1

在 swift 3 中,在 if else 语句中使用以下函数:

    if (textField.isEditing) 

[iOS] [swift3]

于 2017-06-29T17:47:52.283 回答
0

基于Xilexio 的回答,但遍历所有视图以找到请求的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];
}
于 2016-10-01T01:20:07.193 回答