菜鸡
菜鸡
  • 发布:2018-02-04 20:21
  • 更新:2019-01-12 13:48
  • 阅读:8366

非native.js/原生插件监听键盘弹出/收起事件,妈妈再也不用担心我苹果和安卓键盘弹出方式不一样了

分类:MUI

##写在前面

  • 页面需要设置如下css样式,
  • 页面里实在没办法设置成如下所述样式的,
  • 我还没找到办法实现监听键盘弹出/收起
html,body{width:100%;height:100%;overflow:hidden;}

##可解决的问题:
1.ios输入文字时header/input不听话
2. 弹出/收起键盘时要想要做一些事情
3. 等问题

##心路历程
(唔...应该可以跳过)

1.这周六、日因为年前快放假了导致加班

2.刚刚好要写个聊天室的UI

3.聊天室顶部有个header.mui-bar.mui-bar-nav(由于一些原因,用不了父页面的header)

4.底部有个类似手机QQ的输入框
(但是比较简单,只有个输入框和发送按钮)

5.然后重点来了,主角上场了——坑爹的ios

6.所以,输入文字的时候header和底部的textarea开始不听话了

本人又比较菜,大佬们说的各种什么解决方案,
不知道是不是我姿势不对,好像都不是很有效,
具体什么方法,都在公司电脑的浏览器记录里,
就不去翻了,css布局倒是学到了一些,
js方面的,试了的不管用,要不就是很要原生插件配合什么的,
反正最终效果挺不满意的.


##进入正题

###开发调试信息

  • 安卓:一加三
  • 苹果:6s
  • IDE:hb8.8.1&hb8.8.5

###dom结构

header.mui-bar.mui-bar-nav
div.mui-content
footer.mui-input-row>span.mui-btn+textarea

###主要样式

