UITextField:键盘出现时移动视图

时间:2009-11-21 15:57:27

标签: iphone objective-c cocoa-touch 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];      
    }
}

如果消息来源是键盘显示时可见的文本字段之一,则此方法检查,如果不是,则会移动视图。

我还添加了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
}

然而,这个解决方案有一个简单的缺陷:当我完成编辑其中一个“隐藏”文本字段并触摸另一个文本字段时,键盘消失,视图向下移动,视图再次向上移动,键盘重新出现。

是否有可能防止键盘在两个编辑(“隐藏”文本字段)之间消失和重新出现 - 以便只有当所选文本字段从键盘隐藏的文本字段变为可以键入的文本字段时,视图才会移动不被隐藏)?

7 个答案:

答案 0 :(得分:47)

此解决方案基于ComSubVie的解决方案。

优点:

  • 它支持设备旋转 - 适用于所有方向;
  • 它不会对动画持续时间和曲线的值进行硬编码,而是从键盘通知中读取它们;
  • 它利用UIKeyboardWillShowNotification代替UIKeyboardDidShowNotification来同步键盘动画和自定义操作;
  • 它不使用已弃用的UIKeyboardBoundsUserInfoKey;
  • 由于按下国际键,它处理键盘调整大小;
  • 通过取消注册键盘事件来修复内存泄漏;
  • 所有键盘处理代码都封装在一个单独的类中 - KBKeyboardHandler;
  • 灵活性 - KBKeyboardHandler课程可以轻松扩展/修改,以更好地满足特定需求;

限制:

  • 适用于iOS 4及更高版本,需要进行少量修改才能支持旧版本;
  • 适用于具有单个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

<强> 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

@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。

答案 1 :(得分:30)

我刚刚解决了这个问题。该解决方案是UIKeyboardDidShowNotificationUIKeyboardDidHideNotification观察者与上述textFieldDidBeginEditing:textFieldDidEndEditing:方法的组合。

您需要另外三个变量,一个用于存储当前选定的UITextField(我已命名为activeField),一个用于指示当前视图是否已移动,另一个用于指示是否显示键盘。

这就是两个UITextField委托方法现在的样子:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    activeField = nil;
    // Additional Code
}

加载视图时,会创建以下两个观察者:

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

相应的方法实现如下:

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

此代码现在按预期工作。键盘仅在按下“完成”按钮时被解除,否则它将保持可见状态并且视图不会移动。

作为补充说明,我认为通过询问animationDuration对象可以动态获取NSNotification,因为我已经使用了类似的解决方案,但没有让它工作(它现在做了。)

答案 2 :(得分:2)

此视图控制器必须为UITextView委托,您必须在self.textview.delegate = self

中设置viewdidload
 -(void) textViewDidBeginEditing:(UITextView *)textView
    {
        NSLog(@"%f",self.view.frame.origin.y);
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:0.25f];
        CGRect frame = self.view.frame;
        frame.origin.y =frame.origin.y -204;
        [self.view setFrame:frame];
        [UIView commitAnimations];
    }

-(void) textViewDidEndEditing:(UITextView *)textView
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.25f];
    CGRect frame = self.view.frame;
    frame.origin.y = frame.origin.y + 204;
    [self.view setFrame:frame];
    [UIView commitAnimations];
}

答案 3 :(得分:0)

  

我的问题只是简单的事情   只是给UIScrollview出口。   为视图中的每个文本字段设置唯一的Tag属性。

-(void)textFieldDidBeginEditing:(UITextField *)textField
    {   
        switch (textField.tag)
        {
            case 2:    //can be your textfiled tag
              { CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-150); 
                                           //set figure y-150 as per your comfirt
                  [scrollview setContentOffset:scrollPoint animated:YES]; 
             }break;

              case 3:   
              { CGPoint scrollPoint = CGPointMake(0, yourtextfield.frame.origin.y-180); 
                                           //set figure y-180 as per your comfirt
                  [scrollview setContentOffset:scrollPoint animated:YES]; 
             }break;

             ...

         }
    }

    -(void)textFieldDidEndEditing:(UITextField *)textField{

        if(textField.tag==3){
            [scrollview setContentOffset:CGPointZero animated:YES];
                }
         //set the last textfield when you want to disappear keyboard.
    }

