Com*_*Vie 53 iphone cocoa-touch objective-c uitextfield
我目前正在开发一个带有单个视图的iPhone应用程序,它有多个UITextField用于输入.键盘显示时,它覆盖底部文本字段.所以我添加了相应的textFieldDidBeginEditing:方法,将视图向上移动,效果很好:
- (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];
}
}
Run Code Online (Sandbox Code Playgroud)
如果消息源是键盘显示时可见的文本字段之一,则此方法检查,如果不是,则向上移动视图.
我还添加了textFieldDidEndEnditing:方法,它再次向下移动视图(并根据更改的输入更新一些模型对象):
- (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
}
Run Code Online (Sandbox Code Playgroud)
但是,这个解决方案有一个简单的缺陷:当我完成编辑其中一个"隐藏"文本字段并触摸另一个文本字段时,键盘消失,视图向下移动,视图再次向上移动,键盘重新出现.
是否有可能防止键盘在两个编辑("隐藏"文本字段)之间消失和重新出现 - 这样当所选文本字段从键盘隐藏的文本字段变为不隐藏的字段时,视图才会移动)?
Vla*_*rov 47
此解决方案基于ComSubVie的解决方案.
好处:
UIKeyboardWillShowNotification而不是UIKeyboardDidShowNotification同步键盘动画和自定义动作;UIKeyboardBoundsUserInfoKey;KBKeyboardHandler;KBKeyboardHandler可以轻松扩展/修改类以更好地满足特定需求;限制:
UIWindow.如果使用多个UIWindows,则可能需要修改retrieveFrameFromNotification:方法.用法:
在项目中包含KBKeyboardHandler.h,KBKeyboardHandler.m和KBKeyboardHandlerDelegate.h.KBKeyboardHandlerDelegate在视图控制器中实现协议 - 它由单个方法组成,当键盘显示,隐藏或其大小发生变化时,将调用该方法.实例化KBKeyboardHandler并设置其委托(通常是self).见MyViewController下面的示例.
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
KBKeyboardHandlerDelegate.h:
@protocol KBKeyboardHandlerDelegate
- (void)keyboardSizeChanged:(CGSize)delta;
@end
Run Code Online (Sandbox Code Playgroud)
示例MyViewController.h:
@interface MyViewController : UIViewController<KBKeyboardHandlerDelegate>
...
@end
Run Code Online (Sandbox Code Playgroud)
示例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;
}
Run Code Online (Sandbox Code Playgroud)
更新:修复了iOS 7警告,感谢@weienv.
Com*_*Vie 30
我刚刚解决了这个问题.解决方案是a UIKeyboardDidShowNotification和UIKeyboardDidHideNotification观察者与上述textFieldDidBeginEditing:和textFieldDidEndEditing:方法的组合.
您需要三个附加变量,一个用于存储当前选定的UITextField(我已命名为activeField),一个用于指示当前视图是否已移动,另一个用于指示是否显示键盘.
这就是两个UITextField委托方法现在的样子:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
activeField = nil;
// Additional Code
}
Run Code Online (Sandbox Code Playgroud)
加载视图时,将创建以下两个观察者:
- (void)viewDidLoad {
// Additional Code
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasHidden:)
name:UIKeyboardDidHideNotification
object:nil];
}
Run Code Online (Sandbox Code Playgroud)
相应的方法实现如下:
- (void)keyboardWasShown:(NSNotification *)aNotification {
if ( keyboardShown )
return;
if ( ( activeField != inputAmount ) && ( activeField != inputAge ) ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y -= keyboardSize.height-44;
frame.size.height += keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = YES;
}
keyboardShown = YES;
}
- (void)keyboardWasHidden:(NSNotification *)aNotification {
if ( viewMoved ) {
NSDictionary *info = [aNotification userInfo];
NSValue *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
CGSize keyboardSize = [aValue CGRectValue].size;
NSTimeInterval animationDuration = 0.300000011920929;
CGRect frame = self.view.frame;
frame.origin.y += keyboardSize.height-44;
frame.size.height -= keyboardSize.height-44;
[UIView beginAnimations:@"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.view.frame = frame;
[UIView commitAnimations];
viewMoved = NO;
}
keyboardShown = NO;
}
Run Code Online (Sandbox Code Playgroud)
此代码现在按预期工作.键盘仅在按下"完成"按钮时被解除,否则它将保持可见状态并且视图不会移动.
作为一个额外的注释,我认为有可能animationDuration通过询问NSNotification对象来动态获取,因为我已经使用了类似的解决方案,但没有让它工作(它现在做).