混合开发中WKWebView调用原生(三方)键盘(或类似键盘),由原生实现输入域升降WebView不遮挡输入框的方法

 

以html的button标签为例,避免系统自动适配input键盘升降的偏移。

 

原理:html加载完成后在onload中把所有输入框信息告诉原生,原生把所有输入框用原生代码写成一样的,add到WKScrollow上,然后按原生的正常升降方法。

效果:

webview使用原生键盘升降

 

 

下面是实现代码:

 

h5




    
        
        

        H5向Native通信
        

        
    
    
    
        
        

         
        

 

h5与原生交互之原生代码webviewController


@property (nonatomic ,retain)NSMutableDictionary      *nativeTextFiledMutableDic;



- (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
    
    NSLog(@"%@",message.body);
    NSLog(@"%@",message.frameInfo);
    NSLog(@"%@",message.name);
    
 if([message.name isEqualToString:@"createNativeTextFiled"]){
              
       //创建原生输入框加载到WKScrollView上

         NSArray *arr = message.body;
        
        _nativeTextFiledMutableDic = [[NSMutableDictionary alloc] initWithCapacity:arr.count];
        
        for (NSDictionary *dic in arr) {
            float top = [dic[@"top"] floatValue];
            float left = [dic[@"left"] floatValue];
            float height = [dic[@"height"] floatValue];
            float width = [dic[@"width"] floatValue];
            
            NSString *text = [dic[@"text"] stringValue];
            
            UIView *wkScrollView = _myWKWebView.subviews[0];//WKScrollView
            
            YYYTextField *nativeTextField = [[YYYTextField alloc] init];
            nativeTextField.frame =CGRectMake(left, top, width, height);
            nativeTextField.backgroundColor = [UIColor redColor];
            nativeTextField.hidden = NO;
            nativeTextField.webView = _myWKWebView;
            nativeTextField.text = text;
            nativeTextField.idStr = [dic[@"id"] stringValue];

            [wkScrollView addSubview:nativeTextField];
            [nativeTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
            [nativeTextField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventValueChanged];
            [_nativeTextFiledMutableDic setObject:nativeTextField forKey:[dic[@"id"] stringValue]];

          
            
        }
        NSLog(@"");
    } else if([message.name isEqualToString:@"useNativeTextFiled"]){
       
        //这个方法不是每次都走 点到后面的h5标签后 调起对应原生控件
        //h5标签加上disabled="disabled"就不会走到这里了
        NSDictionary *dic = message.body;
        NSString *textId = [dic[@"id"] stringValue];
        
        UITextField *filed =  [_nativeTextFiledMutableDic objectForKey:textId];
        [filed becomeFirstResponder];
        }
}



- (void)textFieldDidChange:(YYYTextField *)textField; {
    
    //改变文字同步到h5输入框或button文字

    NSString *javaScriptStr = [NSString stringWithFormat:@"changeTextById('%@','%@');",textField.idStr,textField.text];
    [_myWKWebView evaluateJavaScript:javaScriptStr completionHandler:^(NSString *str , NSError * _Nullable error) {
        NSLog(@"");
    }];
}

 

YYYTextField

 



#import 

NS_ASSUME_NONNULL_BEGIN

@interface YYYTextField : UITextField
@property(nonatomic,weak)WKWebView *webView;
@property(nonatomic,retain)NSString *idStr;
@property(nonatomic,assign)double keyBoardHeight;
- (double)getKeyBoardHeight;

@end

NS_ASSUME_NONNULL_END




#import "YYYTextField.h"
#import "SSSPublicKeyBoardMoveUpAndDown.h"

@implementation YYYTextField

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        //使用自己的升降 打开这行
        self.delegate = self;
        self.inputAccessoryView=nil;
        self.clearButtonMode = UITextFieldViewModeWhileEditing;
        
        //使用自己的升降 打开这行
        //获取系统键盘高度
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeTextFieldFrame:) name:UIKeyboardWillShowNotification object:nil];

        self.textColor = [UIColor blackColor];

    }
    return self;
}


