日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?WebView軟鍵盤遮擋輸入框方案詳解_Android

作者:guodongAndroid ? 更新時間: 2022-08-01 編程語言

背景

筆者在使用 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 中,后續筆者再想到其他方案時,另寫一篇紀實續集吧。

原文鏈接:https://juejin.cn/post/7105765986120237087

欄目分類
最近更新