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のクラスも確認する必要がありますか?

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

すべてのUITextfieldに個別のタグを付けないのはなぜですか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では、ifelseステートメントで以下の関数を使用します。

    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 に答える