//- (UIView *)inputView{
//    //这里模拟返回当前输入框的自定义键盘
//    //使用默认键盘可以注掉本方法
//    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 350)];
//    view.backgroundColor = [UIColor redColor];
//    return view;
//
//}

- (UIView *)inputAccessoryView{
    //textField加到wkscrollow时,解决键盘工具栏时有时无的问题
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 0.01)];
    view.backgroundColor = [UIColor redColor];
    return view;
}


- (void)changeTextFieldFrame:(NSNotification *)noti
{
    //获取系统键盘高度
    NSDictionary *userInfo = noti.userInfo;
    CGRect r = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    NSLog(@"打印一下%f",r.size.height);
    _keyBoardHeight = r.size.height;
    //
    //防止第一次点击后先升键盘,后走这个方法,导致键盘高度为0
    //
    if([self isFirstResponder]){
        [self textFieldDidBeginEditing:self];
    }
 
    
}

//开始编辑
- (void) textFieldDidBeginEditing:(UITextField *)textField{

    [SSSPublicKeyBoardMoveUpAndDown scrollView:textField andSuperView:[YYYTextField findScrollow:self] isUp:YES];

}
//点击return
- (BOOL)textFieldShouldReturn:(UITextField *)textField;{

    [textField resignFirstResponder];

    return YES;
}

//结束编辑  恢复WkWebView的frame
- (void)textFieldDidEndEditing:(UITextField *)textField{
        UIScrollView *scrollow = [YYYTextField findScrollow:self];
        scrollow = scrollow.superview;//WkWebView

        [UIView animateWithDuration:0.3 animations:^{
//            [(UIScrollView *)sco setContentOffset:CGPointMake(0, 0)];
            [(UIScrollView *)scrollow setSize:CGSizeMake(ScreenWidth, ScreenHeight)];
        } completion:^(BOOL finished) {
            
        }];

}


+ (UIScrollView *)findScrollow:(UIView *)_selfView{
    
    
    UIScrollView *scrollow = _selfView;

    while (![scrollow isKindOfClass:[UIScrollView class]]) {
        if (scrollow.superview == nil) {
            return nil;
        }
        scrollow = scrollow.superview;

        //特殊处理
        if ([scrollow isKindOfClass:NSClassFromString(@"UITableViewWrapperView")]) {
            scrollow = scrollow.superview;
        }
        


    }

    return scrollow;
}

- (void)dealloc{
    
    //获取系统键盘高度
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    
    NSLog(@"dealloc");
}

//移除输入框(点击空白地方 或者 return)
- (BOOL)resignFirstResponder{
        
    //解决输入框remove掉,键盘还在的问题
    BOOL isr = [super resignFirstResponder];
    return YES;
}

//获取系统键盘高度
- (double)getKeyBoardHeight{
    return _keyBoardHeight;
}


 

SSSPublicKeyBoardMoveUpAndDown   配合键盘进行页面升降

 

#import 
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
#define ScreenWidth [UIScreen mainScreen].bounds.size.width

#define IsIphoneX ((((ScreenWidth == 375) && (ScreenHeight == 812)  ) || \
((ScreenWidth == 414) && (ScreenHeight == 896)  )) ? 1 : 0)

/**
 配合键盘进行页面升降
 */
@interface SSSPublicKeyBoardMoveUpAndDown : NSObject

+ (void)scrollView:(UIView *)view andSuperView:(UIView*)mySuperview isUp:(BOOL)up;
- (void)scrollView:(UIView *)view andSuperView:(UIView*)mySuperview isUp:(BOOL)up;

@end



 

#import "SSSPublicKeyBoardMoveUpAndDown.h"
#import "YYYTextField.h"

@interface SSSPublicKeyBoardMoveUpAndDown ()

@property(nonatomic,retain)YYYTextField *textFiled;

@end

@implementation SSSPublicKeyBoardMoveUpAndDown

+ (void)scrollView:(UIView *)view andSuperView:(UIScrollView*)mySuperview isUp:(BOOL)up;{
    CGRect rect = view.frame;
    //坐标系转换
    CGRect resultRect = [view.superview convertRect:rect toView:mySuperview];

    rect.origin.y = resultRect.origin.y;
    
    
    SSSPublicKeyBoardMoveUpAndDown *upAndDown = [[SSSPublicKeyBoardMoveUpAndDown alloc]init];
    upAndDown.textFiled = (UITextField*)view;
    [upAndDown keyboardWillShow:rect direction:up andSuperView:mySuperview];
    
}

