热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

键盘“WillShow”和“WillHide”vs.旋转。-Keyboard“WillShow”and“WillHide”vs.Rotation

IvegotaviewcontrollerlisteningforbothUIKeyboardWillShowNotificationandUIKeyboardWillHideN

I've got a view controller listening for both UIKeyboardWillShowNotification and UIKeyboardWillHideNotification. The handlers for these notifications adjust various parts of the view, which is standard procedure.

我有一个视图控制器监听UIKeyboardWillShowNotification和uikeyboardwillhi。这些通知的处理程序调整视图的各个部分,这是标准过程。

The following code is used to convert the keyboard rect from screen coordinates:

以下代码用于将键盘矩形从屏幕坐标转换为:

CGRect keyboardBounds = [self.view convertRect:[keyboardBoundsValue CGRectValue] fromView:nil];

Again, standard procedure. Unfortunately, there is a critical situation where this conversion fails. Look at what happens when an iPhone is rotated from portrait to landscape while the keyboard is deployed:

同样,标准程序。不幸的是,这种转换失败的情况非常危急。看看当iPhone从竖屏旋转到横屏的时候会发生什么:

1) iOS automatically fires UIKeyboardWillHideNotification; self.interfaceOrientation is reported as portrait; keyboardBounds.height is 216.0. This makes sense. Why? Because the notification handler is given the chance to "clean up" before the view switches to landscape mode.

1) iOS自动触发uikeyboardwillhi;self。interfaceorientation报告为人像;keyboardBounds。高度是216.0。这是有意义的。为什么?因为通知处理程序有机会在视图切换到横向模式之前“清理”。

2) iOS automatically fires UIKeyboardWillShowNotification; self.interfaceOrientation is reported as portrait; keyboardBounds.height is 480.0. This does NOT make sense. Why not? Because the notification handler is going to do its work thinking that the height of the keyboard is 480.0!

2) iOS自动触发UIKeyboardWillShowNotification;self。interfaceorientation报告为人像;keyboardBounds。高度是480.0。这没有道理。为什么不呢?因为通知处理程序将执行它的工作,认为键盘的高度是480.0!

Did Apple drop the ball on this one, or am I doing something wrong?

苹果在这件事上犯了错误,还是我做错了什么?

Please note that listening instead for UIKeyboardDidShowNotification is not a valid solution, because it significantly degrades the user experience. Why? Because animating my changes to the view after the keyboard deployment animation occurs is... well, pretty terrible-looking.

请注意,监听UIKeyboardDidShowNotification不是一个有效的解决方案,因为它会显著降低用户体验。为什么?因为在键盘部署动画发生后,对视图进行动画修改是……嗯,很恐怖的。

Has anyone managed to get autorotation working perfectly while the keyboard is deployed? It seems like an explosion of chaos that Apple has completely overlooked. >:|

当键盘被部署时,有没有人设法使自动旋转工作完美?苹果似乎完全忽略了一场混乱的爆发。>:|

7 个解决方案

#1


54  

Maybe a bit late, but I've just run into the same issue and have a nice solution for it that avoids any kind of work arounds (unless of course apple change things)

可能有点晚了,但是我遇到了同样的问题,我有一个很好的解决方案,避免了任何形式的工作(当然,除非苹果改变了事情)

Basically, when the notification center calls your method for UIKeyboardWillShowNotification (or any of the other notifications), the frame that it gives you for UIKeyboardFrameBeginUserInfoKey is in context of the window, NOT your view. The problem with this, is that the windows coordinate system is always in portrait, regardless of the devices orientation, hence you're finding the width and height the wrong way round.

基本上,当通知中心为UIKeyboardWillShowNotification(或其他通知)调用你的方法时,它为UIKeyboardFrameBeginUserInfoKey提供的框架是在窗口的上下文中,而不是你的视图。这样做的问题是,无论设备的方向如何,windows坐标系统始终是纵向的,因此您会发现宽度和高度是错误的。

If you want to avoid your work around, simply convert the rectangle into the coordinate system of your view (which does change according to the orientation). To do this, do something like the following :

如果你想避免你的工作,只需把矩形转换成你视图的坐标系统(它会根据方向变化)。要做到这一点,可以做以下事情:

- (void) keyboardWillShow:(NSNotification *)aNotification
{
     CGRect keyboardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGRect cOnvertedFrame= [self.view convertRect:keyboardFrame fromView:self.view.window];

    ......
    /* Do whatever you want now with the new frame.
     * The width and height will actually be correct now
     */
    ......
}

