H5 input 浮层 键盘遮挡

这个问题,其实在前端是个老生常谈的问题。

在生产环境中,我们是嵌入到 app 中使用的 H5 降级页面,在去哪儿和携程的 app 中的 webview 容器,表现不一致

携程的 app 表现比较正常,和一般浏览器表现类似,但是去哪儿,有点奇葩。键盘弹起来之后,页面高度依旧不变,着实费解。

 

最终的解决方案其实是在携程中使用 scrollIntoViewIfNeeded

在比较奇葩的去哪儿使用监听 focus,在底部加 padding 的做法。之所以不使用定位,是因为,键盘高度我不确定。所以我给 padding,这样白色的区域即使大一点也可以接受。不至于出现浮层和键盘中间断层。

具体的代码截取了部分。其实,主要是个思路。代码自己实现更好,因为涉及到调试,不自己写的话,心里也没底。

我是使用 ts+react实现,另外,我认为尽量不要使用定位来实现,因为你不知道哪个 webview 就会出现幺蛾子。当然了,定位也解决不了键盘遮挡的问题

!核心函数,计算 dom 位置

// 计算需要提升的元素 : dom的位置
    const movePanel = (enevt: string) => {
      if (judgeDeviceType.isIOS) {
        const dom = codeRef.current.closest(".css-3pxmmn");
        if (dom) {
          console.log("enevt", enevt);
          // 这里是区分 去哪儿端,去哪儿的 webview 容器,比较奇葩,scrollIntoView 不生效,
          // 虽然页面被推上去了,但是页面高度不变,所以特殊处理
          if (window.location.href.indexOf("qunar") > -1) {
            if (enevt === "blur") {
              return setTimeout(() => {
                dom.style.paddingBottom = 0;
              }, 0);
            }
            if (enevt === "focus") {
              return setTimeout(() => {
                dom.style.paddingBottom = "380px";
              }, 300);
            }
            if (enevt === "click") {
              return setTimeout(() => {
                dom.style.paddingBottom = "380px";
              }, 0);
            }
          }
          return setTimeout(() => {
            dom.scrollIntoViewIfNeeded(true);
          }, 300);
        }
      }
    };

首次展示的时候,触发一次 focus 


    // 首次展示的时候,调用一次 focus
    // codeRef.current 代表需要 focus 的 input 元素
    useEffect(() => {
      let moveTimer: any = null;
      if (visiable && codeRef.current) {
        codeRef.current.focus();
        moveTimer = movePanel("focus");
      }
      return () => {
        clearTimeout(moveTimer);
      };
    }, [visiable, codeRef.current]);

操作浮层上的 input 元素,触发重新定位函数

 // 注册 focus, click, blur 事件
    // drawerRef.current 代表需要 改变定位的浮层容器
    useEffect(() => {
      let moveTimer: any = null;
      if (
        drawerRef &&
        drawerRef.current &&
        codeRef &&
        codeRef.current &&
        !isBindListener
      ) {
        codeRef.current.addEventListener("focus", () => {
          moveTimer = movePanel("focus");
        });
        codeRef.current.addEventListener("click", () => {
          moveTimer = movePanel("click");
          // drawerRef.current.style.bottom = "240px";
        });
        codeRef.current.addEventListener("blur", () => {
          moveTimer = movePanel("blur");
        });
      }
      isBindListener = true;
      return () => {
        clearTimeout(moveTimer);
      };
    }, [
      drawerRef,
      drawerRef.current,
      codeRef,
      codeRef.current,
      isBindListener,
    ]);

 

你可能感兴趣的:(javascript,前端)