7

我有一个应用程序,如果键盘显示,我必须向上滚动。要获取键盘大小,我正在注册UIKeyboardWillShowNotification事件,如下所示:

   [[NSNotificationCenter defaultCenter]
     addObserver:self
     selector:@selector(keyboardWillShow:)
     name:UIKeyboardWillShowNotification
     object:self.view.window]

这确实有效,问题是,它是在调用textFieldDidBeginEditing之后被调用的。所以,我无法获得实际的键盘大小,但只有在该字段已经处于编辑模式之后,这违背了首先注册此事件的整个目的。我确定我调用了UIKeyboardWillShowNotification而不是UIKeyboardDidShowNotification,尽管切换这两个会产生相同的结果:首先调用了委托方法,然后才调用了通知方法。关于如何扭转这种局面的任何想法?目前我正在硬编码大小,这是非常糟糕的做法......

4

5 回答 5

2

我可以推荐一个 GitHub 存储库吗

https://github.com/hackiftekhar/IQKeyboardManager

于 2014-01-19T16:09:10.863 回答
1

这是我为这个用途编写的一个基类。它是UIViewController 每当我想实现这种行为的子类,我只是让我的视图控制器成为这个基类的子类。

顺便说一句 - 你是对的。textFieldDidBeginEditing在键盘出现后调用,这就是为什么你想在我的课堂上描述的键盘的回调方法中向上滚动。

另请注意,要使其正常工作,您需要将整个视图嵌入到滚动视图中,并将滚动视图的 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
于 2014-01-14T17:42:52.263 回答
0

我在 XCode 5 中打开了一个新项目,添加了一个UITextFieldViewController连接了它的委托。

这是我唯一的代码:

- (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));
}

这是日志输出:

肖像:

 Rect: {{0, 480}, {320, 216}}

景观:

 Rect: {{-162, 0}, {162, 480}}

编辑:

关于textFieldDidBeginEditing被调用之前name:UIKeyboardWillShowNotification,我真的不明白为什么 textField 是否处于编辑模式会有所不同,但有几种方法可以解决这个问题。

  1. 从 textFieldShouldBeginEditing 保存对 textField 的引用,并在触发 textFieldShouldBeginEditing 时在 myNotificationMethod 中使用它。

  2. 像这样玩UIResponder

textFieldDidBeginEditing-> 保存对的引用UIResponder并将 更改为UIResponder与临时无关的引用。在myNotificationMethod对 textField 做任何你想做的事情(不是在编辑模式\第一响应者),当你完成后,让它成为你的 main UIResponder

于 2014-01-14T10:35:55.230 回答
0

根据 Apple 文档,UIKeyboardWillShowNotification在键盘显示之前被调用,而UITextFieldDidBeginEditing在文本字段成为第一响应者之后被调用。显示键盘的过程在文本字段成为第一响应者开始,并且仅当键盘尚未显示时才开始。这意味着UIKeyboardWillShowNotification将在UITextFieldDidBeginEditing之后调用。所以UITextFieldDidBeginEditing不会过早调用。

如果您只想向上滚动以使文本字段不会隐藏在键盘下,您可以将滚动视图的内容偏移设置为UITextFieldShouldBeginEditingUITextFieldDidBeginEditing中文本字段的 y 原点。

于 2014-01-19T15:57:09.880 回答
0

老问题,但我今天遇到了同样的问题。我已经建立了一些“肮脏”的解决方法,它不会强迫我对键盘大小进行硬编码。我只是在 viewDidAppear 中做了以下事情(注意 - Swift):

 override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.infoTextField.becomeFirstResponder()
    self.infoTextField.resignFirstResponder()
}

这会触发UIKeyboardWillShowNotification,您可以从通知中获取键盘大小并将其存储在属性中。希望这对某人有所帮助,它在我的情况下有效。

于 2016-02-03T15:45:58.297 回答