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方法中,当调用此 if 语句时,视图是否向上滑动。如果文本字段在键盘下方,则向上滑动,如果不在键盘下方,则不向上滑动。

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

工作项目可以在这里找到。

我认为这个想法与视图控制器上的一个不错的类别相距甚远。您可以导入它,然后调用 viewDidLoad 上的设置。它所需要的只是一种无需将其写入 ivar 即可获得主视图的默认 y 原点的方法。我需要考虑一下。

于 2012-11-18T17:54:13.380 回答