0

私はここのドキュメントでAppleが持っているデモコードを使用しました:

http://developer.apple.com/library/ios/#documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html#//apple_ref/doc/uid/TP40009542-CH5-SW7

UITextFieldをタップしてキーボードが表示されたら、ビューを上にスライドする必要があります。私は上記のリンクのコードを使用しています。これはApple独自のデモコードであり、これは理にかなっています。

しかし、私の問題は、Appleのコードを実質的に変更せずに使用すると、実際にはテキストフィールドをタップした後ではなく、入力時にのみビューが上にスライドします。

この- (void)keyboardWasShown:(NSNotification*)aNotificationメソッドでは、ビューが上にスライドするかどうかは、thisifステートメントが呼び出されたときに発生します。テキストフィールドがキーボードの下にある場合は上にスライドし、キーボードの下にない場合は上にスライドしません。

if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }

問題は、テキストフィールドをタップすると、このifステートメントがスキップされ、その中のコードが実行されないことです。

私はそれを解決することはできませんが、それはすべて以下のこの方法で起こります。最初のタップではなく、入力時にスライドするだけなのはなぜですか?

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
    scrollView.contentInset = contentInsets;
    scrollView.scrollIndicatorInsets = contentInsets;

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your application might not need or want this behavior.
    CGRect aRect = self.view.frame;
    aRect.size.height -= kbSize.height;
    if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}
4

1 に答える 1

1

Appleのドキュメントをもう一度見ました。うん-彼らは生活のためのソフトウェアを書いていませんか?代わりにこれを試してください。メインビューのデフォルトの位置を覚えておいてください。

@interface ViewController ()
    @property (assign, nonatomic) CGFloat viewOriginY;
@end

キーボード通知とタップ(ファーストレスポンダーを却下するため)に登録します。

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.viewOriginY = self.view.frame.origin.y;

    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    [center addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    [center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

    // add a tap gesture to drop first responder
    UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
    [self.view addGestureRecognizer:tapGR];
}

最初のレスポンダーを(再帰的に)見つけるための関数を記述します。

- (UIView *)firstResponderWithin:(UIView *)view {

    if ([view isFirstResponder]) return view;

    for (UIView *subview in view.subviews) {
        UIView *answer = [self firstResponderWithin:subview];
        if (answer) return answer;
    }
    return nil;
}

パンチラインは次のとおりです。キーボードが表示されたら、そのフレームと表示する必要のあるビューのフレームを計算します。このVCのビューのように、一般的な座標系でこれを行うことが重要です。次に、ビューをスライドして、ファーストレスポンダーを表示します。

- (void)keyboardDidShow:(NSNotification *)notification {

    CGRect keyboardFrameW = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    CGRect keyboardFrame = [window convertRect:keyboardFrameW toView:self.view];

    UIView *firstResponder = [self firstResponderWithin:self.view];
    CGRect firstResponderFrame = [firstResponder.superview convertRect:firstResponder.frame toView:self.view];

    // let's put the bottom of the first responder's frame just above the top of the keyboard
    CGFloat firstResponderBottom = CGRectGetMaxY(firstResponderFrame);
    CGFloat targetBottom = keyboardFrame.origin.y - 8.0;    
    CGFloat offsetY = MAX(0.0, firstResponderBottom - targetBottom);

    [UIView animateWithDuration:0.3 animations:^{
        self.view.frame = CGRectOffset(self.view.frame, 0.0, -offsetY);
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification {

    [UIView animateWithDuration:0.3 animations:^{
        self.view.frame = CGRectMake(0.0, self.viewOriginY, self.view.frame.size.width, self.view.frame.size.height);
    }];
}

オプション-ユーザーが他の場所をタップした場合は、キーボードを閉じます。

- (void)tapped:(UITapGestureRecognizer *)gr {

    UIView *firstResponder = [self firstResponderWithin:self.view];
    [firstResponder resignFirstResponder];
}

作業プロジェクトはここにあります。

このアイデアは、ViewControllerの優れたカテゴリから1つ離れていると思います。それをインポートして、viewDidLoadでセットアップを呼び出すことができます。必要なのは、メインビューのデフォルトのy原点を、ivarに書き込まずに取得する方法だけです。その上で麺を作る必要があります。

于 2012-11-18T17:54:13.380 に答える