/*总体布局*/  
html,body,.mui-content{width:100%;height:100%;overflow:hidden;}  
/*顶部header*/  
header.mui-bar.mui-bar-nav{width: 100%;position: absolute;top: 0px;}  
/*变化动画,可删除*/  
.mui-focusin header.mui-bar.mui-bar-nav{transition: top 0.5s;}  
/*聊天内容*/  
header.mui-bar.mui-bar-nav~.mui-content{position: absolute;top: 0px;bottom: 50px;padding: 44px 0px 50px;overflow: auto;}  
/*底部*/  
footer.mui-input-row{width: 100%;height: 50px;position: absolute;bottom: 0px;padding: 5px 10px;background-color: #EFEFF4;border-top: 1px solid #DEDEDE;}  
/*发送按钮*/  
footer.mui-input-row>span.mui-btn{padding: 10px 0px;margin: 1.5px 0px;}  
/*输入框*/  
footer.mui-input-row>.mui-btn~textarea{width: 82.5%;height: 40px;line-height: 30px;margin-right: 2.5%;padding: 5px 0px;}

###解决过程

  • 发现ios弹出键盘时,是用键盘将webview"顶起来"弹出键盘的
  • (ios在h5+中的webview在弹出键盘时似乎不会触发scroll事件)
  • (需要设置softinputMode:adjustResize以触发键盘弹出/收起事件)
  • 安卓就是挤压webview咯
  • 上面两点,想必各位dalao比我了解
  • 所以,我何不监听对应的事件呢

###好了,上干货

  
// 这些demo代码是结合解决"ios的浏览器端输入文字时header/input可能不听话"问题来写的  
// 有其他需求可结合具体逻辑修改  
(function($,doc,win){  
    $.qs = function(selector,context){  
        return $.qsa(selector,context)[0];  
    }  
    var body = doc.body,  
        header = $.qs('header',body),  
        header_style = header.style,  
        content = $.qs('.mui-content',body),  
        content_style = content.style,  
        footer = $.qs('footer',body),  
        text_input = $.qs('textarea',footer),  
        init_width = body.offsetWidth,  
        init_height = body.offsetHeight,  
        is_web_ios = $.os.ios&&!$.os.plus&&!$.os.android,  
        tap_y = 0;  
    // 阻止window滚动  
    function block_window_scroll(e){  
        e.preventDefault();  
        e.stopPropagation();  
    }  
    // 阻止在header/footer上触发iso网页上的滚动/弹性拖拽  
    // 如果在获得焦点时通过header/footer触发了滚动/弹性拖拽,  
    // 会有不想看到的情况  
    header.addEventListener($.EVENT_MOVE,block_window_scroll);  
    footer.addEventListener($.EVENT_MOVE,block_window_scroll);  
    //阻止已经滚动了顶部/底部时,继续拖拽  
    content.addEventListener($.EVENT_START,function(e){  
        tap_y = e.touches[0].screenY;  
    });  
    content.addEventListener($.EVENT_MOVE,function(e){  
        ((!(this.scrollTop)&&(e.touches[0].screenY - tap_y)>0)||((this.scrollTop == (this.scrollHeight-  this.offsetHeight))&&(e.touches[0].screenY - tap_y)<0))&&block_window_scroll(e);  
    });  
    // 键盘弹出事件  
    is_web_ios&&win.addEventListener('keyboardShow',function(e){  
        var keyboard_height = e.detail.keyboardHeight;  
        header_style.top = keyboard_height + 'px';  
        content_style.paddingTop = keyboard_height + 44 + 'px';  
    });  
    // 键盘关闭事件  
    is_web_ios&&win.addEventListener('keyboardHide',function(e){  
        header.removeAttribute('style');  
        content.removeAttribute('style');  
    });  
    // 如果是ios,在浏览器第一次弹出键盘时  
    // 我的6s(ios 11.2.1)footer会错位(浏览器会,html5+的webview不会)  
    // 需要在第二次打开时才不会错位  
    // (第一次不是指的刷新后的第一次)  
    // (而是访问网页后的第一次,哪怕是刷新了,但不是访问的第一次,就不会出现问题)  
    // 很是奇怪,所以在第一次想要弹出键盘时,先阻止一下,  
    // 让用户以为没点到,用户自然会重点一次  
    is_web_ios&&text_input.addEventListener('focus',(function(){  
        var first_focus = true;  
        return function(){  
            if (first_focus) {  
                this.blur();  
                return !(first_focus = false);  
            }  
        }  
    })());  
    // 键盘弹出/收起实现  
    // ios的webview通过设置softinputMode:'adjustResize',  
    // 表现会和android一样不会有header/footer不受控制的情况  
    $.os.ios&&$.os.plus?null:(is_web_ios?win:body).addEventListener(is_web_ios?'scroll':'resize',(function(){  
        var timer;  
        return is_web_ios?function(){  
            clearTimeout(timer);  
            var scroll_height = win.scrollY;  
            // 实时触发  
            // scroll_height>=0&&$.trigger(win,scroll_height?'keyboardShow':'keyboardHide',{  
            //     keyboardHeight:scroll_height  
            // });  
            // 弹出后&收起后触发  
            timer = setTimeout(scroll_height>=0?function(){  
                $.trigger(win,scroll_height?'keyboardShow':'keyboardHide',{  
                    keyboardHeight:scroll_height  
                });  
            }:$.noop,100);  
        }:function(){  
            clearTimeout(timer);  
            if(body.offsetWidth != init_width){ //横竖屏的resize  
                init_height = body.offsetHeight;  
                init_width = body.offsetWidth;  
                return;  
            }  
            var resize_height = init_height - body.offsetHeight;  
            // 实时触发  
            // $.trigger(win,resize_height?'keyboardShow':'keyboardHide',{  
            //     keyboardHeight:resize_height  
            // });  
            // 弹出后&收起后触发  
            timer = setTimeout(function(){  
                $.trigger(win,resize_height?'keyboardShow':'keyboardHide',{  
                    keyboardHeight:resize_height  
                });  
            },100);  
        }  
    })());  
    $.plusReady(function(){  
        // ios在h5+环境中需要设置softinputMode:'adjustResize'  
        // 通过resize来监听键盘弹出/收起  
        // 但是ios的"第一次"获得焦点时  
        // 键盘高度似乎不准确  
        // 不知道是什么原因  
        // 个人觉得和上面监听focus注释描述的问题有关  
        $.os.ios&&plus.webview.currentWebview().setStyle({  
            softinputMode:'adjustResize'  
        });  
    });  
})(mui,document,window);  

##demo代码见附件

谁推荐个苹果手机上好用的录屏软件,我去录个gif上来

5 关注 分享
水灵退散 BoredApe lhyh 3***@qq.com s***@163.com

要回复文章请先登录注册

x***@126.com

x***@126.com

https://blog.csdn.net/yanxinyun1990/article/details/84948043
2019-01-12 13:48
菜鸡

菜鸡 (作者)

回复 猫猫猫猫 :
了解
2018-02-05 11:39
猫猫猫猫

猫猫猫猫

我们之前就是用插件方式实现,如果你也遇到我说的问题,可以尝试这个解决方案:通过js 注入高度修复和resize事件。
2018-02-05 11:01
猫猫猫猫

猫猫猫猫

回复 菜鸡 :
浏览器是顺便测试的,用于对比。
主要想表达的是部分办法不触发resize事件和获取高度错误。
2018-02-05 10:55
菜鸡

菜鸡 (作者)

回复 lhyh :
问答社区吹水我只服昊神
2018-02-05 10:39
菜鸡

菜鸡 (作者)

回复 猫猫猫猫 :
浏览器端不用resize做键盘弹出/收起的监听,webview上resize事件有变化,就不会有大问题
2018-02-05 10:39
猫猫猫猫

猫猫猫猫

关于录屏,我推荐用mac自带的 quicktime 连接手机录。
2018-02-05 10:12
猫猫猫猫

猫猫猫猫

回复 菜鸡 :
好的,测试结果出来了:https://www.jianshu.com/p/f5253b3ab100
2018-02-05 10:11
菜鸡

菜鸡 (作者)

回复 猫猫猫猫 :
没有设备,请你帮我测试下
2018-02-05 10:04
猫猫猫猫

猫猫猫猫

可能有个不幸的消息。
你是否分别测试过 iOS8、iOS9、iOS10.0、10.2、iOS10.3.1、iOS10.3.3、iOS11
2018-02-05 10:01