在键盘上方移动文本字段的逻辑

现在,当您开始编辑时,我有基本的代码来移动键盘上的文本字段。 但是,文本字段的大小取决于设备和方向。 所以,我写了一个粗糙的做法,它不会一直保持在键盘上方,而是在旋转时会进一步上升,所以看起来不像我想的那么专业。

我的问题的基本意义是,如果有一个逻辑来获取基于设备和方向的键盘的大小,并自动使用该值,并希望比这更快。

如果这是最好的方式,请让我知道。 否则,请提供意见。 这是我有的代码。 (这只是上移的代码,而不是下移的代码,为了防止占用太多的空间)

- (void)textFieldDidBeginEditing:(UITextField *)textField { //Get Device Type NSString *deviceType = [[UIDevice currentDevice] model]; //Animate Text Field [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDelegate:self]; [UIView setAnimationDuration:0.4]; [UIView setAnimationBeginsFromCurrentState:YES]; if ([deviceType isEqualToString:@"iPhone"]) { //Size For iPhone googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height); } else if ([deviceType isEqualToString:@"iPad"]) { //Size for iPad googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 320.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height); } else if ([deviceType isEqualToString:@"iPod touch"]) { //Size For iPod Touch googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height); } [UIView commitAnimations]; } 

你真正想要做的就是观察UIKeyboard(意志)(显示|隐藏)通知。 它们在其userInfo字典中包含开始和结束帧,以及正确的animation曲线和持续时间。

所以在观察这个通知之后,当它发布的时候,根据提供的animation提示,根据通知中传递的帧的大小来移动文本字段。

您可以在UIWindow类引用的“通知”部分中看到更多信息: https : //developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html

下面是一个示例视图控制器实现。 此视图控制器的笔尖只是一个文本字段,连接了一个sockets,文本字段的委托设置为视图控制器。

 @interface ViewController () - (void)viewControllerInit; @end @implementation ViewController @synthesize textField; - (id)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self viewControllerInit]; } return self; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { [self viewControllerInit]; } return self; } - (void)viewControllerInit { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } #pragma mark - Notification Handlers - (void)keyboardWillShow:(NSNotification *)notification { // I'll try to make my text field 20 pixels above the top of the keyboard // To do this first we need to find out where the keyboard will be. NSValue *keyboardEndFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]; CGRect keyboardEndFrame = [keyboardEndFrameValue CGRectValue]; // When we move the textField up, we want to match the animation duration and curve that // the keyboard displays. So we get those values out now NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey]; NSTimeInterval animationDuration = [animationDurationNumber doubleValue]; NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey]; UIViewAnimationCurve animationCurve = [animationCurveNumber intValue]; // UIView's block-based animation methods anticipate not a UIVieAnimationCurve but a UIViewAnimationOptions. // We shift it according to the docs to get this curve. UIViewAnimationOptions animationOptions = animationCurve << 16; // Now we set up our animation block. [UIView animateWithDuration:animationDuration delay:0.0 options:animationOptions animations:^{ // Now we just animate the text field up an amount according to the keyboard's height, // as we mentioned above. CGRect textFieldFrame = self.textField.frame; textFieldFrame.origin.y = keyboardEndFrame.origin.y - textFieldFrame.size.height - 40; //I don't think the keyboard takes into account the status bar self.textField.frame = textFieldFrame; } completion:^(BOOL finished) {}]; } - (void)keyboardWillHide:(NSNotification *)notification { NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey]; NSTimeInterval animationDuration = [animationDurationNumber doubleValue]; NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey]; UIViewAnimationCurve animationCurve = [animationCurveNumber intValue]; UIViewAnimationOptions animationOptions = animationCurve << 16; [UIView animateWithDuration:animationDuration delay:0.0 options:animationOptions animations:^{ self.textField.frame = CGRectMake(20, 409, 280, 31); //just some hard coded value } completion:^(BOOL finished) {}]; } #pragma mark - View lifecycle - (void)viewDidUnload { [self setTextField:nil]; [super viewDidUnload]; // Release any retained subviews of the main view. // eg self.myOutlet = nil; } #pragma mark - UITextFieldDelegate - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self.textField resignFirstResponder]; return YES; } @end 

使用通知键盘寄存器,您可以将文本字段放置在滚动中,并pipe理滚动的内容偏移,以便在实际的第一响应者的键盘上方转动。

所以在注册控制器到键盘出现之后,必须获得键盘原点和相对于父键的滚动原点之间的差距。

您必须知道特定的第一响应者是否可以更改滚动的内容偏移,因此必须知道键盘原点和第一响应者之间可能的界限。

顺便说一下,您需要知道滚动内容偏移量与第一个响应者之间的差距,以便将第一个响应者置于特定位置。

 @interface MainViewController : UIViewController @property (strong, nonatomic) IBOutlet UIScrollView *scroll; @end @interface MainViewController () { CGPoint scrollOffset; } @end @implementation MainViewController @synthesize scroll -(void)viewWillAppear:(BOOL)animated { [[ NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardDidShowNotification object:nil]; [[ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(keyboardWillDisAppear:) name:UIKeyboardDidHideNotification object:nil]; } -(void)viewWillDisappear:(BOOL)animated { [[ NSNotificationCenter defaultCenter ] removeObserver:self ]; } -(void)keyboardWillAppear:(NSNotification*) note { const CGFloat default_gap = 25.0f; NSValue *keyBoardEndFrameValue = [[ note userInfo ] objectForKey:UIKeyboardFrameEndUserInfoKey ]; CGRect keyBoardFrame = [ keyBoardEndFrameValue CGRectValue ]; offset = scroll.contentOffset; UIWindow *window = [[ UIApplication sharedApplication ] keyWindow]; UITextField *textField = (UITextField*)[ window performSelector:@selector(firstResponder) ]; //Gap between keyboard origin and the scroll origin, relative to parent. CGFloat distanceRelativeToParent = keyBoardFrame.origin.y - scroll.frame.origin.y; //Distance between superview to textfield inside scroll. to determine if it's necesary to scroll. CGFloat bound = (textField.frame.origin.y + textField.frame.size.height)+scroll.frame.origin.y; CGFloat gapScroll = textField.frame.size.height+default_gap; if( bound >= keyBoardFrame.origin.y ) { [ UIView animateWithDuration:.3 delay:0.0 options:UIViewAnimationCurveEaseOut animations:^{ [ scroll setContentOffset:CGPointMake(0, textField.frame.origin.y - distanceRelativeToParent + gapScroll ) animated:YES ]; } completion:^(BOOL finished){ }]; } } -(void) keyboardWillDisAppear:(NSNotification*) note { [ scroll setContentOffset:offset animated:YES ]; } @end 

UIViewControllers有一个名为interfaceOrientation的属性和函数UIInterfaceOrientationIsPortrait / Landscape,所以基本上你可以这样做:

 if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation){ //portrait logic } else{ //landcapeLogic } 

里面的每个iPhone和iPad在你的视图控制器。 从那里你可以像以前一样进行像素测量,因为据我所知,这是最简单的方法。

PS还有一个函数可以检查景观检查器,但是如果第一个if语句是错误的,意味着设备不是纵向的,那么它必须在横向上,因此其他的是平坦的。