答案 4 :(得分:0)

Write below code in your view controller. tbl is your table view. 

-(void)viewWillAppear:(BOOL)animated{


    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

-(void) viewWillDisappear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillChangeFrameNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}



#pragma mark - Keyboard Methods
-(void)keyboardWillShow:(NSNotification *)notification
{
//    375 × 667  ( 750 × 1334 ) iPhone 6
    //414 × 736
    CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    int H = [[UIScreen mainScreen] bounds].size.height - 64- 20 -keyboardRect.size.height;
    [UIView animateWithDuration:0.5 animations:^{
        tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
    }];
}

-(void)keyboardWillChangeFrame:(NSNotification *)notification
{
    CGRect keyboardRect = [[[notification userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
//    int H = IS_IPHONE_5?504-keyboardRect.size.height:416-keyboardRect.size.height;
     int H = [[UIScreen mainScreen] bounds].size.height - 64- 20  -keyboardRect.size.height;
    [UIView animateWithDuration:0.5 animations:^{
        //        scroll.frame = rect;
        tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, H, tbl.contentInset.right);
    }];
}


-(void)keyboardWillHide:(NSNotification *)notification
{

    [UIView animateWithDuration:0.3 animations:^{
        //        scroll.frame = rect;
        tbl.contentInset = UIEdgeInsetsMake(tbl.contentInset.top, tbl.contentInset.left, 0, tbl.contentInset.right);
    }];
}

答案 5 :(得分:0)

非常简单的解决方案,适用于所有屏幕尺寸

首先,您必须将UITextFields嵌入到UIScrollView中。在我的例子中,我有几个UITextFields和一个UITextView。

enter image description here

然后你必须继承UITextFieldDelegate,UITextViewDelegate。

class SettingsVC: UIViewController, UITextFieldDelegate, UITextViewDelegate

将textfield&textview&textview的代表分配给自己。

fullNameTextField.delegate = self usernameTextField.delegate = self websiteTextField.delegate = self profileDescription.delegate = self

然后使用此代码:

&#13;
&#13;
var editingTextInput: UIView!


override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self,
                                           selector: #selector(self.keyboardShown(notification:)),
                                           name: NSNotification.Name.UIKeyboardDidShow,
                                           object: nil)
    

  }
  
    override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
  }
  
  func keyboardShown(notification: NSNotification) {
    
    if let infoKey  = notification.userInfo?[UIKeyboardFrameEndUserInfoKey],
      let rawFrame = (infoKey as AnyObject).cgRectValue {
      
      let keyboardFrame = view.convert(rawFrame, to: view)
      let editingTextInputFrame = self.editingTextInput.convert(self.editingTextInput.frame, to: view)

      
      if editingTextInputFrame.maxY > keyboardFrame.minY{
        
        let diff = keyboardFrame.minY - editingTextInputFrame.maxY
        containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
        
      }
    }
  }
  
  func textFieldDidBeginEditing(_ textField: UITextField) {
    self.editingTextInput = textField
  }
  
  func textViewDidBeginEditing(_ textView: UITextView) {
    self.editingTextInput = textView
  }
  
  func textFieldDidEndEditing(_ textField: UITextField) {
    containerScrollView.setContentOffset(CGPoint.zero, animated: true)
  }
  
  func textViewDidEndEditing(_ textView: UITextView) {
    containerScrollView.setContentOffset(CGPoint.zero, animated: true)
  }
&#13;
&#13;
&#13;

简而言之,您订阅了UIKeyboardDidShow通知。 当您点击textField或显示textView键盘时,您可以轻触键盘的输入元素的框架和框架。将它们转换为viewController的坐标系,并将输入元素的最低点与键盘的最高点进行比较。如果元素的下半部分低于键盘的最高部分,则将containerScrollView的偏移设置为它们之间的差异。

