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

目录
  • 背景
  • 纪实
    • 方案
    • 实现
  • 总结

背景

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

(0)

相关推荐

  • Android开发之WebView输入框提示解决办法

    做基于WebView应用时,页面上有一个输入框,当输入的文字过多时,超过输入框的行数时,输入框能够滚动,这时间问题来了,输入的提示箭头会移动到输入框外,如何解决这个问题呢,查找chromium源码如下: void LoadIfNecessary(jobject context) { if (loaded_) return; loaded_ = true; TRACE_EVENT0("browser", "HandleResources::Create"); JNIE

  • Android软键盘遮挡的四种完美解决方案

    一.问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时输入框被系统键盘遮挡了,大大降低了用户操作体验,这就是开发中非常常见的软键盘遮挡的问题,该如何解决? 二.简单解决方案 方法一 在你的activity中的oncreate中setContentView之前写上这个代码 getWindow().setSoftInputMode(WindowManage

  • Android开发软键盘遮挡登陆按钮的完美解决方案

    在应用登陆页面我们需要填写用户名和密码.当填写这些信息的时候,软键盘会遮挡登陆按钮,这使得用户体验较差,所以今天就来解决这个问题 1:登陆布局界面如下 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="

  • Android优雅的方式解决软键盘遮挡按钮问题

    前言 比如在进行登录的操作中,用户输入完密码之后,肯定是想直接点击登录按钮的.返回键隐藏软键盘这样的体验肯定很糟糕,程序员,遇到问题解决问题. 实现1 xml <ScrollView android:id="@+id/scrollview" android:layout_width="match_parent" android:layout_height="wrap_content" android:fadingEdge="non

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

    目录 背景 纪实 方案 实现 总结 背景 笔者在使用 WebView 加载含有输入框的 H5 页面时,点击输入框后,输入框会被软键盘遮挡住,无法看到输入的内容,这很影响用户体验. 笔者想着这种业务场景比较常见,遂上网搜索一番,果不其然,有不少同志遇到这个问题,想来这个问题很好解决了.笔者一一尝试了同志们提供的解决方案,结果要不是没有作用,要不是效果不太满意,只好自己另辟蹊径了. 注:在笔者的业务场景中,App是全屏的,即没有顶部的系统栏,也没有底部的导航栏,所以笔者的解决方案,可能不适用于其他场

  • 5种方法完美解决android软键盘挡住输入框方法详解

    在开发中,经常会遇到键盘挡住输入框的情况,比如登录界面或注册界面,弹出的软键盘把登录或注册按钮挡住了,用户必须把软键盘收起,才能点击相应按钮,这样的用户体验非常不好.像微信则直接把登录按钮做在输入框的上面,但有很多情况下,这经常满足不了需求.同时如果输入框特别多的情况下,点击输入时,当前输入框没被挡住,但是当前输入框下面的输入框却无法获取焦点,必须先把键盘收起,再去获取下面输入框焦点,这样用户体验也非常不好,那有什么办法呢?  系统的adjustResize和adjustPan有什么区别,他们使

  • js解决软键盘遮挡输入框的问题分享

    经验须知 弹出软键盘时: ios端$('body').scrollTop()会改变 android端$(window).height()会改变 拉起键盘不是一瞬间,而是有一个缓动过程 问题重现 ios端,经常会出现输入法遮挡输入框的问题(特别是那种有一个白色顶部的输入法,如:百度输入法),如图: 问题解决 我们只需要在输入框聚焦之后,开启一个定时器,执行$('body').scrollTop(1000000),这样由于整个body滚动到了最下面,输入框自然就看见了,具体请查看以下示例 示例源码

  • Android 监听软键盘状态的实例详解

    Android 监听软键盘状态的实例详解 近日遇到要检测软键盘是否显示或隐藏的问题,搜了一下网上,最后找到一个很简单的,记录一下. activityRoot是activity的根view,就是xml里面的第一个view,给它设置一个id. final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(ne

  • Android软键盘挡住输入框的终极解决方案

    前言 开发做得久了,总免不了会遇到各种坑. 而在Android开发的路上,『软键盘挡住了输入框』这个坑,可谓是一个旷日持久的巨坑--来来来,我们慢慢看. 入门篇 最基本的情况,如图所示:在页面底部有一个EditText,如果不做任何处理,那么在软键盘弹出的时候,就有可能会挡住EditText. 对于这种情况的处理其实很简单,只需要在AndroidManifest文件中对activity设置:android:windowSoftInputMode的值adjustPan或者adjustResize即

  • Android屏蔽软键盘并且显示光标的实例详解

    Android屏蔽软键盘并且显示光标的实例详解 如果是android4.0以下,那么 editText.setInputType(InputType.TYPE_NULL); 就够了,android4.0以上屏蔽软键盘并且有光标,需要用到. if (android.os.Build.VERSION.SDK_INT <= 10) {//4.0以下 danielinbiti editText.setInputType(InputType.TYPE_NULL); } else { this.act.ge

  • Android屏蔽软键盘自动弹出的解决方案

    问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时输入框被系统键盘遮挡了,大大降低了用户操作体验,这就是开发中非常常见的软键盘遮挡的问题,该如何解决? 简单解决方案 方法一: 在你的activity中的oncreate中setContentView之前写上这个代码 getWindow().setSoftInputMode(WindowManager.L

随机推荐