Ios textFieldDidBeginEditing被过早地调用
我有一个应用程序,在其中我必须向上滚动以防键盘显示。 为了获得键盘大小,我注册了UIKeyboardWillShowNotification事件,如下所示:Ios textFieldDidBeginEditing被过早地调用,ios,uitextfield,autoscroll,uitextfielddelegate,Ios,Uitextfield,Autoscroll,Uitextfielddelegate,我有一个应用程序,在其中我必须向上滚动以防键盘显示。 为了获得键盘大小,我注册了UIKeyboardWillShowNotification事件,如下所示: [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.wi
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window]
这是可行的,问题是,它是在调用textfielddebeginediting后调用的。因此,我无法获得实际的键盘大小,但只能在字段已经处于编辑模式之后,这就违背了注册此事件的全部目的。
我确信我调用了UIKeyboardWillShowNotification,而不是UIKeyboardDidShowNotification,尽管切换这两个会产生相同的结果:
首先调用委托方法,然后才调用通知方法。你知道如何扭转这种局面吗?目前我正在硬编码大小,这是一种非常糟糕的做法…我在XCode 5中打开了一个新项目,在
视图控制器中添加了一个UITextField
,并连接了它的代理
这是我唯一的代码:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(myNotificationMethod:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)myNotificationMethod:(NSNotification*)notification
{
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
NSLog(@"Rect: %@",NSStringFromCGRect(keyboardFrameBeginRect));
}
以下是日志输出:
Portraid:
Rect: {{0, 480}, {320, 216}}
Rect: {{-162, 0}, {162, 480}}
景观:
Rect: {{0, 480}, {320, 216}}
Rect: {{-162, 0}, {162, 480}}
编辑:
Rect: {{0, 480}, {320, 216}}
Rect: {{-162, 0}, {162, 480}}
关于在name:UIKeyboardWillShowNotification
之前调用textfieldDiBeginediting
,我真的不明白为什么textField是否处于编辑模式会有区别,但有几种方法可以解决这个问题
从textFieldShouldBeginEditing保存对textField的引用,如果触发了in-did textFieldShouldBeginEditing,则在myNotificationMethod中使用该引用
玩弄ui应答器
就像这样:
在textfieldDiBeginediting
->中,保存对UIResponder
的引用,并将UIResponder
更改为临时无关的引用。在myNotificationMethod
中,对文本字段(不在编辑模式下的\first responder)执行任何您想执行的操作,完成后将其设置为主UIResponder
这是我为这个用途编写的一个基类。它是UIViewController
每当我想要实现这样的行为时,我就把我的视图控制器作为这个基类的一个子类
顺便说一句,你是对的textFieldDidBeginEditing
在键盘显示后被调用,这就是为什么您希望在键盘的Callbacks方法中向上滚动,如我的课程中所述
另外,请注意,要使其工作,您需要将整个视图嵌入到滚动视图中,并将滚动视图的IBOutlet连接到该视图
如果您不使用故事板,请删除IBOutlet部分,并将视图嵌入到滚动视图中,并在代码中建立连接
这之后是代码:
头文件
#import <UIKit/UIKit.h>
@interface BaseViewControllerWithKeyboard : BaseViewController
@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) UITextField *activeField;
@end
#import "BaseViewControllerWithKeyboard.h"
@interface BaseViewControllerWithKeyboard ()
@end
@implementation BaseViewControllerWithKeyboard
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self registerForKeyboardNotifications];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your app might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, _activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:_activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
_scrollView.contentInset = contentInsets;
_scrollView.scrollIndicatorInsets = contentInsets;
}
@end
根据苹果的文档,UIKeyboardWillShowNotification在显示键盘之前调用,而UIExtFieldDidBeginediting在文本字段成为第一响应者之后调用。显示键盘的过程在文本字段成为第一响应者后开始,并且仅当键盘尚未显示时。这意味着UIKeyboardWillShowNotification将在UIExtFieldDidBeginediting之后调用。因此,uitextfielddibeginediting不会过早调用
如果您只想向上滚动,这样文本字段就不会隐藏在键盘下,您可以在uitextfield shouldbeginediting或uitextfield didbeginediting中将滚动视图的内容偏移设置为文本字段的y原点 我可以推荐一个GitHub存储库吗
老问题,但我今天遇到了同样的问题。我已经建立了一个小的“肮脏”的解决办法,不强迫我硬编码键盘大小。我只是在ViewDidEmerge中做了以下操作(注意-Swift):
这将触发UIKeyboardWillShowNotification,您可以从通知中获取键盘大小并将其存储在属性中。希望这对其他人有所帮助,在我的情况下它起到了作用。你有解决方案吗?我也在处理这个问题。.我假设当键盘通知触发时,你需要知道哪个UITextField正在被编辑,以便你可以正确滚动,这是正确的吗?如果是这样的话,那么您可以在textViewDidBeginEditing
中隐藏对该UITextField的引用,以便在收到通知时使用。这很酷,问题是,如果您使用textfield:didBeginEditing:method,您可以看到它在键盘通知发出之前被调用。@Rizon从textfield shouldbeginediting
保存对textfield
的引用,并在myNotificationMethod
中使用它怎么样是否被触发?我不知道为什么文本字段是否处于编辑模式会有差异。更多地解释一下你为什么要这样做可能会有所帮助。请查看这个解决方案@RizonA用例,它回避了这个代码。。。1.如果UIView有多个UITextFields和2。只有一部分字段需要滚动视图3。然后,当用户将焦点从一个UITextfield移动到另一个UITextfield时,4。键盘显示:将不被调用。1。为什么它不能处理多个文本字段?它有两个。请解释一下。儿子,在这种情况下也没什么问题。4.如果您正确注册通知,KeyboardwasShowed将被调用。例如,1。用户首先点击UITextField,键盘显示:被调用。2.键盘被显示,UIView被稍微滚动3下。用户点击第二个UITextBox(假设键盘与此框的下部重叠,但用户仍可以点击它)4。键盘是可见的,因此KeyboardwasShow:未调用。我添加了一个textFieldDidBeginEditing的处理程序:如果