Hopefully this should be what you're after :)

希望这就是你想要的

#2


4  

Recently I've wrote a blog post about this exact problem you've described and how to solve it with a short and elegant way. Here is the link to the post: Synchronizing rotation animation between the keyboard and the attached view

最近,我写了一篇博文,介绍了你所描述的这个问题,以及如何用一种简洁优雅的方式来解决它。这里是post的链接:在键盘和附加视图之间同步旋转动画

If you don't want to dive into the long explanation described in the blog post here is a short description with a code example:

如果您不想深入了解博客文章中所描述的冗长的解释,这里有一个简短的描述和代码示例:

The basic principle is to use the same method that everyone uses - observing keyboard notifications to animate the attached view up and down. But in addition to that, you have to cancel these animations when the keyboard notifications are fired as a consequence of interface orientation change.

基本原则是使用每个人都使用的相同方法——观察键盘通知,使附加的视图上下浮动。但除此之外,你还必须取消这些动画,当键盘通知被触发,作为接口方向改变的结果。

Rotation example without animation cancellation custom on interface orientation change:

旋转例子,没有动画取消自定义界面方向改变:

Rotation example with animation cancellation on interface orientation change:

旋转例子与动画取消界面方向的改变:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [[NSNotificationCenter defaultCenter]
            addObserver:self selector:@selector(adjustViewForKeyboardNotification:)
            name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]
            addObserver:self selector:@selector(adjustViewForKeyboardNotification:)
            name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    [[NSNotificationCenter defaultCenter]
            removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]
            removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    self.animatingRotation = YES;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
    self.animatingRotation = NO;
}

- (void)adjustViewForKeyboardNotification:(NSNotification *)notification {
    NSDictionary *notificatiOnInfo= [notification userInfo];

    // Get the end frame of the keyboard in screen coordinates.
    CGRect finalKeyboardFrame = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    // Convert the finalKeyboardFrame to view coordinates to take into account any rotation
    // factors applied to the window’s contents as a result of interface orientation changes.
    finalKeyboardFrame = [self.view convertRect:finalKeyboardFrame fromView:self.view.window];

    // Calculate new position of the commentBar
    CGRect commentBarFrame = self.commentBar.frame;
    commentBarFrame.origin.y = finalKeyboardFrame.origin.y - commentBarFrame.size.height;

    // Update tableView height.
    CGRect tableViewFrame = self.tableView.frame;
    tableViewFrame.size.height = commentBarFrame.origin.y;

    if (!self.animatingRotation) {
        // Get the animation curve and duration
        UIViewAnimationCurve animatiOnCurve= (UIViewAnimationCurve) [[notificationInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
        NSTimeInterval animatiOnDuration= [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

        // Animate view size synchronously with the appearance of the keyboard. 
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:animationDuration];
        [UIView setAnimationCurve:animationCurve];
        [UIView setAnimationBeginsFromCurrentState:YES];

        self.commentBar.frame = commentBarFrame;
        self.tableView.frame = tableViewFrame;

        [UIView commitAnimations];
    } else {
        self.commentBar.frame = commentBarFrame;
        self.tableView.frame = tableViewFrame;
    }
}

This answer was also posted in similar question: UIView atop the Keyboard similar to iMessage App

这个答案也有类似的问题:在键盘上的UIView类似iMessage应用。

#3


3  

I met the same problem. iOS gaves me incorrect width/height of the keyboard. I used the following snipped in a keyboardDidShow handler:

我遇到了同样的问题。iOS使我的键盘宽度/高度不正确。我在keyboardDidShow处理器中使用了如下剪切:

CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGSize keyboardSize2 = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
LogDbg(@"keyboard size: frameBegin=%@; frameEnd=%@", NSStringFromCGSize(keyboardSize), NSStringFromCGSize(keyboardSize2));

and for portrait and landscape modes of iPad I got respectively:

iPad的人像模式和景观模式分别是:

2012-06-14 04:09:49.734 -[LoginViewController keyboardDidShow:] 132 [DBG]:keyboard size: frameBegin={768, 264}; frameEnd={768, 264}
2012-06-14 04:10:07.971 -[LoginViewController keyboardDidShow:] 132 [DBG]:keyboard size: frameBegin={352, 1024}; frameEnd={352, 1024}

Guessing that the width of the keyboard should be greater then the height (yep, i'm so naive) I made a workaround like following:

我猜想键盘的宽度应该比高度大(是的,我太天真了),于是我做了如下的变通:

if (keyboardSize.width 

#4


0  

Well, try looking at keyboard width. If it is the value that you are expecting, then I assume that the values are simply switched ;). 480 makes sense as a keyboard width for going into landscape, which is what gives me this hunch.

看看键盘的宽度。如果它是您所期望的值,那么我假定这些值是简单地交换的;)。480作为进入横屏的键盘宽度是有意义的,这就是我的直觉。

If that fails, just store the portrait and landscape rectangles separately. They are well documented ;)

如果失败,就分别存储纵向矩形和横向矩形。它们都有充分的文件证明;)

