UITextField:出现键盘时移动视图 [英] UITextField: move view when keyboard appears

查看:24
本文介绍了UITextField:出现键盘时移动视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发具有单个视图的 iPhone 应用程序,该应用程序具有多个用于输入的 UITextField.当键盘显示时,它会覆盖底部的文本字段.所以我添加了相应的 textFieldDidBeginEditing: 方法,将视图向上移动,效果很好:

I'm currently working on an iPhone application with a single view, which has multiple UITextFields for input. When the keyboard shows, it overlays the bottom textfields. So I added the corresponding textFieldDidBeginEditing: method, to move the view up, which works great:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    if ( ( textField != inputAmount ) && ( textField != inputAge ) ) {
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y -= kOFFSET_FOR_KEYBOARD;
        frame.size.height += kOFFSET_FOR_KEYBOARD;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];      
    }
}

此方法检查消息的来源是否是键盘显示时可见的文本字段之一,如果不是,则向上移动视图.

This method checks, if the source of the message is one of the textfields that are visible when the keyboard shows, and if not, it moves the view up.

我还添加了 textFieldDidEndEnditing: 方法,该方法再次将视图向下移动(并根据更改的输入更新一些模型对象):

I also added the textFieldDidEndEnditing: method, which moves the view down again (and updates some model objects according to the changed input):

- (void)textFieldDidEndEditing:(UITextField *)textField {
    if ( ( textField != inputMenge ) && ( textField != inputAlter ) ) {
        NSTimeInterval animationDuration = 0.300000011920929;
        CGRect frame = self.view.frame;
        frame.origin.y += kOFFSET_FOR_KEYBOARD;
        frame.size.height -= kOFFSET_FOR_KEYBOARD;
        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
        [UIView setAnimationDuration:animationDuration];
        self.view.frame = frame;
        [UIView commitAnimations];      
    }
    // Additional Code
}

然而,这个解决方案有一个简单的缺陷:当我完成编辑一个隐藏"的文本字段并触摸另一个文本字段时,键盘消失,视图向下移动,视图再次向上移动,键盘重新出现.

However, this solution has a simple flaw: When I finish editing one of the "hidden" textfields and touch another textfield, the keyboard vanishes, the view moves down, the view moves up again and the keyboard reappears.

是否有可能防止键盘在两次编辑之间消失和重新出现(隐藏的"文本字段 - 这样视图仅在选定的文本字段从键盘隐藏的文本字段更改为可隐藏的文本字段时移动不会被隐藏)?

Is there any possibility to keep the keyboard from vanishing and reappearing between two edits (of the "hidden" textfields - so that the view only moves when the selected textfield changes from one that would be hidden by the keyboard to one that would not be hidden)?

推荐答案

此解决方案基于 ComSubVie 的解决方案.

This solution is based on ComSubVie's one.

优点:

  • 它支持设备旋转 - 适用于所有方向;
  • 它不会硬编码动画持续时间和曲线的值,而是从键盘通知中读取它们;
  • 它利用 UIKeyboardWillShowNotification 而不是 UIKeyboardDidShowNotification 来同步键盘动画和自定义操作;
  • 它不使用已弃用的 UIKeyboardBoundsUserInfoKey;
  • 它处理因按下国际键而导致的键盘大小调整;
  • 通过注销键盘事件修复内存泄漏;
  • 所有键盘处理代码都封装在一个单独的类中 - KBKeyboardHandler;
  • 灵活性 - KBKeyboardHandler 类可以轻松扩展/修改以更好地满足特定需求;
  • It supports device rotation - works for all orientations;
  • It doesn't hardcode the values for animation duration and curve, it reads them from the keyboard notification;
  • It utilizes UIKeyboardWillShowNotification instead of UIKeyboardDidShowNotification to sync keyboard animation and custom actions;
  • It doesn't use the deprecated UIKeyboardBoundsUserInfoKey;
  • It handles keyboard resize due to pressing the International key;
  • Fixed memory leak by unregistering for keyboard events;
  • All keyboard handling code is encapsulated in a separate class - KBKeyboardHandler;
  • Flexibility - KBKeyboardHandler class may be easy extended / modified to better suit specific needs;

限制:

  • 适用于 iOS 4 及更高版本,需要稍作修改以支持旧版本;
  • 它适用于具有单个 UIWindow 的应用程序.如果您使用多个 UIWindows,您可能需要修改 retrieveFrameFromNotification: 方法.
  • Works for iOS 4 and above, it needs small modifications to support older versions;
  • It works for applications with a single UIWindow. If you use multiple UIWindows, you may need to modify retrieveFrameFromNotification: method.

用法:

在您的项目中包含 KBKeyboardHandler.h、KBKeyboardHandler.m 和 KBKeyboardHandlerDelegate.h.在您的视图控制器中实现 KBKeyboardHandlerDelegate 协议 - 它由一个方法组成,当键盘显示、隐藏或更改大小时将调用该方法.实例化 KBKeyboardHandler 并设置它的委托(通常是 self).请参阅下面的示例 MyViewController.

Include KBKeyboardHandler.h, KBKeyboardHandler.m and KBKeyboardHandlerDelegate.h in your project. Implement the KBKeyboardHandlerDelegate protocol in your view controller - it consists of a single method, which will be called when keyboard is shown, hidden or its size is changed. Instantiate the KBKeyboardHandler and set its delegate (typically self). See sample MyViewController below.

KBKeyboardHandler.h:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@protocol KBKeyboardHandlerDelegate;

@interface KBKeyboardHandler : NSObject

- (id)init;

// Put 'weak' instead of 'assign' if you use ARC
@property(nonatomic, assign) id<KBKeyboardHandlerDelegate> delegate; 
@property(nonatomic) CGRect frame;

@end

KBKeyboardHandler.m:

#import "KBKeyboardHandler.h"
#import "KBKeyboardHandlerDelegate.h"

@implementation KBKeyboardHandler

- (id)init
{
    self = [super init];
    if (self)
    {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];

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

    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super dealloc];
}

