美文网首页
h5页面输入框无法自动获焦、错位等问题

h5页面输入框无法自动获焦、错位等问题

作者: coder丶L | 来源:发表于2019-06-05 21:05 被阅读0次

    一、IOS中h5页面输入框无法自动获焦

    作为一名码农,最怕的应该就是BUG了.不过我们也正是在项目和bug中成长的.
    然而IOS中h5页面的输入框自动获焦问题,困扰了我很久,用过autofocus属性、focus()方法、甚至是用过vue.js的自定义指令去模拟点击输入框:

    directives: {
        trigger: {
          inserted(el, binging) {
            setTimeout(() => {
              el.click();
            }, 200);
          }
        }
      },
    

    但问题依然没有得到完美解决.
    既然安卓是可以的,为什么IOS中就不行了呢?是IOS不支持?那么可以让IOS支持吗?咱是新员工,也不敢贸然去和IOS老员工"抬杠"啊.和别人理论是需要依据的,首先从webView开始研究,发现webView常用的控件有UIWebView和WKWebView等.
    UIWebView有一个 keyboardDisplayRequiresUserAction属性,默认为YES。如果设置为YES,用户必须明确的点击页面上的元素或者相关联的输入页面来显示键盘;如果设置为NO,一个元素的焦点事件导致输入视图的显示和自动关联这个元素。那么,如果我们加载一个Web页面时,想一开始就唤起键盘,我们除了需要设置输入框的focus外,还需要IOS同事将webView中的keyboardDisplayRequiresUserAction设置为false.然而到此还没有结束,因为WKWebView是没有这个属性的,但又想做到以上效果,怎么办呢?只能通过runtime处理了,添加如下代码并调用:

    #import <objc/runtime.h>
    @implementation WebViewInjection
    + (void)allowDisplayingKeyboardWithoutUserAction {
        Class class = NSClassFromString(@"WKContentView");
        NSOperatingSystemVersion iOS_11_3_0 = (NSOperatingSystemVersion){11, 3, 0};
        if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion: iOS_11_3_0]) {
            SEL selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:");
            Method method = class_getInstanceMethod(class, selector);
            IMP original = method_getImplementation(method);
            IMP override = imp_implementationWithBlock(^void(id me, void* arg0, BOOL arg1, BOOL arg2, BOOL arg3, id arg4) {
                ((void (*)(id, SEL, void*, BOOL, BOOL, BOOL, id))original)(me, selector, arg0, TRUE, arg2, arg3, arg4);
            });
            method_setImplementation(method, override);
        } else {
            SEL selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:");
            Method method = class_getInstanceMethod(class, selector);
            IMP original = method_getImplementation(method);
            IMP override = imp_implementationWithBlock(^void(id me, void* arg0, BOOL arg1, BOOL arg2, id arg3) {
                ((void (*)(id, SEL, void*, BOOL, BOOL, id))original)(me, selector, arg0, TRUE, arg2, arg3);
            });
            method_setImplementation(method, override);
        }
    }
    @end
    

    然后就可以让输入框自动获焦了.
    到此,输入框的自动获焦问题也就解决了.

    二、输入框错位

    页面中输入框是使用fixed悬浮在页面底部的,当输入框获焦后,会被键盘顶起,悬浮在键盘上方.然而,又是在IOS中出了问题,有时候输入框并没有被顶起,通过不断换行(用的textarea)撑起高度发现输入框位置依然在底部并没有被顶起.
    解决办法:
    输入框父元素使用fixed悬浮在顶部,输入框obsolute定位在父元素底部,监听窗口改变事件,把父元素高度绑定为获取的浏览器窗口可视高度

    <div class="textBox"  :style="{'height':height}">
            <textarea class="textInput" id="textarea"></textarea>
    </div>
    
    .textBox
      position fixed
      top 0
      left 0
      width 100%
      height 100%
      z-index 30
      .textInput
        background #FFFFFF
        border 2px solid #C8C8C8
        border-radius 36px
        line-height 33px
        font-family PingFangSC-Regular
        font-size 24px
        color #333333
        outline none
        padding 12px 30px
        width 620px
        height 62px
        overflow-y scroll
        resize none
    
    window.addEventListener("resize", function() {
          var viewHeight =
            window.innerHeight ||
            document.documentElement.clientHeight ||
            document.body.clientHeight;
          this.height = viewHeight;
    });
    

    三、textarea根据内容自动调整高度

    网上找的,直接贴代码吧:

    var text = document.getElementById("textarea");
    this.autoHeight(text, 24); 
    autoHeight(elem, extra, maxHeight) {
    //elem:textarea
    //extra:
    //maxHeight:最大高度,如不需要可不传
          extra = extra || 0;
          var isFirefox = !!document.getBoxObjectFor || "mozInnerScreenX" in window,
            isOpera = !!window.opera && !!window.opera.toString().indexOf("Opera"),
            addEvent = function(type, callback) {
              elem.addEventListener
                ? elem.addEventListener(type, callback, false)
                : elem.attachEvent("on" + type, callback);
            },
            getStyle = elem.currentStyle
              ? function(name) {
                  var val = elem.currentStyle[name];
    
                  if (name === "height" && val.search(/px/i) !== 1) {
                    var rect = elem.getBoundingClientRect();
                    return (
                      rect.bottom -
                      rect.top -
                      parseFloat(getStyle("paddingTop")) -
                      parseFloat(getStyle("paddingBottom")) +
                      "px"
                    );
                  }
    
                  return val;
                }
              : function(name) {
                  return getComputedStyle(elem, null)[name];
                },
            minHeight = parseFloat(getStyle("height"));
    
          elem.style.resize = "none";
    
          var change = function() {
            var scrollTop,
              height,
              padding = 0,
              style = elem.style;
    
            if (elem._length === elem.value.length) return;
            elem._length = elem.value.length;
    
            if (!isFirefox && !isOpera) {
              padding =
                parseInt(getStyle("paddingTop")) +
                parseInt(getStyle("paddingBottom"));
            }
            elem.style.height = minHeight + "px";
            if (elem.scrollHeight > minHeight) {
              if (maxHeight && elem.scrollHeight > maxHeight) {
                height = maxHeight - padding;
                style.overflowY = "auto";
              } else {
                height = elem.scrollHeight - padding;
                style.overflowY = "hidden";
              }
              style.height = height + extra + "px";
              elem.currHeight = parseInt(style.height);
            }
          };
          addEvent("propertychange", change);
          addEvent("input", change);
          addEvent("focus", change);
          change();
        }
    

    四、框架中输入框绑定focus、blur事件无效

    <mt-search v-model="searchValue" cancel-text="取消" placeholder="请输入关键字" @focus="searchList"></mt-search>
    

    项目中使用的mintUI,输入框组件使用@focus没有生效。
    focus、blur事件一般只对input、textarea等标签起作用。检查元素可以发现使用的输入框组件的input外面还有几层div元素,使用@focus只是把事件绑定到了组件的最外层元素。那么我们可以通过事件捕获来解决问题。

    <mt-search v-model="searchValue" cancel-text="取消" placeholder="请输入关键字" @focus.native.capture="searchList"></mt-search>
    

    相关文章

      网友评论

          本文标题:h5页面输入框无法自动获焦、错位等问题

          本文链接:https://www.haomeiwen.com/subject/lvbsxctx.html