&#13;
&#13;
if editingTextInputFrame.maxY > keyboardFrame.minY{
            
            let diff = keyboardFrame.minY - editingTextInputFrame.maxY
            containerScrollView.setContentOffset(CGPoint(x: 0, y: -diff), animated: true)
            
          }
&#13;
&#13;
&#13;

res1 res2

答案 6 :(得分:0)

就像我在this answer中提到的那样:

我已经根据自己的需要开发了一个框架,以更好地解决此问题,并将其公开。它不仅适用于UITextField和UITextView,它还适用于任何采用UITextInput协议(如UITextField和UITextView)的自定义UIView,并提供了许多有用的功能。您可以通过Carthage,CocoaPods或Swift Package Manager安装它。

ODScrollView GitHub

ODScrollView Medium

ODScrollView只是一个UIScrollView,它会根据键盘的可见性自动垂直移动UITextField和UITextView之类的可编辑文本区域,以提供更好的用户体验。

功能

  • 当键盘出现/消失时,自动上/下移动采用UITextInput协议的第一响应者UIView,例如UITextField,UITextView,UISearchTextField或任何采用UITextInput协议的自定义UIView。
    • 请注意,如果UITextInput的框架不适合ODScrollView和键盘之间的剩余区域,则ODScrollView会根据光标位置而不是框架来调整UITextInput。在这种情况下,可以使用“ trackTextInputCursor”功能。 Example
  • 可以为.Top和.Bottom调整方向设置将调整边距分别应用于每个UITextInput。默认情况下为20 CGFloat。

  • 可以分别为每个UITextInput启用/禁用调整。默认为true。

  • 调整方向-.Top,.Center和.Bottom-可以分别应用于每个UITextInput。默认为底部。 Example

  • 调整选项确定ODScrollView的调整方式。始终默认情况下。
    • 。总是:不论UITextInput与显示的键盘是否重叠,ODScrollView总是调整放置在ODScrollView中任何位置的UITextInput。 Example
    • .IfNeeded:ODScrollView仅在与显示的键盘重叠时调整UITextInput。 Example
  • 除了UIScrollView.keyboardDismissModes外,还可以通过点击ODScrollViewDelegate提供的UIView来关闭键盘。关闭键盘后,ODScrollView可以返回其原始位置。默认为nil和false。 Example

用法

1-首先,您需要正确设置ODScrollView及其内容视图。由于ODScrollView只是一个UIScrollView,因此可以像对UIScrollView一样执行ODScrollView。由您使用情节提要或以编程方式创建ODScrollView取决于您。

如果要以编程方式创建ODScrollView,则可以从第4步继续。

在Storyboard中创建UIScrollView的建议方法

- If you are using Content Layout Guide and Frame Layout Guide:
    1.1 - scrollView: Place UIScrollView anywhere you want to use.  
    1.2 - contentView: Place UIView inside scrollView.
    1.3 - Set contentView's top, bottom, leading and trailing constraints to Content Layout Guide's constraints.
    1.4 - Set contentView's width equal to Frame Layout Guide's width.
    1.5 - Set contentView's height equal to Frame Layout Guide's height or set static height which is larger than scrollView's height.
    1.6 - Build your UI inside contentView.

- If you are NOT using Content Layout Guide and Frame Layout Guide:
    1.1 - scrollView: Place UIScrollView anywhere you want to use.  
    1.2 - contentView: Place UIView inside scrollView.
    1.3 - Set contentView's top, bottom, leading and trailing constraints to 0.
    1.4 - Set contentView's width equal to scrollView's width.
    1.5 - Set contentView's height equal to scrollView's superview's height or set static height which is larger than scrollView's height.
    1.6 - Build your UI inside contentView.

2-在Storyboard上的身份检查器中,将scrollView的类从UIScrollView更改为ODScrollView。

3-为ViewController上的scrollView和contentView创建IBOutlets。

4-在ViewController的ViewDidLoad()内部调用以下方法:

override func viewDidLoad() {
    super.viewDidLoad()

    //ODScrollView setup
    scrollView.registerContentView(contentView)
    scrollView.odScrollViewDelegate = self
}  

5-可选:您仍然可以使用UIScrollView的功能:

