WebView高度適応スキームの探究

11108 ワード

Androidプロジェクトの開発ではwebviewに対してハイブリッド開発モデルは避けられないが、Android上のwebviewは意気地がなく、ほとんどのAndroidバージョンにwebviewの変更があり、国内ではこのような魚龍混在環境では予想外の問題が多く、今回はwebviewの高度適応の問題についてお話しします.
に質問
Androidの开発生涯の中できっとみんな出会ったことがあって、webviewは时には展示が不完全で、时には底に空白があって、时にはずっと滑らないことがあります.のこの問題の原因には、次の3つがあります.
  • ページ高さ不定
  • ネストレイアウトによりwebviewの高さが適応できない
  • システムの原因により、webviewは、特定の場合、現在のアプリケーションのスクリーン解像度
  • と互換性がない.
    以下、この3つの状況が引き起こした原因と解決方法についてそれぞれ述べます.
    Webページの高さが固定されていない問題に対して
    この部分の原因はH 5の作成方法と大きく関係しており、例えばAjaxの非同期処理結果が遅すぎて、webviewの高さがタイムリーに更新できない.H 5作成時に1つのリソース展示エリアを予約して将来のリソース展示を待っていた可能性もあり、結果としてリソースがロードされなかった.これとH 5開発者は状況を説明し,コード構造をチェックする.
    ネストされたレイアウトによるwebviewの高さの不定性の問題
    これはAndroid開発で最も一般的なことで、多くの場合ハイブリッド開発モデルであり、やむを得ずscrollviewネストwebviewを採用しているが、scrollviewにネストされた他のviewはしばしばいくつかのviewの高さ(match_parent)を失効させることを知っている.もちろんandroid:fillViewport="true"を採用して強制的に満たすことができるが、内部のwebviewは言うことを聞かないようだ.この道理は明らかだ.結局、ウェブビューがレンダリングされているのはウェブページです.つまり、ウェブビューの高さを正確に固定できるという問題が解決されます.
    Webview互換性の現在の適用画面密度の問題
    まず、システムフォントのスケールがwebviewスケールに影響を与えないように処理します.webview.getSettings().setTextZoom(100)で回避できます.残りのサポートは適応すればよく、画面密度設定を適用した後、webiviewは自動的にマッチングすることができ、もちろんいくつかの奇抜なデバイス(アプリケーションによって変更された)もありますが、この部分は無視できます.
    高度に固定されていない問題に対する解決策
    ここでは2つの解決策を示します.
    レイアウト構造調整
    Webiviewの親レイアウトの高さは、公式の推奨に従ってmatch_parentを採用しています.
    Webビューは、Webページの高さに応じて自動的に自己の高さを拡張します.
    手順に従います.
    ステップ1:Jsインタフェースをローカルに定義し、通常H 5はこのインタフェースの識別を明確にする必要があり、Android側はH 5に関連する内容をコールバックすることができます.
    mWebView.addJavascriptInterface(this, "App");
    

    第2歩:ローカル実装インタフェースメソッド、H 5は上の「APP」インタフェースを通じてローカルのインタフェースの中のメソッドを呼び出すことができることを識別する.
    /**
     * js  ,    webview   。
     */
    @JavascriptInterface
    public void resize(final float clientWidth, final float scrollHeight) {
        if (mActivity == null || mWebView == null || clientWidth == 0) {
            return;
        }
        mActivity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                float rate = mWebView.getWidth() / clientWidth;
                Log.i("TAG", "webview---------clientWidth:" + clientWidth + "---------scrollHeight:" + scrollHeight + "---------rate:" + rate);
                mWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                        (int) (scrollHeight * rate)));
            }
        });
    }
    

    ステップ3:H 5のjsメソッドをローカルに呼び出し、H 5に「私、大Android、あなたのH 5の現在の幅と高さが必要です」と伝え、H 5がおとなしくインタフェースの幅をローカルに戻すのが、ステップ2の方法です.でも!私が今日言ったのは汎用的な方法で、すべてのH 5に対して、H 5ごとにjsメソッドを定義してAndroid側に呼び出すことはできません.どうすればいいですか?H 5を直接ローカルにコールバックさせる方法:
    mWebView.loadUrl("javascript:App.resize(document.documentElement.clientWidth, document.documentElement.scrollHeight)");
    

    ここの「App」は実は「this」ですが、jsコールバックのタイミングはいつなのか、このページのロードが終わったときに教えてほしいので、WebViewClientのonPageFinishedの方法を書き直します.いくつかのH 5は非同期ロード方式を採用しているので、私は彼がいつ完全にロードされたのか分からないので、ここでは何度もH 5にコールバックを手伝ってもらいました.
    class DefaultWebViewClient extends WebViewClient {
    
        //     
        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String s) {
            webView.loadUrl(s);
            return true;
        }
    
        @Override
        public void onPageFinished(WebView webView, String s) {
            super.onPageFinished(webView, s);
    
            //        ,        
            mHandler.post(new Runnable() {
    
                //      
                int times = 5;
    
                @Override
                public void run() {
                    if (times > 0) {
                        mWebView.loadUrl("javascript:App.resize(document.documentElement.clientWidth, document.documentElement.scrollHeight)");
                        mHandler.postDelayed(this, 1000);
                        times--;
                    }
                }
            });
        }
    }
    

    まとめ
    以上は私がこのような問題に対して考えたいくつかの処理案で、みんなはもっと良い処理方法があっても分かち合って、広く考えて、一緒に進歩してもいいです.