当键盘出现时,如何使UITextField向上移动?
使用iOS SDK:
我有一个带有UITextField
的UIView
, UITextField
键盘。 我需要它能够:
键盘启动后,允许滚动UIScrollView
的内容以查看其他文本字段
自动“跳转”(通过滚动)或缩短
我知道我需要一个UIScrollView
。 我试过将UIView
的类更改为UIScrollView
但我仍然无法向上或向下滚动文本框。
我是否需要UIView
和UIScrollView
? 一个人进入另一个吗?
需要执行什么才能自动滚动到活动文本字段?
理想情况下,尽可能多的组件设置将在Interface Builder中完成。 我只想编写需要它的代码。
注意:我正在使用的UIView
(或UIScrollView
)由一个tabbar( UITabBar
)提供,它需要正常运行。
编辑:我刚刚添加滚动条,当键盘出现时。 尽管不需要,但我觉得它提供了更好的界面,例如,用户可以滚动和更改文本框。
当键盘上下移动时,我改变了UIScrollView
的框架大小。 我只是简单地使用:
-(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屏幕,则只需要一个ScrollView
。 (如果您将ScrollView
添加为组件的超级视图,只是为了让TextField
在键盘出现时向上滚动,则不需要它。)
为了显示没有被键盘隐藏的textfields
,标准方法是在显示键盘时向上/向下移动具有文本字段的视图。
以下是一些示例代码:
#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];
}
我在使用由多个UITextFields
组成的UIScrollView
遇到了很多问题,其中一个或多个UITextFields
在被编辑时会被键盘遮挡。
如果您的UIScrollView
没有正确滚动,请注意以下UIScrollView
。
1)确保您的contentSize大于UIScrollView
框架大小。 理解UIScrollViews
的方法是UIScrollView
就像contentSize中定义的内容的查看窗口。 所以当为了让UIScrollview
在任何地方滚动时,contentSize必须大于UIScrollView
。 否则,由于contentSize中定义的所有内容都已经可见,因此不需要滚动。 顺便说一句,默认contentSize = CGSizeZero
。
2)现在你明白了UIScrollView
真的是你的“内容”的窗口,确保键盘不会遮挡你的UIScrollView's
查看“窗口”的方法是调整UIScrollView
大小,这样当键盘出现时,你将UIScrollView
窗口调整为原来的UIScrollView
frame.size.height减去键盘的高度。 这将确保您的窗户只有那个小的可视区域。
3)这里有一个问题:当我第一次实现这个时,我想我必须得到已编辑文本字段的CGRect
并调用UIScrollView's
scrollRecToVisible方法。 我通过调用scrollRecToVisible
方法实现了UITextFieldDelegate
方法textFieldDidBeginEditing
。 这实际上与一个奇怪的副作用,即滚动将UITextField
捕捉到位。 最长的时间我无法弄清楚它是什么。 然后我注释掉了textFieldDidBeginEditing
委托方法,它都可以工作!!(???)。 事实证明,我相信UIScrollView
实际上隐含地将当前编辑的UITextField
隐式UITextField
入可视窗口。 我的UITextFieldDelegate
方法的实现和对scrollRecToVisible
后续调用是多余的,并且是造成奇怪副作用的原因。
因此,这里是正常滚动的步骤UITextField
中UIScrollView
到位键盘出现时。
// 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;
}
viewDidLoad
注册键盘通知 viewDidUnload
的键盘nofit contentSize
设置为大于UIScrollView
的viewDidLoad
UIScrollView
UIScrollView
。 UITextField
被选中时都会发送键盘通知,即使键盘已经存在以避免缩小UIScrollView
当它已经缩小 有一点需要注意的是,即使当您在另一个UITextField
上选择了键盘时, UIKeyboardWillShowNotification
也会触发。 我通过使用ivar来解决这个问题,以避免在键盘已经在屏幕上时调整UIScrollView
大小。 当键盘已经存在时无意中调整UIScrollView
大小将会是灾难性的!
希望这段代码能够为您节省一些很多头痛的问题。
正如文档中提供的那样,实际上最好使用Apple的实现。 但是,他们提供的代码是错误的。 将keyboardWasShown:
发现的部分替换为下面的注释:
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];
}
Apple代码的问题是:(1)他们总是计算该点是否在视图的框架内,但它是一个ScrollView
,因此它可能已经滚动并且需要考虑该偏移量:
origin.y -= scrollView.contentOffset.y
(2)他们将contentOffset移动了键盘的高度,但我们想要的是相反的(我们想要将contentOffset
移动到屏幕上可见的高度,而不是那个)。
activeField.frame.origin.y-(aRect.size.height)
链接地址: http://www.djcxy.com/p/27495.html
上一篇: How can I make a UITextField move up when the keyboard is present?
下一篇: How to remove Chutzpah from project to not show result in test explorer?