使用UIScrollViewKeyboardDismissModeInteractive移动一个栏

我有一个文本字段,我锚定到键盘的顶部。 我不能使用inputAccessoryView,因为它总是显示。 我能够通过键盘观察键盘隐藏/显示的通知来上下移动它,但这似乎不适用于UIScrollViewKeyboardDismissModeInteractive。 有没有办法获得关键盘位置的持续反馈以同步动画?

编辑:看起来这在iOS 8中不起作用,伙计们 – 对不起! 我也在寻找新的解决方案

我通过创建一个不可见的inputAccessoryView来解决这个问题。

 textView.inputAccessoryView = [[MJXObservingInputAccessoryView alloc] init]; 

accessoryView观察其superview的框架并发布您可以匹配的通知。

 static NSString * const MJXObservingInputAccessoryViewSuperviewFrameDidChangeNotification = @"MJXObservingInputAccessoryViewSuperviewFrameDidChangeNotification"; @interface MJXObservingInputAccessoryView : UIView @end @implementation MJXObservingInputAccessoryView - (void)willMoveToSuperview:(UIView *)newSuperview { if (self.superview) { [self.superview removeObserver:self forKeyPath:@"frame"]; } [newSuperview addObserver:self forKeyPath:@"frame" options:0 context:NULL]; [super willMoveToSuperview:newSuperview]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == self.superview && [keyPath isEqualToString:@"frame"]) { [[NSNotificationCenter defaultCenter] postNotificationName:MJXObservingInputAccessoryViewSuperviewFrameDidChangeNotification object:self]; } } @end 

我找到了一个解决方案(虽然有点像黑客),我实现了scrollViewDidScroll来监听UITableView中内置的panGestureRecognizer。 事实certificate,在整个手势中,键盘的顶部均保持完美均匀,因此您可以不断更新文本字段,使其保持在平移手指上方。

 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { CGPoint fingerLocation = [scrollView.panGestureRecognizer locationInView:scrollView]; CGPoint absoluteFingerLocation = [scrollView convertPoint:fingerLocation toView:self.view]; if (_keyboardIsOpen && scrollView.panGestureRecognizer.state == UIGestureRecognizerStateChanged && absoluteFingerLocation.y >= (self.view.frame.size.height - _keyboardFrame.size.height)) { [UIView animateWithDuration:.05 animations:^{ //This is an autolayout constraint that needs to be set to the distance between the top of the keyboard and the bottom of the screen (with a buffer of 3) _bottomViewVerticalSpacingConstraint.constant = [[UIScreen mainScreen] bounds].size.height - absoluteFingerLocation.y - 3; [self.view layoutIfNeeded]; }]; } } 

然后我也注册了通知

  [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrame object:nil]; 

并像这样处理它们

 -(void)keyboardWillShown:(NSNotification*)aNotification { _keyboardIsOpen = YES; NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; [UIView animateWithDuration:.05 animations:^{ _bottomViewVerticalSpacingConstraint.constant = kbSize.height; [self.view layoutIfNeeded]; }]; } -(void)keyboardWillBeHidden:(NSNotification*)aNotification { _keyboardIsOpen = NO; [UIView animateWithDuration:.3 animations:^{ _bottomViewVerticalSpacingConstraint.constant = 0; [self.view layoutIfNeeded]; }]; } -(void)keyboardWillChangeFrame:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; _keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; } 

Malcolm的答案适用于iOS 8和7,只需稍作调整即可。 我没有足够的声誉来评论他的post,所以这被添加为社区维基,供需要适用于iOS 7和8的解决方案的人使用。

 #import  static NSString *const SSObservingInputAccessoryViewFrameDidChangeNotification = @"SSObservingInputAccessoryViewFrameDidChangeNotification"; @interface SSObservingInputAccessoryView : UIView @end 

履行

 #import "SSObservingInputAccessoryView.h" @implementation SSObservingInputAccessoryView - (void)willMoveToSuperview:(UIView *)newSuperview { if (self.superview) { [self.superview removeObserver:self forKeyPath:@"center"]; [self.superview removeObserver:self forKeyPath:@"frame"]; } [newSuperview addObserver:self forKeyPath:@"center" options:0 context:nil]; [newSuperview addObserver:self forKeyPath:@"frame" options:0 context:nil]; [super willMoveToSuperview:newSuperview]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (object == self.superview && ([keyPath isEqualToString:@"center"] || [keyPath isEqualToString:@"frame"])) { [[NSNotificationCenter defaultCenter] postNotificationName:SSObservingInputAccessoryViewFrameDidChangeNotification object:self]; } } @end 

只有在iPhone X iOS 11.2.2上以Swift 4交互式更新CALayer位置:

 class MyValueObservingView: UIView { static let CALayerPositionChangeNotification = Notification.Name("CALayerPositionChangeNotification") static let CALayerPositionUserInfoKey = "position" override func willMove(toSuperview newSuperview: UIView?) { superview?.layer.removeObserver(self, forKeyPath: type(of: self).CALayerPositionUserInfoKey) newSuperview?.layer.addObserver(self, forKeyPath: type(of: self).CALayerPositionUserInfoKey, options: [.initial, .new], context: nil) super.willMove(toSuperview: newSuperview) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == type(of: self).CALayerPositionUserInfoKey, let position = change?[.newKey] as? CGPoint { // print("MyValueObservingView layer position changed to \(position)") NotificationCenter.default.post(name: type(of: self).CALayerPositionChangeNotification, object: self, userInfo: [type(of: self).CALayerPositionUserInfoKey: position]) } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) } } } 

你试过DAKeyboardControl吗?

  UIView *addCommentContainer = self.addCommentContainer; [self.view addKeyboardPanningWithActionHandler:^(CGRect keyboardFrameInView) { [addCommentContainer setY:keyboardFrameInView.origin.y - addCommentContainer.frame.size.height]; }]; 

您可以在此控件上查看处理键盘框架的源代码。

有一种更简单的方法可以将某些东西固定在键盘上。 您只需要实现这些方法,iOS将为您处理它。

 - (UIView *) inputAccessoryView { // Return your textfield, buttons, etc } - (BOOL) canBecomeFirstResponder { return YES; } 

这是一个很好的教程,可以更好地分解它

这对我有用:

注册键盘确实隐藏了通知: UIKeyboardDidHideNotification

viewDidLoad ,使用addSubview将工具栏添加到视图的底部。

我使用textView所以在textViewShouldBeginEditing中我设置了inputAccessoryView。

然后在键盘上做了隐藏方法,调整工具栏的框架,将inputAccessoryView设置为nil,重要的是,再次将工具栏添加为视图的子视图。