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

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

问题描述

我目前正在使用一个视图的iPhone应用程序,它有多个UITextFields用于输入。当键盘显示时,它覆盖底部文本字段。所以我添加了相应的 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 c> UIKeyboardDidShowNotification 以同步键盘动画和自定义动作

  • 不使用已弃用的 UIKeyboardBoundsUserInfoKey ;

  • 按下国际键处理键盘大小调整;

  • 通过取消注册键盘事件来修复内存泄漏; li>
  • 所有键盘处理代码封装在单独的类中 - 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 ::

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天全站免登陆