- (void)scrollView:(UIView *)view andSuperView:(UIScrollView*)mySuperview isUp:(BOOL)up;{
    CGRect rect = view.frame;
    //坐标系转换
    CGRect resultRect = [view.superview convertRect:rect toView:mySuperview];
    rect.origin.y = resultRect.origin.y;
    
    self.textFiled = (UITextField*)view;
    [self keyboardWillShow:rect direction:up andSuperView:mySuperview];
    
}


- (void)keyboardWillShow:(CGRect)rect direction:(BOOL)isUP andSuperView:(UIScrollView*)mySuperview
{
    int temp = ScreenHeight - [self differentKeyBoardHeight] - mySuperview.top;

    
    //视图上移的判断条件放宽20,
    if (rect.origin.y + rect.size.height >= temp - 20) {
        int distance_ = (rect.origin.y + rect.size.height) - temp;
        distance_ += 50;

        if (mySuperview.frame.origin.y <= 0) {
            CGRect rect = mySuperview.frame;
            rect.origin.y = 0;
            mySuperview.frame = rect;
        }
        [self setViewMovedUp:isUP distance:distance_ andSuperView: mySuperview];
    }else{
        //设置Superview的size
        [UIView animateWithDuration:0.3 animations:^{

            mySuperview.size = CGSizeMake(ScreenWidth, ScreenHeight - [self differentKeyBoardHeight]);
        } completion:^(BOOL finished) {
            
        }];
    }
  
}
- (double)differentKeyBoardHeight{
    //
    //不同的键盘计算不同的高度
    //
    double differentKeyBoardHeight = 0;
    
    UIView *inputView = _textFiled.inputView;
    NSLog(@"键盘高度%f",inputView.height);
    
 
    {//系统键盘
        
        if ([_textFiled  respondsToSelector:@selector(getKeyBoardHeight)]){
            differentKeyBoardHeight = [_textFiled getKeyBoardHeight];
        }
        if (IsIphoneX) {
            differentKeyBoardHeight -= 34;
        }
    }
    
    
    //_textFiled.inputView 系统键盘是 nil
    if (_textFiled.inputAccessoryView && _textFiled.inputView != nil) {
        differentKeyBoardHeight += _textFiled.inputAccessoryView.height;
    }
    
    
    return differentKeyBoardHeight;
}


- (void)setViewMovedUp:(BOOL)movedUp distance:(CGFloat)distance andSuperView:(UIScrollView*)mySuperview{
    
    double oldY = mySuperview.top;
    
    float y = 0.0;
    if (movedUp) {
        // If moving up, not only decrease the origin but increase the height so the view
        // covers the entire screen behind the keyboard.
        y -= distance;
    } else {
        // If moving down, not only increase the origin but decrease the height.
        y += distance;
    }
    CGRect rect = mySuperview.frame;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    // Make changes to the view's frame inside the animation block. They will be animated instead
    // of taking place immediately.
    rect.origin.y += (y - 60 - 20);
   
    if ([mySuperview isKindOfClass:[UITableView class]]) {
        rect.origin.y -= 64;
    }


         
   //wkscrollow的frame改变不了只能改wkwebview的
    mySuperview.superview.size = CGSizeMake(ScreenWidth, ( ScreenHeight - [self differentKeyBoardHeight] - oldY));
    //wkscrollow改变contentOffset
    mySuperview.contentOffset = CGPointMake(0, - rect.origin.y);
    
    
    //最多只到键盘上边挨着
    if(-rect.origin.y > (mySuperview.contentSize.height - mySuperview.height)){
         mySuperview.contentOffset = CGPointMake(0, (mySuperview.contentSize.height - mySuperview.height));
    }
        

    [UIView commitAnimations];
}

@end


 

 

 

 

 

 

 

 

 

你可能感兴趣的:(ios)