How can I make a UITextField move up when the keyboard is present - on starting to edit?
使用iOS SDK:
我有一个带键盘的
当键盘打开时,允许滚动
自动"跳转"(向上滚动)或缩短
我知道我需要一个
我需要一个
为了自动滚动到活动文本字段,需要实现什么?
理想情况下,尽可能多的组件设置将在Interface Builder中完成。我只想为需要的东西编写代码。
注:我正在使用的
编辑:我添加滚动条只是为了当键盘出现时。尽管不需要,但我觉得它提供了更好的界面,因为这样用户就可以滚动和更改文本框。
我让它工作,当键盘上下移动时,我改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -(void)textFieldDidBeginEditing:(UITextField *)textField { //Keyboard becomes visible scrollView.frame = CGRectMake(scrollView.frame.origin.x, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height - 215 + 50); //resize } -(void)textFieldDidEndEditing:(UITextField *)textField { //keyboard will hide scrollView.frame = CGRectMake(scrollView.frame.origin.x, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height + 215 - 50); //resize } |
但是,这不会自动"向上移动"或使较低的文本字段在可见区域居中,这是我真正想要的。
如果你现在的内容不适合iPhone屏幕,你只需要一个
为了在不被键盘隐藏的情况下显示
以下是一些示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #define kOFFSET_FOR_KEYBOARD 80.0 -(void)keyboardWillShow { // Animate the current view out of the way if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } } -(void)keyboardWillHide { if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } } -(void)textFieldDidBeginEditing:(UITextField *)sender { if ([sender isEqual:mailTf]) { //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } } } //method to move the view up/down whenever the keyboard is shown/dismissed -(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; // if you want to slide up the view CGRect rect = self.view.frame; if (movedUp) { // 1. move the view's origin up so that the text field that will be hidden come above the keyboard // 2. increase the size of the view so that the area behind the keyboard is covered up. rect.origin.y -= kOFFSET_FOR_KEYBOARD; rect.size.height += kOFFSET_FOR_KEYBOARD; } else { // revert back to the normal state. rect.origin.y += kOFFSET_FOR_KEYBOARD; rect.size.height -= kOFFSET_FOR_KEYBOARD; } self.view.frame = rect; [UIView commitAnimations]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } |
我对由多个
如果您的
1)确保内容大小大于
2)既然您了解了
3)这里有一个要点:当我第一次实现它时,我想我必须得到编辑后的textfield的
下面是当键盘出现时,正确地将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window]; // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; keyboardIsShown = NO; //make contentSize bigger than your scrollSize (you will need to figure out for your own use case) CGSize scrollContentSize = CGSizeMake(320, 345); self.scrollView.contentSize = scrollContentSize; } - (void)keyboardWillHide:(NSNotification *)n { NSDictionary* userInfo = [n userInfo]; // get the size of the keyboard CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // resize the scrollview CGRect viewFrame = self.scrollView.frame; // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView. viewFrame.size.height += (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = NO; } - (void)keyboardWillShow:(NSNotification *)n { // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown. This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`. If we were to resize the `UIScrollView` again, it would be disastrous. NOTE: The keyboard notification will fire even when the keyboard is already shown. if (keyboardIsShown) { return; } NSDictionary* userInfo = [n userInfo]; // get the size of the keyboard CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; // resize the noteView CGRect viewFrame = self.scrollView.frame; // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView. viewFrame.size.height -= (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = YES; } |
需要注意的一点是,即使键盘已经在屏幕上,当您在另一个
希望这段代码能让你们中的一些人省去很多麻烦。
事实上,最好只使用文档中提供的Apple实现。然而,他们提供的代码是错误的。将EDOCX1[0]中的部分替换为以下注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 | NSDictionary* info = [aNotification userInfo]; CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view]; CGSize kbSize =keyPadFrame.size; CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview]; CGRect aRect = self.view.bounds; aRect.size.height -= (kbSize.height); CGPoint origin = activeRect.origin; origin.y -= backScrollView.contentOffset.y; if (!CGRectContainsPoint(aRect, origin)) { CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height)); [backScrollView setContentOffset:scrollPoint animated:YES]; } |
苹果代码的问题是:(1)它们总是计算点是否在视图的框架内,但它是一个
1 | origin.y -= scrollView.contentOffset.y |
(2)它们通过键盘的高度来移动内容偏移量,但我们想要的是相反的(我们要通过屏幕上可见的高度来移动
1 | activeField.frame.origin.y-(aRect.size.height) |
在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | -(void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField:textField up:YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField:textField up:NO]; } -(void)animateTextField:(UITextField*)textField up:(BOOL)up { const int movementDistance = -130; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? movementDistance : -movementDistance); [UIView beginAnimations: @"animateTextField" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; } |
我希望这段代码对您有所帮助。
在斯威夫特2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | func animateTextField(textField: UITextField, up: Bool) { let movementDistance:CGFloat = -130 let movementDuration: Double = 0.3 var movement:CGFloat = 0 if up { movement = movementDistance } else { movement = -movementDistance } UIView.beginAnimations("animateTextField", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } func textFieldDidBeginEditing(textField: UITextField) { self.animateTextField(textField, up:true) } func textFieldDidEndEditing(textField: UITextField) { self.animateTextField(textField, up:false) } |
斯威夫特3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | func animateTextField(textField: UITextField, up: Bool) { let movementDistance:CGFloat = -130 let movementDuration: Double = 0.3 var movement:CGFloat = 0 if up { movement = movementDistance } else { movement = -movementDistance } UIView.beginAnimations("animateTextField", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration) self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement) UIView.commitAnimations() } func textFieldDidBeginEditing(textField: UITextField) { self.animateTextField(textField: textField, up:true) } func textFieldDidEndEditing(textField: UITextField) { self.animateTextField(textField: textField, up:false) } |
仅使用文本字段:
1a)使用
1b)在uiscrollview中手动嵌入名为scrollview的文本字段
2)设置
3)设置每个
4)复制/粘贴:
1 2 3 4 5 6 7 8 | - (void)textFieldDidBeginEditing:(UITextField *)textField { CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y); [scrollView setContentOffset:scrollPoint animated:YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [scrollView setContentOffset:CGPointZero animated:YES]; } |
对于通用解决方案,这里是我实现IQKeyboardManager的方法。
步骤1:-我在一个单例类中添加了
步骤2:-如果发现
第3步:我计算了第一个响应的
第4步:根据预期的移动距离,我向上/向下移动
步骤5:-如果发现
第6步:我计算了
第七步:根据干扰距离,我恢复了
步骤8:-我在app load上实例化了singleton iqkeyboardManager类实例,所以app中的每个
这就是iqkeyboardManager为您所做的一切,实际上没有任何代码行!!只需将相关源文件拖放到项目。iqkeyboardManager还支持设备方向、自动uitoolbar管理、keybkeyboardDistance from textfield,比您想象的要多得多。
我整合了一个通用的
当键盘即将出现时,子类将找到将要编辑的子视图,并调整其帧和内容偏移量,以确保视图可见,并显示与键盘弹出窗口匹配的动画。当键盘消失时,它会恢复原来的大小。
它基本上可以与任何设置一起工作,要么是基于
这里是:将文本字段移出键盘的解决方案
For Swift Programmers :
这将为您做所有事情,只需将它们放到视图控制器类中,并将
1 | textField.delegate = self // Setting delegate of your UITextField to self |
实现委托回调方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | func textFieldDidBeginEditing(textField: UITextField) { animateViewMoving(true, moveValue: 100) } func textFieldDidEndEditing(textField: UITextField) { animateViewMoving(false, moveValue: 100) } // Lifting the view up func animateViewMoving (up:Bool, moveValue :CGFloat){ let movementDuration:NSTimeInterval = 0.3 let movement:CGFloat = ( up ? -moveValue : moveValue) UIView.beginAnimations("animateView", context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(movementDuration ) self.view.frame = CGRectOffset(self.view.frame, 0, movement) UIView.commitAnimations() } |
已经有很多答案了,但是上面的解决方案都没有"完美"的无缺陷、向后兼容和无闪烁动画所需的所有高级定位工具。(同时设置帧/边界和内容偏移动画、不同的界面方向、iPad拆分键盘等时出现错误)
让我分享我的解决方案:
(假设您已经设置了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | // Called when UIKeyboardWillShowNotification is sent - (void)keyboardWillShow:(NSNotification*)notification { // if we have no view or are not visible in any window, we don't care if (!self.isViewLoaded || !self.view.window) { return; } NSDictionary *userInfo = [notification userInfo]; CGRect keyboardFrameInWindow; [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow]; // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil]; CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView); UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0); // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary. [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; _scrollView.contentInset = newContentInsets; _scrollView.scrollIndicatorInsets = newContentInsets; /* * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element * that should be visible, e.g. a purchase button below an amount text field * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields */ if (_focusedControl) { CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view. CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y; CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height; // this is the visible part of the scroll view that is not hidden by the keyboard CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height; if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question // scroll up until the control is in place CGPoint newContentOffset = _scrollView.contentOffset; newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight); // make sure we don't set an impossible offset caused by the"nice visual offset" // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight); [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) { // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field CGPoint newContentOffset = _scrollView.contentOffset; newContentOffset.y = controlFrameInScrollView.origin.y; [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code } } [UIView commitAnimations]; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillHide:(NSNotification*)notification { // if we have no view or are not visible in any window, we don't care if (!self.isViewLoaded || !self.view.window) { return; } NSDictionary *userInfo = notification.userInfo; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]]; [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]]; // undo all that keyboardWillShow-magic // the scroll view will adjust its contentOffset apropriately _scrollView.contentInset = UIEdgeInsetsZero; _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero; [UIView commitAnimations]; } |
Shiun说,"事实证明,我相信uiscrollView实际上隐式地将当前编辑的uitextfield引入了可视窗口",这似乎适用于iOS 3.1.3,但不适用于3.2、4.0或4.1。我必须添加一个显式的ScrollDirectToVisible,以便使iOS上的uitextfield可见>=3.2。
要考虑的一件事是,你是否曾经想单独使用
这将是一些额外的工作,但我建议您实现一个表视图中的所有数据输入视图。在你的
本文档详细介绍了此问题的解决方案。查看"移动位于键盘下的内容"下的源代码。这很简单。
编辑:注意到示例中有一个小故障。你可能想听听
找到最简单的解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | - (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField: textField up: YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField: textField up: NO]; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { const int movementDistance = 80; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: @"anim" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; } |
适用于许多uitextfield的小修补程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #pragma mark UIKeyboard handling #define kMin 150 -(void)textFieldDidBeginEditing:(UITextField *)sender { if (currTextField) { [currTextField release]; } currTextField = [sender retain]; //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y + currTextField.frame.origin. y >= kMin) { [self setViewMovedUp:YES]; } } //method to move the view up/down whenever the keyboard is shown/dismissed -(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3]; // if you want to slide up the view CGRect rect = self.view.frame; if (movedUp) { // 1. move the view's origin up so that the text field that will be hidden come above the keyboard // 2. increase the size of the view so that the area behind the keyboard is covered up. rect.origin.y = kMin - currTextField.frame.origin.y ; } else { // revert back to the normal state. rect.origin.y = 0; } self.view.frame = rect; [UIView commitAnimations]; } - (void)keyboardWillShow:(NSNotification *)notif { //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately if ([currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y >= kMin) { [self setViewMovedUp:YES]; } else if (![currTextField isFirstResponder] && currTextField.frame.origin.y + self.view.frame.origin.y < kMin) { [self setViewMovedUp:NO]; } } - (void)keyboardWillHide:(NSNotification *)notif { //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately if (self.view.frame.origin.y < 0 ) { [self setViewMovedUp:NO]; } } - (void)viewWillAppear:(BOOL)animated { // register for keyboard notifications [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; } - (void)viewWillDisappear:(BOOL)animated { // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; } |
RPDP的代码成功地将文本字段移到键盘之外。但是,当您在使用和取消键盘后滚动到顶部时,顶部已向上滚动到视图之外。对于模拟器和设备来说是这样的。要读取该视图顶部的内容,必须重新加载该视图。
他下面的代码不应该让视图变低吗?
1 2 3 4 5 6 | else { // revert back to the normal state. rect.origin.y += kOFFSET_FOR_KEYBOARD; rect.size.height -= kOFFSET_FOR_KEYBOARD; } |
我不确定向上移动视图是否是正确的方法,我用不同的方式,调整uiscroll视图的大小。我在一篇小文章里详细解释了它
要恢复到原始视图状态,请添加:
1 2 3 4 5 6 7 8 9 | -(void)textFieldDidEndEditing:(UITextField *)sender { //move the main view, so that the keyboard does not hide it. if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } } |
有这么多解决方案,但我花了几个小时才开始工作。所以,我把这个代码放在这里(粘贴到项目中,任何修改都不需要):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | @interface RegistrationViewController : UIViewController <UITextFieldDelegate>{ UITextField* activeField; UIScrollView *scrollView; } @end - (void)viewDidLoad { [super viewDidLoad]; scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame]; //scrool view must be under main view - swap it UIView* natView = self.view; [self setView:scrollView]; [self.view addSubview:natView]; CGSize scrollViewContentSize = self.view.frame.size; [scrollView setContentSize:scrollViewContentSize]; [self registerForKeyboardNotifications]; } - (void)viewDidUnload { activeField = nil; scrollView = nil; [self unregisterForKeyboardNotifications]; [super viewDidUnload]; } - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShown:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } -(void)unregisterForKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; // unregister for keyboard notifications while not visible. [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; CGRect frame = self.view.frame; frame.size.height -= kbSize.height; CGPoint fOrigin = activeField.frame.origin; fOrigin.y -= scrollView.contentOffset.y; fOrigin.y += activeField.frame.size.height; if (!CGRectContainsPoint(frame, fOrigin) ) { CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y + activeField.frame.size.height - frame.size.height); [scrollView setContentOffset:scrollPoint animated:YES]; } } - (void)keyboardWillBeHidden:(NSNotification*)aNotification { [scrollView setContentOffset:CGPointZero animated:YES]; } - (void)textFieldDidBeginEditing:(UITextField *)textField { activeField = textField; } - (void)textFieldDidEndEditing:(UITextField *)textField { activeField = nil; } -(BOOL) textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } |
P.S:我希望代码能帮助人们快速取得预期的效果。(XCODER 4.5)
@ USER 171753
要使视图返回原始添加:
1 2 3 4 5 | -(BOOL)textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; [self setViewMovedUp:NO]; return YES; } |
试试这个小把戏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - (void)textFieldDidBeginEditing:(UITextField *)textField { [self animateTextField: textField up: YES]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [self animateTextField: textField up: NO]; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { const int movementDistance = textField.frame.origin.y / 2; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: @"anim" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; } |
它不需要滚动视图就能移动视图框架。您可以更改
要使用此子类,请将自定义视图控制器设置为gmkeyboardvc的子类,并继承此功能(只需确保实现
斯威夫特4。
使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import UIKit class ViewController: UIViewController, UITextFieldDelegate { @IBOutlet var textField: UITextField! @IBOutlet var chatView: UIView! override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { textField.resignFirstResponder() } @objc func keyboardWillChange(notification: NSNotification) { let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue let deltaY = targetFrame.origin.y - curFrame.origin.y print("deltaY",deltaY) UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: { self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField },completion: nil) } func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() return true } } |
根据文档,从iOS 3.0开始,当对文本字段进行在线编辑时,
来自文档:
A table view controller supports inline editing of table view rows;
if, for example, rows have embedded text fields in editing mode, it
scrolls the row being edited above the virtual keyboard that is
displayed.
这是我为一个特定的布局提出的黑客解决方案。这个解决方案类似于MattGallagher的解决方案,即滚动一个部分到视图中。我对iPhone的开发还是个新手,不熟悉布局是如何工作的。因此,这个黑客。
我的实现需要支持在单击字段时滚动,以及在用户选择键盘上的下一个时滚动。
我有一个775米高的鸟瞰图。控件基本上以3组的形式分布在一个大空间上。最后我得到了下面的ib布局。
1 | UIView -> UIScrollView -> [UI Components] |
黑客来了
我将uiscrollview的高度设置为比实际布局(1250)大500个单位。然后,我创建了一个数组,其中包含我需要滚动到的绝对位置,以及一个简单的函数,根据ib标签号获取它们。
1 2 3 4 5 6 7 8 9 | static NSInteger stepRange[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410 }; NSInteger getScrollPos(NSInteger i) { if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) { return 0 ; return stepRange[i] ; } |
现在,您需要做的就是在textfieldDidbeginediting和textfieldShouldReturn中使用以下两行代码(如果要创建下一个字段导航,则使用后一行代码)
1 2 | CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ; [self.scrollView setContentOffset:point animated:YES] ; |
一个例子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | - (void) textFieldDidBeginEditing:(UITextField *)textField { CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ; [self.scrollView setContentOffset:point animated:YES] ; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSInteger nextTag = textField.tag + 1; UIResponder* nextResponder = [textField.superview viewWithTag:nextTag]; if (nextResponder) { [nextResponder becomeFirstResponder]; CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ; [self.scrollView setContentOffset:point animated:YES] ; } else{ [textField resignFirstResponder]; } return YES ; } |
此方法不像其他方法那样"向后滚动"。这不是要求。同样,这是一个相当高的uiview,我没有时间学习内部布局引擎。
Here I found the simplest solution to handle keypad.
您只需要复制粘贴到下面的示例代码,并更改您的文本字段或任何您想向上移动的视图。
STEP -1
Just copy-paste below two method in your controller
1 2 3 4 5 6 7 8 9 10 11 12 13 | - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } - (void)deregisterFromKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } |
STEP -2
register & deregister Keypad Notifications in viewWillAppear and
viewWillDisappear methods respectively.
1 2 3 4 5 6 7 8 9 10 11 | - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self registerForKeyboardNotifications]; } - (void)viewWillDisappear:(BOOL)animated { [self deregisterFromKeyboardNotifications]; [super viewWillDisappear:animated]; } |
STEP-3
Here comes the soul part, Just replace your textfield, and change
height how much you want to move upside.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | - (void)keyboardWasShown:(NSNotification *)notification { NSDictionary* info = [notification userInfo]; CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; //you need replace your textfield instance here CGPoint textFieldOrigin = self.tokenForPlaceField.frame.origin; CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height; CGRect visibleRect = self.view.frame; visibleRect.size.height -= currentKeyboardSize.height; if (!CGRectContainsPoint(visibleRect, textFieldOrigin)) { //you can add yor desired height how much you want move keypad up, by replacing"textFieldHeight" below CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height [self.scrollView setContentOffset:scrollPoint animated:YES]; } } - (void)keyboardWillBeHidden:(NSNotification *)notification { [self.scrollView setContentOffset:CGPointZero animated:YES]; } |
参考文献:好吧,请感谢这家伙,他分享了这个漂亮的代码截图,干净的解决方案。
希望这能帮上大忙。
当
如果不是,可能是因为TableView的代码/设置不正确。
例如,当我在长桌上重新加载一个底部的
1 2 3 4 | -(void) viewWillAppear:(BOOL)animated { [self.tableview reloadData]; } |
然后,当我点击文本框时,底部的文本框被键盘遮住了。
为了解决这个问题,我必须这么做-
1 2 3 4 5 6 | -(void) viewWillAppear:(BOOL)animated { //add the following line to fix issue [super viewWillAppear:animated]; [self.tableview reloadData]; } |
一直在为初学者寻找一个关于这个主题的好教程,在这里找到了最好的教程。
在教程底部的
1 | @property (nonatomic, retain) id backgroundTapDelegate; |
如你所见。
使用这个第三方你甚至不需要写一行
https://github.com/hackiftekhar/iqkeyboardmanager
下载项目并在项目中拖放iqkeyboardManager。如果您发现任何问题,请阅读自述文件。
伙计们管理键盘真的很头疼。
谢谢,祝你好运!
注意:此答案假设您的文本字段在滚动视图中。
我更喜欢使用ScrollContentInset和ScrollContentOffset来处理这个问题,而不是处理视图的框架。
首先,让我们听一下键盘通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //call this from viewWillAppear -(void)addKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } //call this from viewWillDisappear -(void)removeKeyboardNotifications{ [[NSNotificationCenter default Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } |
下一步是保留表示当前第一响应程序的属性(当前具有键盘的uitextfield/uitextview)。
我们使用委托方法来设置这个属性。如果您正在使用另一个组件,则需要类似的东西。
注意,对于textfield,我们将其设置为didbeginediting,对于textview设置为shouldbeginediting。这是因为出于某种原因,在uikeyboardwillshownotification之后调用了textviewdidbginediting。
1 2 3 4 5 6 7 8 | -(BOOL)textViewShouldBeginEditing:(UITextView * )textView{ self.currentFirstResponder = textView; return YES; } -(void)textFieldDidBeginEditing:(UITextField *)textField{ self.currentFirstResponder = textField; } |
最后,这是魔法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | - (void)keyboardWillShow:(NSNotification*)aNotification{ NSDictionary* info = [aNotification userInfo]; CGRect kbFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/ if(self.currentFirstResponder){ //keyboard origin in currentFirstResponderFrame CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.origin fromView:nil]; float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y); //only scroll the scrollview if keyboard overlays the first responder if(spaceBetweenFirstResponderAndKeyboard>0){ //if i call setContentOffset:animate:YES it behaves differently, not sure why [UIView animateWithDuration:0.25 animations:^{ [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)]; }]; } } //set bottom inset to the keyboard height so you can still scroll the whole content UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0); _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; } - (void)keyboardWillHide:(NSNotification*)aNotification{ UIEdgeInsets contentInsets = UIEdgeInsetsZero; _scrollView.contentInset = contentInsets; _scrollView.scrollIndicatorInsets = contentInsets; } |
这就是使用swift的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import UIKit class ExampleViewController: UIViewController, UITextFieldDelegate { @IBOutlet var scrollView: UIScrollView! @IBOutlet var textField1: UITextField! @IBOutlet var textField2: UITextField! @IBOutlet var textField3: UITextField! @IBOutlet var textField4: UITextField! @IBOutlet var textField5: UITextField! var activeTextField: UITextField! // MARK: - View override func viewDidLoad() { super.viewDidLoad() self.textField1.delegate = self self.textField2.delegate = self self.textField3.delegate = self self.textField4.delegate = self self.textField5.delegate = self } override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) self.registerForKeyboardNotifications() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) self.unregisterFromKeyboardNotifications() } // MARK: - Keyboard // Call this method somewhere in your view controller setup code. func registerForKeyboardNotifications() { let center: NSNotificationCenter = NSNotificationCenter.defaultCenter() center.addObserver(self, selector:"keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil) center.addObserver(self, selector:"keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil) } func unregisterFromKeyboardNotifications () { let center: NSNotificationCenter = NSNotificationCenter.defaultCenter() center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil) center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } // Called when the UIKeyboardDidShowNotification is sent. func keyboardWasShown (notification: NSNotification) { let info : NSDictionary = notification.userInfo! let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size let contentInsets: UIEdgeInsets = 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 app might not need or want this behavior. var aRect = self.view.frame aRect.size.height -= kbSize.height; if (!CGRectContainsPoint(aRect, self.activeTextField.frame.origin) ) { self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true) } } // Called when the UIKeyboardWillHideNotification is sent func keyboardWillBeHidden (notification: NSNotification) { let contentInsets = UIEdgeInsetsZero; scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } // MARK: - Text Field func textFieldDidBeginEditing(textField: UITextField) { self.activeTextField = textField } func textFieldDidEndEditing(textField: UITextField) { self.activeTextField = nil } } |
斯威夫特2:
添加一个uiscrollview并在其顶部添加文本字段。将故事板引用到VC。
1 2 3 | @IBOutlet weak var username: UITextField! @IBOutlet weak var password: UITextField! @IBOutlet weak var scrollView: UIScrollView! |
添加以下方法:uiExtFieldDelegate&uiScrollViewDelegate。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | //MARK:- TEXTFIELD METHODS func textFieldShouldReturn(textField: UITextField) -> Bool { if(username.returnKeyType == UIReturnKeyType.Default) { password.becomeFirstResponder() } textField.resignFirstResponder() return true } func textFieldDidBeginEditing(textField: UITextField) { dispatch_async(dispatch_get_main_queue()) { let scrollPoint:CGPoint = CGPointMake(0,textField.frame.origin.y/4) self.scrollView!.setContentOffset(scrollPoint, animated: true); } } func textFieldShouldEndEditing(textField: UITextField) -> Bool { dispatch_async(dispatch_get_main_queue()) { UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) }) } return true } override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { self.view.endEditing(true) } func scrollViewWillBeginDragging(scrollView: UIScrollView) { self.scrollView.scrollEnabled = true dispatch_async(dispatch_get_main_queue()) { UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) }) } } |
您需要使用特定的帧大小以编程方式添加滚动视图。必须在.h文件中添加uiscrollviewdelegate。必须启用ScrollView才能在viewdidLoad()中写入以下内容。
1 2 3 4 5 6 7 | scrollview.scrollEnabled=YES; scrollview.delegate=self; scrollview.frame = CGRectMake(x,y,width,height); //---set the content size of the scroll view--- [scrollview setContentSize:CGSizeMake(height,width)]; |
通过这种方式,您可以添加X、Y、宽度和高度值。我想这对你有帮助。
试试这个:
1 2 3 4 5 6 7 | -(void)textFieldDidBeginEditing:(UITextField *)sender { if ([sender isEqual:self.m_Sp_Contact]) { [self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES]; } } |
我认为,如果您使用的是Swift,那么最好的方法是使用面向协议的编程。
首先,您必须创建一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import Foundation import UIKit protocol KeyboardCapable: KeyboardAnimatable { func keyboardWillShow(notification: NSNotification) func keyboardWillHide(notification: NSNotification) } extension KeyboardCapable where Self: UIViewController { func registerKeyboardNotifications() { NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil) } func unregisterKeyboardNotifications() { NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } } |
您已经注意到上面这段代码上的外来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import Foundation import UIKit protocol KeyboardAnimatable { } extension KeyboardAnimatable where Self: UIViewController { func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) { UIView.animateWithDuration(duration, animations: { () -> Void in self.view.frame = CGRectMake(view.frame.origin.x, -height, view.bounds.width, view.bounds.height) }, completion: nil) } func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) { UIView.animateWithDuration(duration, animations: { () -> Void in self.view.frame = CGRectMake(view.frame.origin.x, 0.0, view.bounds.width, view.bounds.height) }, completion: nil) } } |
这个
好的,如果
让我们来看一个符合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import Foundation import UIKit class TransferConfirmViewController: UIViewController, KeyboardCapable { //MARK: - LIFE CYCLE override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) registerKeyboardNotifications() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) unregisterKeyboardNotifications() } //MARK: - NOTIFICATIONS //MARK: Keyboard func keyboardWillShow(notification: NSNotification) { let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration) } func keyboardWillHide(notification: NSNotification) { let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double performKeyboardHideFullViewAnimation(withDuration: animationDuration) } } |
现在,您的
注意:如果您希望自定义动画而不是推或拉视图,则必须在
这是一个免费的库,用于处理iPhone应用程序中的键盘处理。您只需要编写一行代码:
1 | [AutoScroller addAutoScrollTo:scrollView]; |
在窗体中处理键盘真是太棒了
把这个添加到你的pod文件->
就是这样,处理所有的键盘,滚动视图和一切!
您不需要编写任何代码,找不到更好的解决方案!
它有一个扩展名,用于处理文本字段显示、屏幕切换、下一个和上一个箭头(如果有多个文本字段)。
它还有一个自定义完成按钮,可以删除。
链接->https://github.com/hackiftekhar/iqkeyboardmanager
一个更为优雅的解决方案是使用
这样做的好处是,构建一个执行正确操作的
幼稚的实现是重写EDOCX1(不要),更好的实现是只使用
此解决方案不需要硬编码键盘偏移量(如果它们不在拆分中,键盘偏移量会发生变化等),还意味着您的视图可能是许多其他视图的子视图,并且仍然能够正确响应。
除非没有其他解决方案,否则不要硬编码类似的东西。操作系统给你足够的信息,如果你做的对,你只需要重新聪明地画(基于你的新
干杯。
很简单,只需在类中放入以下代码,并根据需要进行定制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -(void)textFieldDidBeginEditing:(UITextField *)textField { //Show Keyboard self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-50, self.view.frame.size.width, self.view.frame.size.height); } -(void)textFieldDidEndEditing:(UITextField *)textField { // Hide keyboard self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+50, self.view.frame.size.width, self.view.frame.size.height); } |
您也可以使用textfield委托方法。检查下面的代码。在滚动视图上放置textfield时,它对我有效。
1 2 3 4 5 6 7 8 | - (void)textFieldDidBeginEditing:(UITextField *)textField { if(textField == answer) { CGPoint cPoint = textField.frame.origin; [scrollView setContentOffset:CGPointMake(0, cPoint.y - 100) animated:YES]; } } |
Note: You have to change cPoint.y - 100 value according to your view.
这里有一个uitextfield(和其他类似的字段)类别,我创建了这个类别,它将使textfield避免使用键盘,您应该能够将它按原样放到视图控制器中,并且它应该可以工作。它将整个屏幕向上移动,使当前文本字段位于键盘上方并带有动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #import"UIView+avoidKeyboard.h" #import"AppDelegate.h" @implementation UIView (avoidKeyboard) - (void) becomeFirstResponder { if(self.isFirstResponder) return; [super becomeFirstResponder]; if ([self isKindOfClass:[UISearchBar class]] || [self isKindOfClass:[UITextField class]] || [self isKindOfClass:[UITextView class]]) { AppDelegate *appDelegate = [UIApplication sharedApplication].delegate; CGRect screenBounds = appDelegate.window.frame; CGFloat keyboardHeight; CGFloat keyboardY; CGFloat viewsLowestY; CGPoint origin = [self.superview convertPoint:self.frame.origin toView:appDelegate.window]; //get this views origin in terms of the main screens bounds if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ //the window.frame doesnt take its orientation into account so if its sideways we must use the x value of the origin instead of the y keyboardHeight = 216; keyboardY = screenBounds.size.height - keyboardHeight; //find the keyboards y coord relative to how much the main window has moved up viewsLowestY = origin.y + self.frame.size.height; //find the lowest point of this view } else { keyboardHeight = 162; keyboardY = screenBounds.size.width - keyboardHeight; viewsLowestY = origin.x + self.frame.size.height; } CGFloat difference = viewsLowestY - keyboardY + 20; //find if this view overlaps with the keyboard with some padding if (difference > 0){ //move screen up if there is an overlap [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ CGRect frame = appDelegate.window.frame; if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ frame.origin.y -= difference; } else { frame.origin.x -= difference; } appDelegate.window.frame = frame; } completion:nil]; } } } //look at appDelegate to see when the keyboard is hidden @end |
在AppDelegate中添加此函数
1 2 3 4 5 6 7 8 9 10 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHides:) name:UIKeyboardWillHideNotification object:nil]; //add in didFinishLaunchingWithOptions ... - (void)keyboardHides:(NSNotification *)notification { [UIView animateWithDuration:0.3 animations:^{ [window setFrame: CGRectMake(0, 0, window.frame.size.width, window.frame.size.height)]; } completion:nil]; } |
有很多答案可以告诉我们这个方法。我采用了同样的方法,但是实现不好。
这是基本的想法。我修改了键盘显示方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | { // Obtain keyboard Info NSDictionary* info = [notification userInfo]; CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; keyboardRect = [self.view convertRect:keyboardRect fromView:nil]; // Obtain ScrollView Info w.r.t. top View CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil]; // Depending upon your screen Ui, Scroll View's bottom edge might be at some offset from screen's bottom // Calculate the exact offset int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.origin.y + scrollViewRect.size.height); int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset; // We may also need to consider the Insets if already present with ScrollView. Let's keep it simple for now // But we should store these, so that we can restore the Insets when Keyboard is gone // origInsets = self.scrollView.contentInset; // Set the new Insets for ScrollView UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0); self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; // Visible frame (not overlapped by Keyboard) CGRect visibleFrame = self.view.frame; visibleFrame.size.height -= keyboardRect.size.height; // Get the Rect for Textfield w.r.t self.view CGRect activeFieldFrame = self.activeField.frame; activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView]; // Check if the TextField is Visible or not if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) { // Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View [self.scrollView scrollRectToVisible:self.activeField.frame animated:YES]; } |
}
并添加此方法以初始化ActiveField
1 2 3 4 | - (IBAction)textFieldDidBeginEditing:(UITextField *)sender { self.activeField = sender; } |
https://github.com/michaeltyson/tpkeyboardavailing下载此文件并在表视图中添加自定义类,它将管理所有内容,因为您不需要做任何事情。它有很多选择,你也可以选择其他的,这是你所需要避免的键盘。
以下是我使用自动布局的版本:
其想法只是将包含文本字段/文本视图的视图嵌入到uiscrollview中,从底部设置一个约束到它的超级视图,创建一个出口,并使用通知根据键盘高度更新它的常量。这是基于这里的苹果示例,以及在uiscrollview上使用autolayout的苹果技术说明。
1)将视图v嵌入uiscroll视图中:如果已经设置了常量和子视图,则可以将视图和子视图复制/粘贴到视图控制器的视图中,然后使用"编辑器"->"嵌入"菜单将其嵌入,最后删除复制的视图。)
2)设置以下约束:
- S到顶部布局参考线:0
- s到底部布局参考线:0
- S导致SuperView:0
s跟踪到SuperView:0
V顶部空间到SuperView:0
- v底部空间到SuperView:0
- v从尾随空格到超视图:0
V超视距:0
v等于s的宽度
最新的底部v子视图到超级视图:20
3)创建从最新约束到视图控制器的出口
4)使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpaceToContentView; // ... - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. // ... [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Handle keyboard // Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification { NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; self.bottomSpaceToContentView.constant = kBottomMargin + kbSize.height; [self.view layoutIfNeeded]; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { self.bottomSpaceToContentView.constant = kBottomMargin; [self.view layoutIfNeeded]; } |
还有Tadaaaa,它工作了!
这是独立于设备的偏移计算。获取键盘和文本字段之间的重叠高度:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | func keyboardShown(notification: NSNotification) { let info = notification.userInfo! let value: AnyObject = info[UIKeyboardFrameEndUserInfoKey]! let rawFrame = value.CGRectValue let keyboardFrame = view.convertRect(rawFrame, fromView: nil) let screenHeight = UIScreen.mainScreen().bounds.size.height; let Ylimit = screenHeight - keyboardFrame.size.height let textboxOriginInSuperview:CGPoint = self.view.convertPoint(CGPointZero, fromCoordinateSpace: lastTextField!) self.keyboardHeight = (textboxOriginInSuperview.y+self.lastTextField!.frame.size.height) - Ylimit if(self.keyboardHeight>0){ self.animateViewMoving(true, moveValue: keyboardHeight!) }else{ keyboardHeight=0 } } |
键盘高度是偏移量。
我最近发现自己在使用一个消息应用程序时也遇到了类似的情况。我创建了一个自定义的uiview,它可以贴在键盘的顶部,自动完成大部分需要的操作。
消息组合视图
http://www.thegameengine.org/wp-content/uploads/2013/11/message_composer_quad_1.jpg
这个项目背后的想法是创建一个类似于IMessage合成视图的功能,即:
- 当键盘关闭时,会一直停留在键盘顶部并移动到屏幕底部。
- 处理文本更改
- 处理旋转
要调整/重新配置uiscrollview,您需要使用以下可选委托方法:
它将在帧更改(调整大小、重新定位、旋转)时调用,并提供动画持续时间。您可以根据需要使用此信息调整uiscrollview的框架和内容插入的大小。
和苹果一样,一个更简单但更通用的方法是考虑键盘的高度,当我们在键盘上使用自定义工具栏时,这是非常有用的。尽管苹果在这方面的做法没有什么问题。
这是我的方法(稍微修改一下苹果的方法)——
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // UIKeyboardDidShowNotification - (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); self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; } // UIKeyboardWillHideNotification - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; } |
请遵循这些步骤。
1)在.h文件中声明以下变量。
1 2 3 | { CGFloat animatedDistance; } |
2)在.m文件中声明以下常量。
1 2 3 4 5 | static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3; static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2; static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8; static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216; static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162; |
3)使用uitextfield delegate向上/向下移动键盘。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | -(void) textFieldDidBeginEditing:(UITextField *)textField { if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField]; CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view]; CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height; CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height; CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height; CGFloat heightFraction = numerator / denominator; if (heightFraction < 0.0) { heightFraction = 0.0; } else if (heightFraction > 1.0) { heightFraction = 1.0; } UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; if (orientation == UIInterfaceOrientationPortrait) { animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction); } else { animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction); } CGRect viewFrame = self.view.frame; viewFrame.origin.y -= animatedDistance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrame]; [UIView commitAnimations]; } } -(void) textFieldDidEndEditing:(UITextField *)textField { if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone) { CGRect viewFrame = self.view.frame; viewFrame.origin.y += animatedDistance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrame]; [UIView commitAnimations]; } } |
我发现这是最好的解决方案,请遵循以下代码:
将下面的内容附加到您的
1 | @property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst; |
第二,添加键盘通知的观察者。
1 2 3 4 | - (void)observeKeyboard { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } |
把这个加到你的EDOCX1[1]
1 | [self observeKeyboard]; |
最后是处理键盘更改的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | - (void)keyboardWillShow:(NSNotification *)notification { //THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS. kbHeight = 0; height = 0; self.textViewBottomConst.constant = height; self.btnViewBottomConst.constant = height; NSDictionary *info = [notification userInfo]; NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey]; NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; CGRect keyboardFrame = [kbFrame CGRectValue]; CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window]; int kbHeight = finalKeyboardFrame.size.height; int height = kbHeight + self.textViewBottomConst.constant; self.textViewBottomConst.constant = height; [UIView animateWithDuration:animationDuration animations:^{ [self.view layoutIfNeeded]; }]; } - (void)keyboardWillHide:(NSNotification *)notification { NSDictionary *info = [notification userInfo]; NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; self.textViewBottomConst.constant = 10; [UIView animateWithDuration:animationDuration animations:^{ [self.view layoutIfNeeded]; }]; } |
我把所有东西都包在一个班级里。加载ViewController时,只需调用这些代码行:
1 2 3 4 5 | - (void)viewDidLoad { [super viewDidLoad]; KeyboardInsetScrollView *injectView = [[KeyboardInsetScrollView alloc] init]; [injectView injectToView:self.view withRootView:self.view]; } |
下面是示例项目的链接:https://github.com/caouuloc/keyboardinsetcrollview
我知道这太晚了,但我想和未来的游客分享,尤其是我的方式。很多好的方法都被共享了,但我不喜欢UI是如何变得完全糟糕的。有一个简单的方法包括两部分:
我知道这看起来很简单,但它确实是有效和整洁的。
扩展uiviewController的简单解决方案
https://github.com/damienromito/visibleformview控制器
这里有很多答案,但这很有效,而且比大多数答案要短得多:
1 2 3 4 5 6 7 8 | - (void)textFieldDidBeginEditing:(UITextField *)sender { UIScrollView *scrollView = (UIScrollView *)self.view; // assuming this method is pasted into the UIScrollView's controller const double dontHardcodeTheKeyboardHeight = 162; double textY = [sender convertPoint:CGPointMake(0, 0) toView:scrollView].y; if (textY - scrollView.contentOffset.y + sender.frame.size.height > self.view.frame.size.height - dontHardcodeTheKeyboardHeight) [scrollView setContentOffset:CGPointMake(0.0, textY - 10) animated:YES]; } |
在视图中设置滚动视图
1 2 3 4 5 6 7 8 9 10 11 12 | - (void)textFieldDidBeginEditing:(UITextField *)textField { CGPoint point; if(textField == txtEmail){ // -90 is for my you can change as per your postion point = CGPointMake(0, textField.frame.origin.y - 90); } else if (textField == txtContact){ point = CGPointMake(0, textField.frame.origin.y - 90); } [scrollV setContentOffset:point animated:YES]; } |
这段代码将根据键盘高度和文本字段的深度计算需要向上移动的程度。记住在头部添加委托并继承UItextfieldDelegate。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [_tbxUsername resignFirstResponder]; [_tbxPassword resignFirstResponder]; } - (void)textFieldDidBeginEditing:(UITextField *) textField { [self animateTextField:textField up:YES]; } - (void)textFieldDidEndEditing:(UITextField *) textField { [self animateTextField:textField up:NO]; } - (void) animateTextField: (UITextField*) textField up: (BOOL) up { int animatedDistance; int moveUpValue = textField.frame.origin.y+ textField.frame.size.height; UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { animatedDistance = 236-(460-moveUpValue-5); } else { animatedDistance = 182-(320-moveUpValue-5); } if(animatedDistance>0) { const int movementDistance = animatedDistance; const float movementDuration = 0.3f; int movement = (up ? -movementDistance : movementDistance); [UIView beginAnimations: nil context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; } } |
委托以在VIEWDIDLOAD处添加
1 2 | _tbxUsername.delegate = self; _tbxPassword.delegate = self; |
尝试iqkeyboard库。
这将自动向上移动文本字段。
刚刚找到这个类:
https://github.com/oliverleter/slscrollview键盘支持
到目前为止,它在iPhone上运行得非常好,包括动画和正确的偏移量。
要使用它,只需添加到EDOCX1[24]
1 | self.support = [[SLScrollViewKeyboardSupport alloc] initWithScrollView:self.scrollView]; |
- 如果文本字段未完全或部分隐藏,则不应更改任何内容。
我们应该计算出隐藏的确切的交叉区域(键盘的框架和文本字段的框架),然后我们应该更改视图的框架。
这里我举一个完整的例子。
声明3变量
#define PADDING 10
1
2
3
4
5 @interface PKViewController ()
@property (nonatomic, assign) CGRect originalViewFrame; //original view's frame
@property (nonatomic, strong) UITextField *activeTextField; // current text field
@property (nonatomic, assign) CGRect keyBoardRect; // covered area by keaboard
@end
存储原始帧
1 2 3 4 | - (void)viewDidLoad { [super viewDidLoad]; _originalViewFrame = self.view.frame; } |
添加视图控制器作为键盘通知的观察者
1 2 3 4 5 6 7 8 9 10 11 | - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } |
删除观测器
1 2 3 4 | - (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } |
当键盘出现时存储键盘覆盖的区域,当键盘消失时将其设置为cDirectZero。
1 2 3 4 5 6 7 8 9 10 | - (void)keyboardWasShown:(NSNotification *)notification{ CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; _keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height); [self moveTextFieldUP]; } - (void) keyboardWillHide:(NSNotification *)notification{ _keyBoardRect = CGRectZero; [self setDefaultFrame]; } |
存储活动文本字段
1 2 3 4 5 6 7 8 9 10 11 12 | - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { _activeTextField = textField; //When keyboard is already present but the textfield is hidden. Case:When return key of keyboard makes the next textfield as first responder if (!CGRectIsEmpty(_keyBoardRect)) { [self moveTextFieldUP]; } return YES; } - (BOOL)textFieldShouldReturn:(UITextField *)textField{ [textField resignFirstResponder]; return YES; } |
现在我们应该改变视图的框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | - (void)moveTextFieldUP{ CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.origin.y, _activeTextField.frame.size.width, _activeTextField.frame.origin.y+_activeTextField.frame.size.height); if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) { CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect); CGFloat newY = _originalViewFrame.origin.y - intersectRect.size.height; CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height; CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING); [UIView animateWithDuration:0.3 animations:^{ [self.view setFrame:newFrame]; }]; NSLog(@"Intersect"); } } - (void)setDefaultFrame { [UIView animateWithDuration:0.3 animations:^{ [self.view setFrame:_originalViewFrame]; }]; } |
这可以通过使用约束的下面几行代码来简单实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)keyboardWillShow:(NSNotification *)notification { [self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]]; } - (void)keyboardWillHide:(NSNotification *)notification { [self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]]; } - (void)viewDidDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super viewDidDisappear:animated]; } - (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info { CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGFloat height = keyboardFrame.size.height; self.constraintToAdjust.constant = height; UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]; UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState; if (animationCurve == UIViewAnimationCurveEaseIn) { animationOptions |= UIViewAnimationOptionCurveEaseIn; } else if (animationCurve == UIViewAnimationCurveEaseInOut) { animationOptions |= UIViewAnimationOptionCurveEaseInOut; } else if (animationCurve == UIViewAnimationCurveEaseOut) { animationOptions |= UIViewAnimationOptionCurveEaseOut; } else if (animationCurve == UIViewAnimationCurveLinear) { animationOptions |= UIViewAnimationOptionCurveLinear; } [UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{ [self.view layoutIfNeeded]; } completion:nil]; } |
如果该textfield在表的单元格中(即使table.scrollable=no),也可以轻松地自动完成。
- 注意:桌子的位置和尺寸必须合理。例如:
- 如果从视图底部开始计算表的Y位置为100,则300高度键盘将覆盖整个表。
- 如果表的高度=10,并且当键盘出现时必须向上滚动文本字段100才能可见,则该文本字段将超出表的界限。
在视图控制器上:
1 2 3 4 5 6 7 8 | @IBOutlet weak var usernameTextfield: UITextField! @IBOutlet weak var passwordTextfield: UITextField! @IBOutlet weak var loginScrollView: UIScrollView! override func viewWillAppear(animated: Bool) { loginScrollView.scrollEnabled = false } |
添加textfield委托。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //MARK:- TEXTFIELD METHODS func textFieldShouldReturn(textField: UITextField) -> Bool { if (usernameTextfield.resignFirstResponder()) { passwordTextfield.becomeFirstResponder() } textField.resignFirstResponder(); loginScrollView!.setContentOffset(CGPoint.zero, animated: true); loginScrollView.scrollEnabled = false return true } func textFieldDidBeginEditing(textField: UITextField) { loginScrollView.scrollEnabled = true if (textField.tag == 1 && (device =="iPhone" || device =="iPhone Simulator" || device =="iPod touch")) { let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.4); loginScrollView!.setContentOffset(scrollPoint, animated: true); } else if (textField.tag == 2 && (device =="iPhone" || device =="iPhone Simulator" || device =="iPod touch")) { let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.origin.y/6.0); loginScrollView!.setContentOffset(scrollPoint, animated: true); } } func textFieldDidEndEditing(textField: UITextField) { loginScrollView!.setContentOffset(CGPointZero,animated: true); } |
非常轻的解决方案可以使用键盘动画。
项目得到了示例实现,文档还在进行中…
适当使用:它有一个针对uitextfield&uitextview的特定实现
局限性:它完全在Objective-C上,很快就会有Swift版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | -(BOOL) textFieldShouldBeginEditing:(UITextField *)textField { [self slideUp]; return YES; } -(BOOL) textFieldShouldEndEditing:(UITextField *)textField { [self slideDown]; return YES; } #pragma mark - Slide Up and Down animation - (void) slideUp { [UIView beginAnimations:nil context:nil]; layoutView.frame = CGRectMake(0.0, -70.0, layoutView.frame.size.width, layoutView.frame.size.height); [UIView commitAnimations]; } - (void) slideDown { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDelay: 0.01]; layoutView.frame = CGRectMake(0.0, 0.0, layoutView.frame.size.width, layoutView.frame.size.height); [UIView commitAnimations]; } |
虽然这条线索有足够的答案,但我想提出一个更简单但更全面的方法,就像苹果公司一样,将键盘的高度考虑在内,这在我们使用键盘上的自定义工具栏时非常有用。尽管苹果在这方面的做法没有什么问题。
这是我的方法(稍微修改一下苹果的方法)——
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Called when the UIKeyboardDidShowNotification is sent. - (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); self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification { UIEdgeInsets contentInsets = UIEdgeInsetsZero; self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; } |
请在文本字段Delegate方法中添加这些行,以便在iPad中向上滚动。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | - (void)textFieldDidBeginEditing:(UITextField *)textField { activeTextfield = textField; CGPoint pt; CGRect rc = [textField bounds]; rc = [textField convertRect:rc toView:scrlView]; pt = rc.origin; pt.x = 0; pt.y -= 100; [scrlView setContentOffset:pt animated:YES]; scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.origin.y+button.frame.size.height + 8 + 370); } |
我想扩大@sumanthkodi的回答。
正如一些人所说,他的方法在较新的实现中不起作用,因为当您使用约束时,uiview无法移动。
我将代码编辑如下(并移植到Swift2.0),希望它能帮助一些人:
1)参考要向上移动的视图的垂直约束:
1 | @IBOutlet var viewConstraint: NSLayoutConstraint! |
确保在故事板中使用约束引用这个var。
2)添加委托并实现侦听器。这与以前的实现相同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class YourViewController: UIViewController, UITextFieldDelegate { ... func textFieldDidBeginEditing(textField: UITextField) { animateTextField(textField, up: true) } func textFieldDidEndEditing(textField: UITextField) { animateTextField(textField, up: false) } ... } |
3)将动画方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | func animateTextField(textfield: UITextField, up: Bool) { let originalConstraint = 50 let temporaryConstraint = 0 let movementDuration = 0.3 let constraint = CGFloat(up ? temporaryConstraint : originalConstraint) containerViewConstraint.constant = constraint UIView.animateWithDuration(movementDuration) { self.view.layoutIfNeeded() } } |
这会很好地工作。滚动视图会根据文本框位置自动调整。我相信你会感觉很好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.25; static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2; static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8; static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216; static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162; @interface LoginVC () { CGFloat animatedDistance; CGRect viewFrameKey; } //In ViewDidLoad viewFrameKey=self.view.frame; - (void)textFieldDidBeginEditing:(UITextField *)textField { CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField]; CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view]; CGFloat midline = textFieldRect.origin.y + 0.5 * textFieldRect.size.height; CGFloat numerator = midline - viewRect.origin.y - MINIMUM_SCROLL_FRACTION * viewRect.size.height; CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION) * viewRect.size.height; CGFloat heightFraction = numerator / denominator; if (heightFraction < 0.0) { heightFraction = 0.0; } else if (heightFraction > 1.0) { heightFraction = 1.0; } UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) { animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction); } else { animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction); } CGRect viewFrame = self.view.frame; viewFrame.origin.y -= animatedDistance; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrame]; [UIView commitAnimations]; } - (void)textFieldDidEndEditing:(UITextField *)textField { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION]; [self.view setFrame:viewFrameKey]; [UIView commitAnimations]; } |
简单的解决方案和最新的动画API。更改原点Y到215,您可以将其自定义为适合您的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | - (void)textFieldDidBeginEditing:(UITextField *)textField { if (self.view.frame.origin.y >= 0) { [UIView animateWithDuration:0.5 animations:^{ self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-215, self.view.frame.size.width, self.view.frame.size.height); }]; } } - (void)textFieldDidEndEditing:(UITextField *)textField { if (self.view.frame.origin.y < 0) { [UIView animateWithDuration:0.5 animations:^{ self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+215, self.view.frame.size.width, self.view.frame.size.height); }]; } } |
下面是带文本字段的滚动视图的简单解决方案,不需要任何约束或活动文本字段等…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | override func viewWillAppear(_ animated: Bool){ super.viewWillAppear(animated) registerForKeyboardNotifications(); } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) deregisterFromKeyboardNotifications(); } //MARK:- KEYBOARD DELEGATE METHODS func registerForKeyboardNotifications(){ //Adding notifies on keyboard appearing NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func deregisterFromKeyboardNotifications(){ //Removing notifies on keyboard appearing NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func keyboardWasShown(notification: NSNotification){ var info = notification.userInfo! let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size var contentInset:UIEdgeInsets = self.scrRegister.contentInset contentInset.bottom = (keyboardSize?.height)! scrRegister.contentInset = contentInset } func keyboardWillBeHidden(notification: NSNotification) { var contentInset:UIEdgeInsets = self.scrRegister.contentInset contentInset.bottom = 0 scrRegister.contentInset = contentInset } |
请遵循这些步骤,可能会有所帮助。放置一个视图,然后将文本字段放在该视图上,并在键盘打开时通过委托检测事件,此时立即向上动画视图(您也可以为该视图指定一些位置),然后视图将向上移动到该位置。同样,对向下动画视图执行相同的操作。
谢谢
Apples键盘管理代码的Swift 3.0版本如下:下面代码中使用的floatingtf是iOS中基于材质设计的文本字段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | import UIKit class SignupViewController: UIViewController, UITextFieldDelegate { //MARK: - IBOutlet: @IBOutlet weak var emailTF: FloatingTF! @IBOutlet weak var passwordTF: FloatingTF! @IBOutlet weak var dobTF: FloatingTF! @IBOutlet weak var scrollView: UIScrollView! //MARK: - Variable: var activeTextField: UITextField! //MARK: - ViewController Lifecycle: override func viewDidLoad() { super.viewDidLoad() emailTF.delegate = self passwordTF.delegate = self dobTF.delegate = self } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) registerKeyboardNotifications() } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) deRegisterKeyboardNotifications() } //MARK: - Keyboard notification observer Methods fileprivate func registerKeyboardNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } fileprivate func deRegisterKeyboardNotifications() { NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: self.view.window) NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: self.view.window) } func keyboardWillShow(notification: NSNotification) { let info: NSDictionary = notification.userInfo! as NSDictionary let value: NSValue = info.value(forKey: UIKeyboardFrameBeginUserInfoKey) as! NSValue let keyboardSize: CGSize = value.cgRectValue.size let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0) scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets // If active text field is hidden by keyboard, scroll it so it's visible // Your app might not need or want this behavior. var aRect: CGRect = self.view.frame aRect.size.height -= keyboardSize.height let activeTextFieldRect: CGRect? = activeTextField?.frame let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin if (!aRect.contains(activeTextFieldOrigin!)) { scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true) } } func keyboardWillHide(notification: NSNotification) { let contentInsets: UIEdgeInsets = .zero scrollView.contentInset = contentInsets scrollView.scrollIndicatorInsets = contentInsets } //MARK: - UITextField Delegate Methods func textFieldShouldReturn(_ textField: UITextField) -> Bool { if textField == emailTF { passwordTF.becomeFirstResponder() } else if textField == passwordTF { dobTF.becomeFirstResponder() } else { self.view.endEditing(true) } return true } func textFieldDidBeginEditing(_ textField: UITextField) { activeTextField = textField scrollView.isScrollEnabled = true } func textFieldDidEndEditing(_ textField: UITextField) { activeTextField = nil scrollView.isScrollEnabled = false } } |
其简单:
在textfieldDidbeginediting中:
1 | self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-150, self.view.frame.size.width, self.view.frame.size.height); |
在文本字段中应指定:
1 | self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+150, self.view.frame.size.width, self.view.frame.size.height); |
使用iqKeyboardManager,出现键盘时,uitextfield和uitextview会自动滚动。Git链接:https://github.com/hackiftekhar/iqkeyboardmanager。
豆荚:pod‘iqkeyboardmanager’ios8及更高版本
pod‘iqkeyboardmanager’,‘3.3.7’ios7
这个问题已经有很多答案了,有的说要使用滚动视图,有的说要使用第三个lib。
但对我来说,解决方案应该是使用静态细胞的
您将用户界面分成多个部分,并将它们逐个放到TableViewCells中,而不再需要担心键盘,TableViewController将自动为您管理它。
计算填充、边距、单元格高度可能有点困难,但如果您的数学计算正确,就很简单了。
我们可以为Swift 4.1用户提供代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | let keyBoardSize = 80.0 func keyboardWillShow() { if view.frame.origin.y >= 0 { viewMovedUp = true } else if view.frame.origin.y < 0 { viewMovedUp = false } } func keyboardWillHide() { if view.frame.origin.y >= 0 { viewMovedUp = true } else if view.frame.origin.y < 0 { viewMovedUp = false } } func textFieldDidBeginEditing(_ textField: UITextField) { if sender.isEqual(mailTf) { //move the main view, so that the keyboard does not hide it. if view.frame.origin.y >= 0 { viewMovedUp = true } } } func setViewMovedUp(_ movedUp: Bool) { UIView.beginAnimations(nil, context: nil) UIView.setAnimationDuration(0.3) // if you want to slide up the view let rect: CGRect = view.frame if movedUp { rect.origin.y -= keyBoardSize rect.size.height += keyBoardSize } else { // revert back to the normal state. rect.origin.y += keyBoardSize rect.size.height -= keyBoardSize } view.frame = rect UIView.commitAnimations() } func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil) } func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil) NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) } |
加上我的5美分:)
我总是喜欢将TableView用于InputExtField或ScrollView。结合通知,您可以轻松地管理此类行为。(注意,如果在TableView中使用静态单元格,这些行为将自动为您管理。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | // MARK: - Notifications fileprivate func registerNotificaitions() { NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } fileprivate func unregisterNotifications() { NotificationCenter.default.removeObserver(self) } @objc fileprivate func keyboardWillAppear(_ notification: Notification) { if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height { view.layoutIfNeeded() UIView.animate(withDuration: 0.3, animations: { let heightInset = keyboardHeight - self.addDeviceButton.frame.height self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0) self.view.layoutIfNeeded() }, completion: nil) } } @objc fileprivate func keyboardWillDisappear() { view.layoutIfNeeded() UIView.animate(withDuration: 0.3, animations: { self.tableView.contentInset = UIEdgeInsets.zero self.view.layoutIfNeeded() }, completion: nil) } |
参见
如果文本字段应该在屏幕的底部,那么最神奇的解决方案是在您的视图控制器上进行以下覆盖:
1 2 3 | override var inputAccessoryView: UIView? { return <yourTextField> } |
您可以使用这个简单的Git存储库:https://github.com/hackiftekhar/iqkeyboardmanager
这是一个自动管理字段移动的库。
根据他们的自述,集成非常简单:
without needing you to enter any code and no additional setup required. To use IQKeyboardManager you simply need to add source files to your project
虽然,这是一个非常好的控件,但在某些情况下,它会导致冲突,就像在带有滚动视图的视图控制器中一样。它有时会更改内容大小。尽管如此,你还是可以去尝试,并根据你的要求尝试,也许你可以做我错过的事情。
我有点晚了。您应该在视图控制器上添加滚动视图。
您必须实现低于2的方法。
textfield委托方法。
1 2 3 | - (void)textFieldDidBeginEditing:(UIView *)textField { [self scrollViewForTextField:reEnterPINTextField]; } |
然后在委托方法中调用下面的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | - (void)scrollViewForTextField:(UIView *)textField { NSInteger keyboardHeight = KEYBOARD_HEIGHT; if ([textField UITextField.class]) { keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height; } CGRect screenFrame = [UIScreen mainScreen].bounds; CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)}; aRect.size.height -= keyboardHeight; CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField]; CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height); if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) { CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height); [contentSlidingView setContentOffset:scrollPoint animated:YES]; } } |
在iOS中,向上移动键盘和在应用程序中返回文本字段有点让人困惑,需要实现几个相同的方法。此外,您还需要委托给textfield并处理它。它的代码将在每个存在文本字段的类中重复。
我更喜欢使用这个Github控件。
IQ键盘
在哪儿我们什么都不需要做。--只需将拖放控件拖到项目和生成中即可。--它将为你的应用程序做一切。
谢谢
也许这会有用。
这对我很有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | func setupKeyboardNotifications() { NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWasShown:"), name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillBeHidden:"), name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(aNotification:NSNotification) { let info = aNotification.userInfo let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue let kbSize = infoNSValue.CGRectValue().size UIView.beginAnimations(nil, context: nil) UIView.setAnimationDuration(0.3) var rect : CGRect = self.view.frame rect.size.height -= kbSize.height self.view.frame = rect UIView.commitAnimations() } func keyboardWillBeHidden(aNotification:NSNotification) { let info = aNotification.userInfo let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue let kbSize = infoNSValue.CGRectValue().size UIView.beginAnimations(nil, context: nil) UIView.setAnimationDuration(0.3) var rect : CGRect = self.view.frame rect.size.height += kbSize.height self.view.frame = rect UIView.commitAnimations() } |
我使用Swift和Auto-layout(但不能对之前的Swift答案发表评论);以下是我在没有滚动视图的情况下如何进行的操作:
我在ib中布局表单,在字段之间使用垂直约束来分隔它们。我添加了一个从最上面的字段到容器视图的垂直约束,并创建了一个出口(下面代码中的topspaceforforforforformconstraint)。所需要的就是更新这个约束,我在动画块中做的是一个很好的软动作。当然,高度检查是可选的,在这种情况下,我需要做的只是为了最小的屏幕尺寸。
这可以使用任何常用的textfieldDidbeginediting或keyboardwillshow方法调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 | func setFormHeight(top: CGFloat) { let height = UIScreen.mainScreen().bounds.size.height // restore text input fields for iPhone 4/4s if (height < 568) { UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: { self.topSpaceForFormConstraint.constant = top self.view.layoutIfNeeded() }, completion: nil) } } |
在(bool)textfield中应注册:(uitextfield*)textfield
1 2 3 4 5 6 7 8 9 10 | if (textField.frame.origin.y > self.view.frame.size.height - 216) { if (screenHeight>500) scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 100); else scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 216); CGPoint scrollPoint = CGPointMake(0.0,(textField.frame.origin.y - (self.view.frame.size.height - 216 - textField.frame.size.height - 20))); [scrollView setContentOffset:scrollPoint animated:YES]; } [scrollView setScrollEnabled:YES]; |
当退出键盘时,您需要编写以下代码
1 2 3 | scrollView.contentSize = CGSizeMake(0.0, 640); CGPoint scrollPoint = CGPointMake(0.0,0.0); [scrollView setContentOffset:scrollPoint animated:YES]; |
我发现@dk_u是我开始使用的解决方案。但是,有一种假设,即滚动视图覆盖了整个视图。我不是这样的。我只想要一个滚动视图,以防键盘覆盖了我登录屏幕上较低的文本字段。所以我的内容视图和滚动视图的大小相同,它比主视图小。
它也没有解释风景,这是我开始遇到麻烦的地方。在玩了几天之后,这是我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | - (void)keyboardWasShown:(NSNotification*)aNotification { // A lot of the inspiration for this code came from http://stackoverflow.com/a/4837510/594602 CGFloat height = 0; NSDictionary* info = [aNotification userInfo]; CGRect kbFrameRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect kbBoundsRect = [self.view convertRect:kbFrameRect fromView:nil]; // Convert frame from window to view coordinates. CGRect scrollRect = scrollView.frame; CGRect intersect = CGRectIntersection(kbBoundsRect, scrollRect); if (!CGRectIsNull(intersect)) { height = intersect.size.height; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, height, 0.0); scrollView.contentInset = contentInsets; scrollView.scrollIndicatorInsets = contentInsets; } // Figure out what the view rectangle is for the scrollView CGPoint contentOffset = scrollView.contentOffset; CGRect visibleRect = CGRectOffset(scrollRect, contentOffset.x, contentOffset.y); // I'm not 100% sure if this is needed/right. My scrollView was always at the top in testing. visibleRect.size.height -= height; CGRect activeRect = activeField.frame; if (!CGRectContainsRect(visibleRect, activeRect)) { [self.scrollView scrollRectToVisible:activeField.frame animated:YES]; } } |
我在使用自动布局时也遇到了一些困难。如果我没有正确地完成布局,我就无法得到预期的滚动。有一件事使生活变得更容易,那就是把所有要滚动到一个视图中的项目放在一个视图中,并把它作为滚动视图中唯一的项目。我把这个单一视图称为"内容视图"。
我认为关键部分是内容视图有一个设置的宽度和高度。这使得滚动视图能够确切地知道它必须处理多少内容。这与通常的布局有点背道而驰。通常情况下,视图会尽量占用空间。对于滚动视图的内容,您试图使视图尽可能地限制自己。内容视图允许您停止该操作。所以我给了我248的高度,用320的标准屏幕宽度作为我的宽度。
最终对我有用的布局是:
- 滚动视图到超级视图:基本上我对顶部、左侧和右侧进行了约束。
Horizontal Space - View - Scroll View 0Vertical Space - View - Scroll View 0Horizontal Space - Scroll View - View 0
- 滚动视图高度:我将滚动视图设置为恒定的高度。我不知道这是否真的有必要,但它有滚动视图本身的界限。
Height - (248) - Scroll View
- 滚动视图的内容视图:我给了所有边、顶部、左侧、底部和右侧常量。
Vertical Space - View - Scroll View 0Vertical Space - Scroll View - View (0)Horizontal Space - View - Scroll View 0Horizontal Space - Scroll View - View 0
- 内容视图的维度。
Height - (248) - View Width - (320) - View
我在这里没有看到这种可能性,所以我要补充一点,因为我尝试了答案中的方法,但几个小时后发现在IOS6/7中的Xcode5中有一种更简单的方法:使用nslayoutConstraints。
请参见:自动布局约束-键盘
这是我的代码:
m文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Called when the UIKeyboardWillShowNotification is sent. - (void)keyboardWillBeShown:(NSNotification*)aNotification { NSLog(@"keyboardWillBeShown:"); [self.PhoneNumberLabelOutlet setHidden:TRUE]; CGFloat heightOfLabel = self.PhoneNumberLabelOutlet.frame.size.height; for( NSLayoutConstraint* thisConstraint in self.topElementsVerticalDistanceFromTopLayoutConstraint ) { thisConstraint.constant -= heightOfLabel; } NSDictionary* info = [aNotification userInfo]; CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; CGFloat oldConstant = [self.SignInYConstraint constant]; self.SignInYConstraint.constant = oldConstant + kbSize.height; [self.view setNeedsUpdateConstraints]; NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; [UIView animateWithDuration:duration animations:^{ [self.view layoutIfNeeded]; }]; } |
h文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #import <UIKit/UIKit.h> @interface SignInViewController : UIViewController { UITextField* _activeField; } - (void)signInCallback:(NSObject*)object; @property (weak, nonatomic) IBOutlet UILabel *PhoneNumberLabelOutlet; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *ActivityIndicatorOutlet; @property (weak, nonatomic) IBOutlet UITextField *UserIDTextfieldOutlet; @property (weak, nonatomic) IBOutlet UITextField *PasswordTextfieldOutlet; @property (weak, nonatomic) IBOutlet UIButton *SignInButton; @property (weak, nonatomic) IBOutlet NSLayoutConstraint *SignInYConstraint; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *topElementsVerticalDistanceFromTopLayoutConstraint; @end |
我在更改文本字段或编辑其内容时(例如,电话文本字段和添加"-"符号,视图返回覆盖文本字段)重新设置为默认主视图时遇到问题。我最终通过使用自动布局和更改约束常量(而不是通知委托函数中的帧大小或位置)来克服此问题,如下所示:
另外,我不使用滚动视图,只使用简单的向上移动视图,但是它的工作方式应该类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | func keyboardWillShow(notification: NSNotification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { if !keyboardIsShown{ self.infoViewTopConstraint.constant -= keyboardSize.height self.infoViewBottomConstraint.constant += keyboardSize.height self.view.setNeedsLayout() self.view.layoutIfNeeded() keyboardIsShown = true } } func keyboardWillHide(notification: NSNotification) { if keyboardIsShown { self.infoViewTopConstraint.constant += keyboardSize.height self.infoViewBottomConstraint.constant -= keyboardSize.height self.view.setNeedsLayout() self.view.layoutIfNeeded() keyboardIsShown = false } |
对于Swift开发者,使用Swift 3,这里是repo https://github.com/jamesrochabrun/keyboardwillshow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | import UIKit class ViewController: UIViewController { //1 Create a view that will hold your TEXTFIELD let textField: UITextField = { let tf = UITextField() tf.translatesAutoresizingMaskIntoConstraints = false tf.layer.borderColor = UIColor.darkGray.cgColor tf.layer.borderWidth = 3.0 return tf }() //2 global variable that will hold the bottom constraint on changes var textfieldBottomAnchor: NSLayoutConstraint? override func viewDidLoad() { super.viewDidLoad() //3 add the view to your controller view.addSubview(textField) textField.heightAnchor.constraint(equalToConstant: 80).isActive = true textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor) textfieldBottomAnchor?.isActive = true setUpKeyBoardObservers() } //4 Use NSnotificationCenter to monitor the keyboard updates func setUpKeyBoardObservers() { NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } //5 toggle the bottom layout global variable based on the keyboard's height func handleKeyboardWillShow(notification: NSNotification) { let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect if let keyboardFrame = keyboardFrame { textfieldBottomAnchor?.constant = -keyboardFrame.height } let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double if let keyboardDuration = keyboardDuration { UIView.animate(withDuration: keyboardDuration, animations: { self.view.layoutIfNeeded() }) } } func handleKeyboardWillHide(notification: NSNotification) { textfieldBottomAnchor?.constant = 0 let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double if let keyboardDuration = keyboardDuration { UIView.animate(withDuration: keyboardDuration, animations: { self.view.layoutIfNeeded() }) } } //6 remove the observers override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver(self) } } |
如果你还在为此苦苦挣扎-读我的文章
我今天想出了一个解决办法。我读过很多关于这个问题的文章和"教程",但没有一篇在任何情况下都有效(大多数都是相互复制的)。即使苹果官方提出的"解决方案"也不起作用,而且更重要的是,它完全不适用于景观模式。为苹果公司不给开发者一个打败如此普遍的基本问题的方法而感到羞愧。非常不专业。如此惊人的框架(cocoa)和如此令人讨厌的被低估的问题。
现在,我的解决方案是:使uiscrollview成为您的根视图,然后将所有内容放入其中。然后从这个keyboadawareController类(您可能需要重新定义ScrollView和keyboardPadding方法)中对视图控制器进行子类化:
/ ///键盘AwareController.h/社会病/ ///由管理员于2014年1月13日创建。//版权所有(c)2014 Kuchumovn。版权所有。/ /
1 2 3 4 5 | #import <UIKit/UIKit.h> @interface KeyboardAwareController : UIViewController <UITextFieldDelegate> @end |
/ ///键盘AwareController.m/社会病/ ///由管理员于2014年1月13日创建。//版权所有(c)2014 Kuchumovn。版权所有。/ /
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | #import"KeyboardAwareController.h" @interface KeyboardAwareController () @end @implementation KeyboardAwareController { CGPoint scrollPositionBeforeKeyboardAdjustments; __weak UIScrollView* scrollView; UITextField* activeField; } - (id) initWithCoder: (NSCoder*) decoder { if (self = [super initWithCoder:decoder]) { scrollPositionBeforeKeyboardAdjustments = CGPointZero; } return self; } - (void) viewDidLoad { [super viewDidLoad]; } - (UIScrollView*) scrollView { return (UIScrollView*) self.view; } - (CGFloat) keyboardPadding { return 5; } - (void) registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil]; } - (void) deregisterFromKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } - (void) viewWillAppear: (BOOL) animated { [super viewWillAppear:animated]; [self registerForKeyboardNotifications]; } - (void) viewWillDisappear: (BOOL) animated { [self deregisterFromKeyboardNotifications]; [super viewWillDisappear:animated]; } - (void) keyboardWillShow: (NSNotification*) notification { //NSLog(@"keyboardWillShow"); // force the animation from keyboardWillBeHidden: to end scrollView.contentOffset = scrollPositionBeforeKeyboardAdjustments; scrollPositionBeforeKeyboardAdjustments = CGPointZero; } // warning: i have no idea why this thing works and what does every line of this code mean // (but it works and there is no other solution on the internets whatsoever) // P.S. Shame on Apple for missing such a basic functionality from SDK (and many other basic features we have to hack and mess around with for days and nights) - (void) keyboardDidShow: (NSNotification*) notification { //NSLog(@"keyboardDidShow"); UIWindow* window = [[[UIApplication sharedApplication] windows]objectAtIndex:0]; UIView* mainSubviewOfWindow = window.rootViewController.view; CGRect keyboardFrameIncorrect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; CGRect keyboardFrame = [mainSubviewOfWindow convertRect:keyboardFrameIncorrect fromView:window]; CGSize keyboardSize = keyboardFrame.size; CGRect visibleFrame = CGRectMake(0, 0, 0, 0); visibleFrame.origin = self.scrollView.contentOffset; visibleFrame.size = self.scrollView.bounds.size; CGFloat paddedKeyboardHeight = keyboardSize.height + self.keyboardPadding; //NSLog(@"visibleFrame %@", NSStringFromCGRect(visibleFrame)); visibleFrame.size.height -= paddedKeyboardHeight; //NSLog(@"visibleFrame after keyboard height %@", NSStringFromCGRect(visibleFrame)); if (CGRectContainsPoint(visibleFrame, activeField.frame.origin)) return; scrollPositionBeforeKeyboardAdjustments = scrollView.contentOffset; UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, activeField.frame.origin.y - visibleFrame.size.height + activeField.frame.size.height, 0); contentInsets = UIEdgeInsetsMake(0.0, 0.0, paddedKeyboardHeight, 0); self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; CGSize scrollContentSize = self.scrollView.bounds.size; scrollContentSize.height += paddedKeyboardHeight; self.scrollView.contentSize = scrollContentSize; //NSLog(@"scrollView %@", NSStringFromCGRect(scrollView.frame)); //NSLog(@"activeField %@", NSStringFromCGRect(activeField.frame)); //[scrollView scrollRectToVisible:activeField.frame animated:YES]; CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y - visibleFrame.size.height + activeField.frame.size.height); //NSLog(@"scrollPoint %@", NSStringFromCGPoint(scrollPoint)); [self.scrollView setContentOffset:scrollPoint animated:YES]; } - (void) keyboardWillBeHidden: (NSNotification*) notification { //NSLog(@"keyboardWillBeHidden"); UIEdgeInsets contentInsets = UIEdgeInsetsZero; // this doesn't work when changing orientation while the keyboard is visible // because when keyboardDidShow: will be called right after this method the contentOffset will still be equal to the old value //[scrollView setContentOffset:scrollPositionBeforeKeyboardAdjustments animated:YES]; [UIView animateWithDuration:.25 animations:^ { self.scrollView.contentInset = contentInsets; self.scrollView.scrollIndicatorInsets = contentInsets; // replacement for setContentOffset:animated: self.scrollView.contentOffset = scrollPositionBeforeKeyboardAdjustments; }]; } - (void) textFieldDidBeginEditing: (UITextField*) textField { activeField = textField; } - (void) textFieldDidEndEditing: (UITextField*) textField { activeField = nil; } @end |
如果您有任何问题,我的项目将在Github上托管:https://github.com/kuchumovn/socopathy.ios网站
为了更好的解释,我还截图了:
参考文献
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import UIKit @available(tvOS, unavailable) public class KeyboardLayoutConstraint: NSLayoutConstraint { private var offset : CGFloat = 0 private var keyboardVisibleHeight : CGFloat = 0 @available(tvOS, unavailable) override public func awakeFromNib() { super.awakeFromNib() offset = constant NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } // MARK: Notification @objc func keyboardWillShowNotification(_ notification: Notification) { if let userInfo = notification.userInfo { if let frameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { let frame = frameValue.cgRectValue keyboardVisibleHeight = frame.size.height } self.updateConstant() switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { case let (.some(duration), .some(curve)): let options = UIViewAnimationOptions(rawValue: curve.uintValue) UIView.animate( withDuration: TimeInterval(duration.doubleValue), delay: 0, options: options, animations: { UIApplication.shared.keyWindow?.layoutIfNeeded() return }, completion: { finished in }) default: break } } } @objc func keyboardWillHideNotification(_ notification: NSNotification) { keyboardVisibleHeight = 0 self.updateConstant() if let userInfo = notification.userInfo { switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { case let (.some(duration), .some(curve)): let options = UIViewAnimationOptions(rawValue: curve.uintValue) UIView.animate( withDuration: TimeInterval(duration.doubleValue), delay: 0, options: options, animations: { UIApplication.shared.keyWindow?.layoutIfNeeded() return }, completion: { finished in }) default: break } } } func updateConstant() { self.constant = offset + keyboardVisibleHeight } } |
试试看,它工作得很好:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | if Firstnametxt.text =="" || Passwordtxt.text =="" || emailtxt.text =="" { if Firstnametxt.text =="" { Firstnametxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal) Firstnametxt.becomeFirstResponder() } else if Passwordtxt.text =="" { Passwordtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal) Passwordtxt.becomeFirstResponder() } else if emailtxt.text =="" { emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal) emailtxt.becomeFirstResponder() } } else { let isValidEmail:Bool = self.isValidEmail(emailtxt.text!) if isValidEmail == true { } else { emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal) emailtxt.becomeFirstResponder() } } |
首先,我建议为您的页面提供更好的设计,这样就不需要滚动您的视图。如果有许多文本字段,您仍然不必使用滚动视图,它只会使事情变得复杂。您可以在控制器原始视图的顶部添加一个容器uiview,然后将这些文本字段放到该视图上。当键盘显示或消失时,只需使用动画来移动此容器视图。