文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android WebView软键盘遮挡输入框方案详解

2022-06-07 20:33

关注

目录

背景

纪实

方案

实现

总结

背景

笔者在使用 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 软键盘遮挡输入框内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