iOS相关

TPKeyBoardAvoiding-研究

2017-08-30  本文已影响830人  9362d9acd9ef

TPKeyboardAvoiding

There are a hundred and one proposed solutions out there for how to move UITextField and UITextView out of the way of the keyboard during editing -- usually, it comes down to observing UIKeyboardWillShowNotification and UIKeyboardWillHideNotification, or implementing UITextFieldDelegate delegate methods, and adjusting the frame of the superview, or using UITableView's scrollToRowAtIndexPath:atScrollPosition:animated:, but most proposed solutions tend to be quite DIY, and have to be implemented for each view controller that needs it.

解决 UITextField and UITextView 不被弹起的键盘遮盖的作法有很多,通用的方法有两种种

作者认为这样定制性太强

This is a relatively universal, drop-in solution: UIScrollView and UITableView subclasses that handle everything.



When the keyboard is about to appear, the subclass will find the subview that's about to be edited, and adjust its frame and content offset to make sure that view is visible, with an animation to match the keyboard pop-up. When the keyboard disappears, it restores its prior size.



It should work with basically any setup, either a UITableView-based interface, or one consisting of views placed manually.



It also automatically hooks up "Next" buttons on the keyboard to switch through the text fields.

采取的方案是:继承 UIScrollViewUITableView ,把事件 hook 住,实现了下面的功能。


对 TPKeyboardAvoidingTableView 进行分析

在每个初始化函数调用的时候注册事件监听

- (void)setup {
if ( [self hasAutomaticKeyboardAvoidingBehaviour] ) return;

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillShow:) name:UIKeyboardWillChangeFrameNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(TPKeyboardAvoiding_keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollToActiveTextField) name:UITextViewTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(scrollToActiveTextField) name:UITextFieldTextDidBeginEditingNotification object:nil];
}

注册了通知:

hasAutomaticKeyboardAvoidingBehaviour

- (BOOL)hasAutomaticKeyboardAvoidingBehaviour {
    if ( [self.delegate isKindOfClass:[UITableViewController class]] ) {
    // Theory: Apps built using the iOS 8.3 SDK (probably: older SDKs not tested) seem to handle keyboard
    // avoiding automatically with UITableViewController. This doesn't seem to be documented anywhere
    // by Apple, so results obtained only empirically.
    return YES;
    }
    return NO;
}

作者在 iOS 8.3 SDK 下猜测 UITableViewController 可能自动对键盘收起做了处理。如果判断使用了 UITableViewController 则代码都不会起作用。

setContentSize

- (void)setContentSize:(CGSize)contentSize {
    if ( [self hasAutomaticKeyboardAvoidingBehaviour] ) {
     [super setContentSize:contentSize];
     return;
    }
    if (CGSizeEqualToSize(contentSize, self.contentSize)) {
        // Prevent triggering contentSize when it's already the same
        // this cause table view to scroll to top on contentInset changes
        return;
    }
    [super setContentSize:contentSize];
    [self TPKeyboardAvoiding_updateContentInset];
}

除了修改 contentSize 会调用,当 contentInset 改变的时候也会调用。

willMoveToSuperview

- (void)willMoveToSuperview:(UIView *)newSuperview {
    [super willMoveToSuperview:newSuperview];
    if ( !newSuperview ) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(TPKeyboardAvoiding_assignTextDelegateForViewsBeneathView:) object:self];
    }
}

当 tableView 被加入或移除其他视图的子视图列表中时调用。当 tableView 被释放之类的情况也会调用

上一篇 下一篇

猜你喜欢

热点阅读