override func viewDidLoad() {
    super.viewDidLoad()

    //ODScrollView setup
    scrollView.registerContentView(contentView)
    scrollView.odScrollViewDelegate = self

    // UIScrollView setup
    scrollView.delegate = self // UIScrollView Delegate
    scrollView.keyboardDismissMode = .onDrag // UIScrollView keyboardDismissMode. Default is .none.

    UITextView_inside_contentView.delegate = self
}

6-:从ViewController中采用ODScrollViewDelegate并确定ODScrollView选项:

extension ViewController: ODScrollViewDelegate {

    // MARK:- State Notifiers: are responsible for notifiying ViewController about what is going on while adjusting. You don't have to do anything if you don't need them.

    // #Optional
    // Notifies when the keyboard showed.
    func keyboardDidShow(by scrollView: ODScrollView) {}

    // #Optional
    // Notifies before the UIScrollView adjustment.
    func scrollAdjustmentWillBegin(by scrollView: ODScrollView) {}

    // #Optional
    // Notifies after the UIScrollView adjustment.
    func scrollAdjustmentDidEnd(by scrollView: ODScrollView) {}

    // #Optional
    // Notifies when the keyboard hid.
    func keyboardDidHide(by scrollView: ODScrollView) {}

    // MARK:- Adjustment Settings

    // #Optional
    // Specifies the margin between UITextInput and ODScrollView's top or bottom constraint depending on AdjustmentDirection
    func adjustmentMargin(for textInput: UITextInput, inside scrollView: ODScrollView) -> CGFloat {
        if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
            return 20
        } else {
            return 40
        }
    }

    // #Optional
    // Specifies that whether adjustment is enabled or not for each UITextInput seperately.
    func adjustmentEnabled(for textInput: UITextInput, inside scrollView: ODScrollView) -> Bool {
        if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
            return true
        } else {
            return false
        }
    }


    // Specifies adjustment direction for each UITextInput. It means that  some of UITextInputs inside ODScrollView can be adjusted to the bottom, while others can be adjusted to center or top.
    func adjustmentDirection(selected textInput: UITextInput, inside scrollView: ODScrollView) -> AdjustmentDirection {
        if let textField = textInput as? UITextField, textField == self.UITextField_inside_contentView {
            return .bottom
        } else {
            return .center
        }
    }

    /**
     - Always : ODScrollView always adjusts the UITextInput which is placed anywhere in the ODScrollView.
     - IfNeeded : ODScrollView only adjusts the UITextInput if it overlaps with the shown keyboard.
     */
    func adjustmentOption(for scrollView: ODScrollView) -> AdjustmentOption {
        .Always
    }

    // MARK: - Hiding Keyboard Settings

    /**
     #Optional

     Provides a view for tap gesture that hides keyboard.

     By default, keyboard can be dismissed by keyboardDismissMode of UIScrollView.

     keyboardDismissMode = .none
     keyboardDismissMode = .onDrag
     keyboardDismissMode = .interactive

     Beside above settings:

     - Returning UIView from this, lets you to hide the keyboard by tapping the UIView you provide, and also be able to use isResettingAdjustmentEnabled(for scrollView: ODScrollView) setting.

     - If you return nil instead of UIView object, It means that hiding the keyboard by tapping is disabled.
     */
    func hideKeyboardByTappingToView(for scrollView: ODScrollView) -> UIView? {
        self.view
    }

    /**
     #Optional

     Resets the scroll view offset - which is adjusted before - to beginning its position after keyboard hid by tapping to the provided UIView via hideKeyboardByTappingToView.

     ## IMPORTANT:
     This feature requires a UIView that is provided by hideKeyboardByTappingToView().
     */
    func isResettingAdjustmentEnabled(for scrollView: ODScrollView) -> Bool {
        true
    }
}

7-可选:在多行UITextInput中键入光标与键盘重叠时,可以调整ODScrollView。键入时会触发的UITextInput函数必须调用trackTextInputCursor(用于UITextInput)。

/**
## IMPORTANT:
This feature is not going to work unless textView is subView of _ODScrollView
*/
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
       _ODScrollView.trackTextInputCursor(for textView)
   return true
}