#5


0  

I know this a very very late reply. Now only I came on this situation and find the unanswered question. So I thought I'll share my solution. There will be some other better way, but the following way also we can solve this.

我知道这是一个非常非常晚的答复。现在只有我在这个问题上找到了没有答案的问题。所以我想和大家分享我的解决方案。还有其他更好的方法,但是下面的方法我们也可以解决这个问题。

The KBKeyboardHandler that I used is from: UITextField: move view when keyboard appears

我使用的KBKeyboardHandler来自:UITextField:当键盘出现时,移动视图。

I just changed my delegate as following:

我刚刚将我的委托改为:

- (void)keyboardSizeChanged:(CGSize)delta
{    
    CGRect frame = self.view.frame;    
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    switch (interfaceOrientation) {
        case UIInterfaceOrientationPortrait:
            frame.origin.y-=delta.height;
            break;
        case UIInterfaceOrientationPortraitUpsideDown:
            frame.origin.y+=delta.height;
            break;
        case UIInterfaceOrientationLandscapeLeft:
            frame.origin.x-=delta.height;
            break;
        case UIInterfaceOrientationLandscapeRight:
            frame.origin.x+=delta.height;
            break;
        default:
            break;
    }
    self.view.frame = frame;
}

And it was working fine.

它运行得很好。

#6


-1  

Here is my workaround:

这是我的解决方案:

CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
float keyboardHeight = self.interfaceOrientation == UIInterfaceOrientationPortrait ? keyboardSize.height : keyboardSize.width;

Hope this helps :)

希望这有助于:)

#7


-1  

I use the following code to get the size of the keyboard which works fine for all rotations

我使用下面的代码来获得适合所有旋转的键盘大小

NSDictionary *info = [aNotification userInfo];
if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
  kbHeight = [[NSNumber numberWithFloat:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.width] floatValue];
else
  kbHeight = [[NSNumber numberWithFloat:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size.height] floatValue];
NSLog(@"keyboard height = %F",kbHeight);

I then test for the orientation using the status bar orientation (which works in the first launch case for the iPad) and shift the view in the relative direction needed to make space for the keyboard. This works perfectly, if the keyboard is visible then it relocates to the correct position on rotations.

然后,我使用状态栏定位(在iPad的第一个启动案例中起作用)测试定位,并将视图移到为键盘留出空间所需的相对方向上。这是完美的工作,如果键盘是可见的,那么它重新定位到正确的位置在旋转。

UIDeviceOrientation orientation =  [UIApplication sharedApplication].statusBarOrientation;


if (orientation == UIDeviceOrientationPortrait)
  {
  NSLog(@"Orientation: portrait");
  self.originalCenter = self.view.center;
  self.view.center = CGPointMake(self.originalCenter.x, self.originalCenter.y-kbHeight);
  }

if (orientation == UIDeviceOrientationPortraitUpsideDown)
  {
  NSLog(@"Orientation: portrait upside down");
  self.originalCenter = self.view.center;
  self.view.center = CGPointMake(self.originalCenter.x, self.originalCenter.y+kbHeight);
  }

if (orientation == UIDeviceOrientationLandscapeLeft)
  {
  NSLog(@"Orientation: landscape left");
  self.originalCenter = self.view.center;
  self.view.center = CGPointMake(self.originalCenter.x+kbHeight,self.originalCenter.y);
  }

if (orientation == UIDeviceOrientationLandscapeRight)
  {
  NSLog(@"Orientation: landscape right");
  self.originalCenter = self.view.center;
  self.view.center = CGPointMake(self.originalCenter.x-kbHeight,self.originalCenter.y);
  }

You can return the view to its original position when the keyboard disappears or via a textFileDidEndEditing function.

当键盘消失或通过textFileDidEndEditing函数时,可以将视图返回到原来的位置。


推荐阅读
author-avatar
双豆儿_668
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有