@synthesize delegate;
@synthesize frame;

- (void)keyboardWillShow:(NSNotification *)notification
{
    CGRect oldFrame = self.frame;    
    [self retrieveFrameFromNotification:notification];

    if (oldFrame.size.height != self.frame.size.height)
    {
        CGSize delta = CGSizeMake(self.frame.size.width - oldFrame.size.width,
                                  self.frame.size.height - oldFrame.size.height);
        if (self.delegate)
            [self notifySizeChanged:delta notification:notification];
    }
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    if (self.frame.size.height > 0.0)
    {
        [self retrieveFrameFromNotification:notification];
        CGSize delta = CGSizeMake(-self.frame.size.width, -self.frame.size.height);

        if (self.delegate)
            [self notifySizeChanged:delta notification:notification];
    }

    self.frame = CGRectZero;
}

- (void)retrieveFrameFromNotification:(NSNotification *)notification
{
    CGRect keyboardRect;
    [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
    self.frame = [[UIApplication sharedApplication].keyWindow.rootViewController.view convertRect:keyboardRect fromView:nil];
}

- (void)notifySizeChanged:(CGSize)delta notification:(NSNotification *)notification
{
    NSDictionary *info = [notification userInfo];

    UIViewAnimationOptions curve;
    [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve];

    NSTimeInterval duration;
    [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration];

    void (^action)(void) = ^{
        [self.delegate keyboardSizeChanged:delta];
    };

    [UIView animateWithDuration:duration
                          delay:0.0
                        options:curve
                     animations:action
                     completion:nil];    
}

@end

KBKeyboardHandlerDelegate.h:

@protocol KBKeyboardHandlerDelegate

- (void)keyboardSizeChanged:(CGSize)delta;

@end

示例 MyViewController.h:

@interface MyViewController : UIViewController<KBKeyboardHandlerDelegate>
...
@end

示例 MyViewController.m:

@implementation MyViewController
{
    KBKeyboardHandler *keyboard;
}

- (void)dealloc
{
    keyboard.delegate = nil;
    [keyboard release];
    [super dealloc];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    keyboard = [[KBKeyboardHandler alloc] init];
    keyboard.delegate = self;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    keyboard.delegate = nil;
    [keyboard release];
    keyboard = nil;
}

- (void)keyboardSizeChanged:(CGSize)delta
{
    // Resize / reposition your views here. All actions performed here 
    // will appear animated.
    // delta is the difference between the previous size of the keyboard 
    // and the new one.
    // For instance when the keyboard is shown, 
    // delta may has width=768, height=264,
    // when the keyboard is hidden: width=-768, height=-264.
    // Use keyboard.frame.size to get the real keyboard size.

    // Sample:
    CGRect frame = self.view.frame;
    frame.size.height -= delta.height;
    self.view.frame = frame;
}

更新:修复了 iOS 7 警告,感谢@weienv.

UPDATE: Fixed iOS 7 warning, thanks @weienv.

这篇关于UITextField:出现键盘时移动视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