如何计算 iPad 上模态视图的底部偏移量?
Posted
技术标签:
【中文标题】如何计算 iPad 上模态视图的底部偏移量?【英文标题】:How to calculate the bottom offset of a modal view on iPad? 【发布时间】:2013-09-13 00:17:50 【问题描述】:当用户点击 UITextField 时,键盘会出现。我向上滚动 UITextField 以坐在键盘上方。这在 iPhone 上运行良好:
- (void) someWhere
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onKeyboardShow:)
name:UIKeyboardWillShowNotification
object:nil];
- (void) onKeyboardShow:(NSNotification *)notification
CGRect keyboardRect = [[[notification userInfo]
objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue
];
if (keyboardRect.size.height >= IPAD_KEYBOARD_PORTRAIT_HEIGHT)
self.containerView.y = self.containerView.y - keyboardRect.size.width;
else
self.containerView.y = self.containerView.y - keyboardRect.size.height;
但是,它在 iPad 上坏了。在 iPad 上,模态视图控制器可以显示为仅占屏幕一部分的工作表。可以看到最后一个 UITextField 和 iPad 上的键盘之间有一个空隙。
UINavigationController* nav = [[UINavigationController alloc]
initWithRootViewController:someRootViewController];
nav.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:nav animated:YES completion:nil];
我需要检测模态视图从屏幕底部的偏移并将其添加到 UITextField 的 Y 坐标。这将使 UITextField 与键盘顶部齐平。通过一些逆向工程,我通过遍历未记录的视图层次结构得到了模态视图的框架:
- (void) viewDidAppear:(BOOL)animated
[super viewDidAppear:animated];
// describe is a category function on UIView that prints out the frame
[self.viewController.view.superview.superview.superview.superview describe];
x:114.000000, y: 192.000000, w: 540.000000, h: 620.000000
最后,为了获得模态视图从屏幕底部的偏移量,我这样做了:
UIView* modalView = self.viewController.view.superview.superview.superview.superview;
// usage of self-explanatory UIView category methods
CGFloat bottomOffset = modalView.superview.height - (modalView.y + modalView.height);
令我懊恼的是,这只适用于纵向模式。出于某种原因,无论 iPad 处于什么方向,模态视图的超级视图总是卡在 768 的宽度和 1024 的高度。所以这就是我寻求帮助的地方。无论方向如何,如何在 iPad 上可靠地获取模式视图从屏幕底部的偏移量?
【问题讨论】:
【参考方案1】:我看到了两种可能的解决方案:
使用inputAccessoryView
将文本字段自动附加到键盘。
将键盘矩形转换为您要移动的 containerView 的父视图。然后,您可以在 containerView 的 superview 的坐标中获取其顶部 Y 值。
类似:
CGRect rectInWindowCoordinates = [self.containerView.window convertRect:keyboardRect fromWindow:nil];
CGRect rectCoveredByKeyboard = [self.containerView.superview convertRect:rectInWindowCoordinates fromView:nil];
CGFloat top = CGRectGetMinY(rectCoveredByKeyboard);
self.containerView.y = top - self.containerView.frame.size.height;
【讨论】:
在我花时间实现inputAccessoryView
之前,我想知道iPad的Messages App的文本输入框是否也使用inputAccessoryView
。该设计与我的设计几乎相同。基本上,UITextField
和inputAccessoryView
是一回事。 UITextField
最初位于屏幕底部,并在键盘出现时向上移动以变为 inputAccessoryView
。
我猜它没有使用inputAccessoryView
,因为它具有特殊的键盘滚动行为。如果您想要与 Messages 界面几乎相同的东西,您可能可以find one on Cocoa Controls 使用或查看示例。
我正在尝试实施您的第二个选项,但是我使用的是UIView convertPoint:(CGPoint)point toView:(UIView*)view
。我将UIWindow
中的键盘顶点转换为我的文本字段的坐标系。这在纵向模式下运行良好,但在横向模式下仍然中断。当键盘以横向出现时,它将模态视图推到更高的屏幕顶部。所以最初,我可以将我的文本字段与键盘齐平,但是一旦模态视图滑动得更高,键盘就会覆盖文本字段。
啊,对了!我忘记了。我已经更新了我的答案,以包括应该解决该问题的所需窗口转换。 (键盘矩形是屏幕坐标,不是窗口坐标,所以你必须先转换成窗口坐标。)【参考方案2】:
- (void) onKeyboardShow:(NSNotification *)notification
CGRect keyboardRect = [[[notification userInfo]
objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue
];
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
// The keyboard height is only correct when in portrait mode. To get the
// real height, we make the assumption that keyboards are always wider than
// they are tall.
CGFloat keyboardHeight;
if (keyboardRect.size.width < keyboardRect.size.height)
keyboardHeight = keyboardRect.size.width;
else
keyboardHeight = keyboardRect.size.height;
CGPoint originOfKeyboardInWindowContext;
switch (orientation)
//
// (0,0) ___________
// | |
// | |
// | |
// | |
// | |
// |===========|
// |===========|
//
case UIInterfaceOrientationPortrait:
originOfKeyboardInWindowContext = CGPointMake(0.0, [VeetleAppDelegate instance].window.height - keyboardHeight);
break;
//
// ___________
// | |
// | |
// | |
// | |
// | |
// |===========|
// |===========| (0,0)
//
case UIInterfaceOrientationPortraitUpsideDown:
originOfKeyboardInWindowContext = CGPointMake(0.0, keyboardHeight);
break;
//
// _________________
// | |
// | |
// | |
// |=================|
// |=================|
// (0,0)
//
case UIInterfaceOrientationLandscapeRight:
originOfKeyboardInWindowContext = CGPointMake(keyboardHeight, 0.0);
break;
//
// _________________ (0,0)
// | |
// | |
// | |
// |=================|
// |=================|
//
case UIInterfaceOrientationLandscapeLeft:
originOfKeyboardInWindowContext = CGPointMake([VeetleAppDelegate instance].window.width - keyboardHeight, 0.0);
break;
CGPoint originOfKeyboardInTextFieldContext = [[VeetleAppDelegate instance].window convertPoint:originOfKeyboardInWindowContext toView:self.containerView.superview];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
self.containerView.y = originOfKeyboardInTextFieldContext.y - self.containerView.height;
[UIView commitAnimations];
【讨论】:
以上是关于如何计算 iPad 上模态视图的底部偏移量?的主要内容,如果未能解决你的问题,请参考以下文章