【问题标题】:Android get height of webview content once rendered渲染后,Android获取webview内容的高度
【发布时间】:2014-04-05 07:44:09
【问题描述】:

我正在尝试获取渲染后的 webview 的高度。它总是返回null,我试过getHeightgetMeasuredHeightgetContentHeight,它总是返回null。

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/instructions"
    android:background="@color/transparent_black" >

        <WebView
            android:id="@+id/top_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </RelativeLayout>

活动

public class TestActivity extends MenuActivity {

private final static String TAG = "HearingTest";
private String urlTopContent;
private WebView topContent;
private boolean mMoreInfoTop = true;
private int mYdelta = 0;
private int mBottomOffset = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.right_hearing_test);

        String topHtml = this.getString(R.string.top_content);
        //String bottomHtml = this.getString(R.string.bottom_content);

        urlTopContent = "file:///android_asset/html/" + topHtml;
        WebViewSettings();
        LoadWebPage(urlTopContent);
    }

    public void WebViewSettings(){

        topContent = (WebView) findViewById(R.id.top_content);
        topContent.getSettings().setJavaScriptEnabled(true);
        topContent.getSettings().setBuiltInZoomControls(true);
        topContent.getSettings().setSupportZoom(true);
        topContent.getSettings().setLoadWithOverviewMode(true);
        topContent.setBackgroundColor(0);
        topContent.canGoBack();

        int topHeight = topContent.getContentHeight();
        Log.d("Top Height", "Height: " + topHeight);            

        topContent.setWebViewClient(new WebViewClient(){

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                if (Uri.parse(url).getHost().equals(urlTopContent)) {
                    // This is my web site, so do not override; let my WebView load the page
                    return false;
                }
                // Otherwise, the link is not for a page on my site, so launch another Activity that handles URLs
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(intent);
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                View webViewHeight = (View) findViewById(R.id.top_content);
                int height = webViewHeight.getHeight();
                Log.d("Top Content","Top Content Height:" + height);
            }
        });
    }

    public void LoadWebPage(String url){

        try {
            topContent.loadUrl(url);
            Log.d("Loading Web Page", "URL" + url + "connected");
        } 
        catch (Exception e) {
                Log.d("Loading Web Page", "URL: " + url + " couldn't connect.");
        }
    }

}

我什至不知道是否可以在渲染后获取 web 视图的高度,但我不明白为什么你不能。如果有人得到解决方案,将不胜感激。

【问题讨论】:

    标签: java android webview


    【解决方案1】:

    您可以在该WebView 上使用ViewTreeObserver 来获取渲染其内容后的实际高度。

    这是示例代码。

    ViewTreeObserver viewTreeObserver  = mWebView.getViewTreeObserver();
    
    viewTreeObserver.addOnPreDrawListener(new OnPreDrawListener() {
                       @Override
                       public boolean onPreDraw() {                                
                               int height = mWebView.getMeasuredHeight();
                               if( height != 0 ){
                                       Toast.makeText(getActivity(), "height:"+height,Toast.LENGTH_SHORT).show();
                                       mWebView.getViewTreeObserver().removeOnPreDrawListener(this);
                               }
                               return false;
                       }
               });
    

    【讨论】:

    • 工作就像一个魅力,非常感谢多年来一直坚持这一点。
    • 在 onloadPageFinish 之后在哪里调用它?
    • 我得到了错误的值.. 测试 www.google.com 给出大小 714px
    【解决方案2】:

    我发现这个解决方案是 100% 可靠的。

    子类化您的 WebView,并且需要在内容加载后调用 javascript

    // callback made this way in order to get reliable html height and to avoid race conditions
        @SuppressLint("SetJavaScriptEnabled")
        override fun onPageFinished(view: WebView?, url: String?) {
            view?.let {
                it.settings.javaScriptEnabled = true
                it.addJavascriptInterface(WebAppInterface(it), "AndroidGetHeightFunction")
                it.loadUrl("javascript:AndroidGetHeightFunction.resize(document.body.scrollHeight)")
            }
        }
    

    然后我们可以得到合适的高度并在回调中禁用javascript(为了安全和一致性):

    inner class WebAppInterface(private val webView: WebView) {
        @JavascriptInterface
        fun resize(height: Float) {
            webView.post {
                heightMeasuredListener?.invoke(formatContentHeight(webView, height.toInt()))
                webView.settings.javaScriptEnabled = false
            }
        }
    }
    

    WebView 必须调用 post() 因为 resize(...) 中的代码在 WebView 线程中被调用!

    之后,确保缩放像素以匹配像素密度!:

    fun formatContentHeight(webView: WebView, height: Int): Int = Math.floor((height * webView.context.resources.displayMetrics.density).toDouble()).toInt()
    

    【讨论】:

      【解决方案3】:

      我选择了这种方法

      const val heightWebViewJSScript = "(function() {var pageHeight = 0;function findHighestNode(nodesList) { for (var i = nodesList.length - 1; i &gt;= 0; i--) {if (nodesList[i].scrollHeight &amp;&amp; nodesList[i].clientHeight) {var elHeight = Math.max(nodesList[i].scrollHeight, nodesList[i].clientHeight);pageHeight = Math.max(elHeight, pageHeight);}if (nodesList[i].childNodes.length) findHighestNode(nodesList[i].childNodes);}}findHighestNode(document.documentElement.childNodes); return pageHeight;})()"

      webView.webViewClient = object : WebViewClient() {
      
                  override fun onPageFinished(view: WebView, url: String) {
                      webView.evaluateJavascript(heightWebViewJSScript
                      ) { height ->
                          val params = itemView.layoutParams
                          // params.height
                      }
                  }
              }

      【讨论】:

        【解决方案4】:

        尝试并测试了以下内容:

            mWebView = new WebView(this);
            mWebView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
        
                @Override
                public void onLayoutChange(View view, int l, int t, int r, int b, int ol, int ot, int or, int ob) {
                    Log.i("demo", String.format("%s: top=%d, bottom=%d, content height=%d",
                            Thread.currentThread().getStackTrace()[2].getMethodName(), t, b, mWebView.getContentHeight()
                    ));
                }
        
            });
        

        日志:

        12-20 16:08:33.969 1466-1466/yourPkg I/demo: onLayoutChange: top=0, 底部=0,内容高度=0
        12-20 16:08:33.970 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=0, content height=0
        12-20 16:08:34.061 1466-1466/yourPkg I/demo: onLayoutChange: top=0, 底部=1510,内容高度=0
        12-20 16:08:34.091 1466-1466/yourPkg I/demo: onLayoutChange: top=0, bottom=1510, content height=2050

        最后一个是正确的。
        ViewTreeObserver 有时给了我错误的高度。

        【讨论】:

          【解决方案5】:

          好的,这已经很晚了,但我认为这是一个不错的解决方案, 只需使用if (webView.getContentHeight() &gt; 0) if ture 表示已完成,否则表示尚未完成

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-02-22
            • 2021-12-09
            • 2017-10-18
            • 2011-02-28
            相关资源
            最近更新 更多