背景

笔者在使用 WebView 加载含有输入框的 H5 页面时,点击输入框后,输入框会被软键盘遮挡住,无法看到输入的内容,这很影响用户体验。

笔者想着这种业务场景比较常见,遂上网搜索一番,果不其然,有不少同志遇到这个问题,想来这个问题很好解决了。笔者一一尝试了同志们提供的解决方案,结果要不是没有作用,要不是效果不太满意,只好自己另辟蹊径了。

注:在笔者的业务场景中,App是全屏的,即没有顶部的系统栏,也没有底部的导航栏,所以笔者的解决方案,可能不适用于其他场景。

纪实

方案

好的,重新梳理下遇到的问题,目前的问题是:用户无法看到输入框里的内容,那么我们可以先让用户看到输入框里的内容。

笔者想到了第一种方案:**输入框被软键盘遮挡后,在软键盘输入时,可以在 H5 页面顶部实时显示输入框里的内容。**本方案解决了输入框被软键盘遮挡后看不到输入内容的问题,但是没有解决输入框被软键盘遮挡的问题,此方案一定程度上提升了用户体验,不过笔者认为本方案不是很完美,继续思考其他方案。

最后笔者想到了第二种方案,大体思路如下:

  • 笔者的业务场景,App是全屏的,所以整个 WebView 也是全屏的,
  • 在点击 H5 页面的输入框时,H5 获取当前输入框左下角的 Y 坐标,然后把左下角的 Y 坐标通知到 Android 原生,
  • Android 原生获取软键盘顶部的 Y 坐标与输入框左下角的 Y 坐标进行比较,如果小于左下角的 Y 坐标,则认为此时输入框被软键盘遮挡,需要将 WebView 向上滚动相应的距离以显示出来输入框,否则判断 WebView 当前的滚动距离是否为 0,如果不为 0 则取当前距离的负值作为滚动距离,否则就不滚动。

上述方案的文字描述可能比较绕,我们可以看下面的流程图跟上思路:

实现

接下来笔者根据上面的方案二进行代码上的具体实现:

首先是获取输入框左下角的 Y 坐标,这一步如果让前端来实现的话,是比较容易的,不过笔者认为方案二是一种比较通用的解决方案,可以提取出来作为二方库来使用,如果让其他使用二方库项目组的前端同志也来实现一次的话就比较麻烦了,所以在这一步,笔者选择了在 Android 端注入 JS 的方案:

ready();
document.addEventListener("readystatechange", function () {
    var readyState = document.readyState;
    if (readyState !== "loading") {
        console.log(readyState);
        ready();
    }
});
document.addEventListener("DOMContentLoaded", function () {
    console.log("DOMContentLoaded");
    ready();
});
function ready() {
    document.body.addEventListener("DOMNodeInserted", function () {
        webInput();
    });
    webInput();
}
function webInput() {
    var input = document.querySelectorAll("input") || [];
    console.log("input -> "   input.length);
    if (input.length === 0) {
        return;
    }
    input.forEach(function (value) {
        var type = value.getAttribute("type");
        console.log("type -> "   type);
        if (type === null
            || type === "number"
            || type === "search"
            || type === "password"
            || type === "tel"
            || type === "email"
            || type === "url"
            || type === "text") {
            value.removeEventListener("click", webInput2Android);
            value.removeEventListener("focus", webInput2Android);
            value.addEventListener("click", webInput2Android);
            value.addEventListener("focus", webInput2Android);
        }
    });
}
function webInput2Android() {
    console.log("webInput2Android");
    var offset = getOffset(this);
    var x = offset.x;
    var y = offset.y;
    console.log("x:y --> "   x   ":"   y);
    var width = this.offsetWidth;
    var height = this.offsetHeight;
    console.log("w:h --> "   width   ":"   height);
	// Send to Android
}
function getOffset (el) {
    var box = el.getBoundingClientRect();
    return {
        x: box.left   window.pageXOffset - document.documentElement.clientLeft,
        y: box.top   window.pageYOffset - document.documentElement.clientTop
    }
}

在 JS 中通过监听输入框的点击事件,在点击时获取输入框左上角的坐标和输入框的宽高,间接算出输入框左下角的坐标,然后通知到 Android 原生:

public void run() {
    Activity activity = mActivityReference.get();
    WebView webView = mWebViewReference.get();
    if (activity == null || webView == null) {
        return;
    }
    // JS 传入的输入框左下角 Y 坐标
    int bottom = mWebInput.getBottom();
    // 获取软键盘顶部的 Y 坐标
    int keyboardTop = KeyboardHelper.getKeyboardTop(activity);
    // WebView 当前滚动的距离
    int scrollY = webView.getScrollY();
    // 判断软键盘是否弹出
    if (keyboardTop != -1) {
        // 判断输入框是否被软键盘遮挡
        if (bottom >= keyboardTop) {
            // 计算滚动距离
            int diff = bottom - keyboardTop - scrollY;
            // 滚动 WebView diff   mDistance 距离,mDistance 默认 50,
            // diff   mDistance:即软键盘距离输入框底部 50 距离 
            webView.assistWebKeyboard(scrollY, diff   mDistance);
        } else {
            // 判断 WebView 是否有滚动
            if (scrollY != 0) {
                // 滚动 WebView
                webView.assistWebKeyboard(scrollY, -scrollY);
            }
        }
    }
}

以上代码实现方案二中第三步,首先获取 JS 传入的输入框左下角 Y 坐标,其次获取软键盘顶部的 Y 坐标,然后获取 WebView 当前滚动的距离,接下来根据软键盘顶部的 Y 坐标判断软键盘是否弹出,在软键盘弹出的情况下,判断输入框左下角 Y 坐标是否大于等于软键盘顶部 Y 坐标:

  • 如果大于等于,则认为输入框被软键盘遮挡,此时计算出 WebView 需要滚动多长的距离,输入框才能被显示出来,最后调用 assistWebKeyboard 方法滚动 WebView
  • 如果小于,则认为输入框没有被软键盘遮挡,此时判定 WebView 之前是否有滚动,如果有滚动距离,则计算滚动距离为当前滚动距离的负值,最后调用 assistWebKeyboard 方法滚动 WebView

至此完结。

总结

本文提供了一种新的解决 WebView 输入框被软键盘遮挡的思路,不过这种思路也有它的局限性,目前来看仅适用于全屏的 WebView 中,后续笔者再想到其他方案时,另写一篇纪实续集吧。

到此这篇关于Android WebView软键盘遮挡输入框方案详解的文章就介绍到这了,更多相关android 软键盘遮挡输入框内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Android WebView软键盘遮挡输入框方案详解的更多相关文章

  1. 详解通过focusout事件解决IOS键盘收起时界面不归位的问题

    这篇文章主要介绍了详解通过focusout事件解决IOS键盘收起时界面不归位的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. HTML5去掉输入框type为number时的上下箭头的实现方法

    这篇文章主要介绍了HTML5去掉输入框type为number时的上下箭头的实现方法,需要的朋友可以参考下

  4. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. HTML5页面无缝闪开的问题及解决方案

    这篇文章主要介绍了HTML5页面无缝闪开方案,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  7. HTML5中input输入框默认提示文字向左向右移动的示例代码

    这篇文章主要介绍了HTML5中input输入框默认提示文字向左向右移动,本文通过实例代码给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  8. 详解移动端HTML5页面端去掉input输入框的白色背景和边框(兼容Android和ios)

    本篇文章主要介绍了移动端HTML5页面端去掉input输入框的白色背景和边框,非常具有实用价值,需要的朋友可以参考下。

  9. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  10. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部