如何获取webView的高度

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何获取webView的高度相关的知识,希望对你有一定的参考价值。

如果要获取高度,在上面增加

_webview.delegate = self;

再增加方法
- (void)webViewDidFinishLoad:(UIWebView *)webView



//在这个方法中取高度

参考技术A <!-- lang: cpp -->
htmlHeight = [webView stringByEvaluatingjavascriptFromString:@"document.body.offsetHeight"];
这段代码是无效的,body 获取到的 offsetHeight,为显示区域的高度,因此修改为:

<!-- lang: cpp -->
htmlHeight = [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"];
scrollHeight 为网页内容的实际高度。
之后,自然需要关闭 UIWebView 的滚动效果,否则将会影响整体页面滚动,代码如下:

<!-- lang: cpp -->
UIScrollView *tempView=(UIScrollView *)[webView.subviews objectAtIndex:0];
tempView.scrollEnabled=NO;
修改 UIScrollView的内容高度。

<!-- lang: cpp -->
scrollView.contentSize = CGSizeMake(width, height);
参考技术B  android SDK 的扩展通过使用特定的view允许你做许多事情比如WebView用来在Android手机上展示网页
  As of lately while I was experimenting with the Android SDK I was using a WebView in one of my activities
  最近我在体验Android SDK的时候在一个Activity中用到了WebView
  From that particular WebView I needed to know the ContentHeight but also the ContentWidth
  从WebView我不但想要知道ContentHeight还想知道ContentWidth
  Now getting the contentHeight is easy like so:
  现在的情况是获取contentHeight很easy如下
  webviewgetContentHeight();
  Unfortunately getting the contentWidth from a WebView is rather more difficult since there is not a simple method like:
  不幸的是从一个WebView获取contentWidth是相当困难因为SDK中没有一个像这样的方法
  // THIS METHOD DOES NOT EXIST!
   webviewgetContentWidth();
  There are ways to get the contentWidth of the rendered HTML page and that is through Javascript If Javascript can get it for you then you can also have them in your Java code within your Android App
  当然是有方法获取contentWidth的就是通过Javascript来获取如果你能够支持Javascript那么你就可以在你的Android 程序中使用java代码来获取宽度
  By using a JavascriptInterface with your WebView you can let Javascript communicate with your Android App Java code by invoking methods on a registered object that you can embed using the JavascriptInterface
  通过在你的WebView中使用JavascriptInterface通过调用你注册的JavascriptInterface方法可以让Javascript和你的Android程序的java代码相互连通
  So how does this work?
  怎么做呢?
  For a quick example I created a simple Activity displaying a webview that loads a webpage wich displays a log message and a Toast message with the contentWidth wich was determined using Javascript Note that this happens AFTER the page was finished loading because before the page is finished loading the width might not be fully rendered Also keep in mind that if there is content loaded asynchronously that it doesnt affect widths (most likely only heights will be affected as the width is almost always fully declared in CSS files unless you have a % width webpage)
  搭建一个快速的例子创建一个简单的展示webView的Activity一个LogCat消息一个Toast消息用来显示我们通过 Javascript获取的宽度注意这些会在网页完全加载之后显示因为在网页加载完成之前宽度可能不能够正确的获取到同时也要注意到如果是异 步加载这并不影响宽度(最多高度会受影响因为宽度总是在CSS文件中做了完全的定义除非在网页中你用了%宽度)
  Below is the code of the Activity Mainjava:
  下面的代码是Activity的代码
  package compimmosandroidsampleswebviewcontentwidth;
  import androidappActivity;
  import androidosBundle;
  import androidutilLog;
  import androidwebkitWebView;
  import androidwebkitWebViewClient;
  import androidwidgetToast;
  publicclass Main extends Activity
  privatefinalstatic String LOG_TAG = "WebViewContentWidth";
  privatefinal Activity activity = this;
  privatestaticint webviewContentWidth = ;
  privatestatic WebView webview;
  
  /** Called when the activity is first created */
  @Override
  publicvoid onCreate(Bundle savedInstanceState)
  superonCreate(savedInstanceState);
   setContentView(Rlayoutmain);
   webview = (WebView) findViewById(Ridwebview);
   webviewgetSettings()setJavaScriptEnabled(true);
   webviewsetSaveEnabled(true);
   webviewaddJavascriptInterface(new JavaScriptInterface() "HTMLOUT");
   webviewsetWebViewClient(new WebViewClient()
  @Override
  publicvoid onPageFinished(WebView view String url)
   webviewloadUrl("javascript:windowHTMLOUTgetContentWidth(documentgetElementsByTagName(html)[]scrollWidth);");
  
   );
   webviewloadUrl(";);
  
  
  class JavaScriptInterface
  publicvoid getContentWidth(String value)
  if (value != null)
   webviewContentWidth = IntegerparseInt(value);
   Logd(LOG_TAG "Result from javascript: " + webviewContentWidth);
   ToastmakeText( activity
  "ContentWidth of webpage is: " +
   webviewContentWidth +
  "px" ToastLENGTH_SHORT)show();
  
  
  
  
  Below is the XML layout used with the Activity wich only contains a simple WebView:
  下面是Activity的Layout主要就是一个简单的WebView
  <?xml version="" encoding="utf"?>
   <LinearLayout
   xmlns:android=";
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
   <WebView android:id="@+id/webview"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent" />
   </LinearLayout>
  AndroidManifestxml layout:
  AndroidManifestxml代码
  <?xml version="" encoding="utf"?>
   <manifest
   xmlns:android=";
   package="compimmosandroidsampleswebviewcontentwidth"
   android:versionCode="" android:versionName="">
   <application android:icon="@drawable/icon"
   android:label="@string/app_name">
   <activity android:name="Main"
   android:label="@string/app_name">
   <intentfilter>
   <action android:name="androidintentactionMAIN" />
   <category
   android:name="androidintentcategoryLAUNCHER" />
   </intentfilter>
   </activity>
   </application>
   <usessdk android:minSdkVersion="" />
   <usespermission android:name="androidpermissionINTERNET" />
   </manifest>

text 如何获取的WebView内容高度

如何获取WebView内容高度
96  zhuguohui 
 0.7 2017.08.09 14:04* 字数 765 阅读 6456评论 3喜欢 27
序言
最近项目需求中需要实现WebView显示内容,下方显示评论列表,列表还可以分页加载。我最近做了技术预研,难度主要是实时获取WebView的高度。

效果
1.分页加载

这里写图片描述
2.动态获取高度,点击阅读更多,会将几个隐藏的div,显示出来,造成WebView内容高度变化。

这里写图片描述
实现
使用的ScrollView包裹一层LinearLayout,LinearLayout中依次防止WebView和RecyclerView。布局如下:

<?xml version="1.0" encoding="utf-8"?>
<com.trs.studyview.view.TRSScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/scrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.trs.studyview.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <com.trs.studyview.view.TRSWebView
            android:id="@+id/webview"
            android:layout_width="match_parent"
            android:layout_height="100dp" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

</com.trs.studyview.view.TRSScrollView>

问题一,如果获取WebView高度
1.通过js获取
以下是js获取高度的方法

网页可见区域宽: document.body.clientWidth 
网页可见区域高: document.body.clientHeight 
网页可见区域宽: document.body.offsetWidth (包括边线的宽) 
网页可见区域高: document.body.offsetHeight (包括边线的高) 
网页正文全文宽: document.body.scrollWidth 
网页正文全文高: document.body.scrollHeight 
网页被卷去的高: document.body.scrollTop 
网页被卷去的左: document.body.scrollLeft 
网页正文部分上: window.screenTop 
网页正文部分左: window.screenLeft 
屏幕分辨率的高: window.screen.height 
屏幕分辨率的宽: window.screen.width 
屏幕可用工作区高度: window.screen.availHeight 
屏幕可用工作区宽度: window.screen.availWidth 
下面是测试代码

package com.trs.studyview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.trs.studyview.adpater.CommentAdapter;
import com.trs.studyview.view.TRSScrollView;
import com.trs.studyview.view.TRSWebView;

public class MainActivity extends AppCompatActivity {
    TRSWebView webView;
    RecyclerView recyclerView;
    String url = "http://app.nxnews.net/ningxia/cfwz/zt/201708/t20170807_1859270.html";
    CommentAdapter adapter;
    TRSScrollView scrollView;
    Mobile mobile = new Mobile();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }


    private void initView() {
        scrollView = $(R.id.scrollView);
        webView = $(R.id.webview);
        recyclerView = $(R.id.recyclerView);
        WebSettings setting = webView.getSettings();
        setting.setJavaScriptEnabled(true);//支持js
        webView.addJavascriptInterface(mobile, "mobile");
        webView.setWebViewClient(mClient);
        webView.loadUrl(url);
        adapter = new CommentAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        scrollView.setRecyclerView(recyclerView);
    }

    private class Mobile {
        @JavascriptInterface
        public void onGetWebContentHeight(String type, int height) {
            Log.i("zzz", "onGetWebContentHeight type=" + type + " height=" + height);

        }
    }

    private String[] getHeightJs = new String[]{
            "document.body.clientHeight",
            "document.body.offsetHeight",
            "document.body.scrollHeight",
            "document.body.scrollTop",
            "window.screen.availHeight"
    };

    private WebViewClient mClient = new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            for (int i = 0; i < getHeightJs.length; i++) {
                String js = "javascript:mobile.onGetWebContentHeight(\"" + getHeightJs[i] + "\"," + getHeightJs[i] + ")";
                view.loadUrl(js);
            }
        }
    };

    protected <T extends View> T $(int id) {
        return (T) findViewById(id);
    }
}

结果如下:

这里写图片描述
可以告诉大家以上高度都不对。

2.通过getContentHeight()获取高度
思路是在网页加载完成以后通过WebView的getContentHeight()方法获取高度
代码如下:

    private WebViewClient mClient = new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            Log.i("zzz", "webview contentHeight=" + view.getContentHeight());
        }
    };
运行结果

这里写图片描述
结论:高度不对

3.通过measure()进行测量
思路,在WebView加载网页完毕以后,通过webview.measure(0,0)进行测量,两个0表示对宽高无限制。

代码改动部分


    private class Mobile {
        @JavascriptInterface
        public void onGetWebContentHeight() {
            //重新调整webview高度
            webView.post(() -> {
                webView.measure(0, 0);
                int measuredHeight = webView.getMeasuredHeight();
                Log.i("zzz", "measuredHeight=" + measuredHeight);
            });


        }
    }


    private WebViewClient mClient = new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            mobile.onGetWebContentHeight();
        }
    };
运行结果

这里写图片描述
结论:大家可以看到这个高度是最高的,也的确是webView网页内容的高度。

总结
至此大家以后就知道怎么获取WebView内容高度了

问题二,如果监听网页高度变化
这是第一次打开APP的时候,获取到网页高度,在重新设置webView的高度,和RecyclerView的高度
代码如下


    private class Mobile {
        @JavascriptInterface
        public void onGetWebContentHeight() {
            //重新调整webview高度
            webView.post(() -> {
                webView.measure(0, 0);
                int measuredHeight = webView.getMeasuredHeight();
                ViewGroup.LayoutParams layoutParams = webView.getLayoutParams();
                layoutParams.height = measuredHeight;
                webView.setLayoutParams(layoutParams);
                ViewGroup.LayoutParams layoutParams1 = recyclerView.getLayoutParams();
                layoutParams1.height = scrollView.getHeight();
                Log.i("zzz", "scrollView height=" + scrollView.getHeight());
                recyclerView.setLayoutParams(layoutParams1);
            });


        }
    }


    private WebViewClient mClient = new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            mobile.onGetWebContentHeight();
        }
    };
效果如下:可以看到网页全部显示了,这已经滑动到网页的最底部。

这里写图片描述
但问题是点击阅读更多,网页中有几个隐藏的新闻被显示出来,造成网页内容高度变化,但是我们检测不到网页内容高度变化,所以变成这样了。

这里写图片描述
下面是我的解决思路。

思路1.通过js监听内容变化
我通过设置window的resize监听来实现高度变化的监听。下面使用浏览器来测试:

这里写图片描述
结果点击阅读更多,没有触发相关的函数。只有调整window大学的时候才会


这里写图片描述
思路2.在WebView的onDraw方法中监听
经过我的实验在点击阅读更多以后webView的contentHeight会发生变化,于是我就扩展了WebView使其能监听内容高度变化

这是我的自定义WebView:

package com.trs.studyview.view;

import android.content.Context;
import android.graphics.Canvas;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.webkit.WebView;

/**
 * Created by zhuguohui on 2017/8/8.
 */

public class TRSWebView extends WebView {
    private int lastContentHeight = 0;
    private static final int MSG_CONTENT_CHANGE = 1;
    private onContentChangeListener onContentChangeListener = null;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_CONTENT_CHANGE:
                    if (onContentChangeListener != null) {
                        onContentChangeListener.onContentChange();
                    }
                    break;
            }
        }
    };


    public TRSWebView(Context context) {
        this(context, null);
    }

    public TRSWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (getContentHeight() != lastContentHeight) {
            handler.sendEmptyMessage(MSG_CONTENT_CHANGE);
            lastContentHeight = getContentHeight();
            Log.i("www", "contentChange height=" + getContentHeight());
        }

    }

    public void setOnContentChangeListener(TRSWebView.onContentChangeListener onContentChangeListener) {
        this.onContentChangeListener = onContentChangeListener;
    }

    /**
     * 监听内容高度发生变化
     */
    public interface onContentChangeListener {
        void onContentChange();
    }
}

点击多次阅读更多

这里写图片描述
结论:可以监听网页内容的变化

问题三 recyclerView的滑动冲突。
我是通过自定义ScrollView来实现的,具体代码如下,测试可用

package com.trs.studyview.view;

import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ScrollView;

/**
 * Created by zhuguohui on 2017/8/8.
 */

public class TRSScrollView extends ScrollView {
    RecyclerView recyclerView;

    public TRSScrollView(Context context) {
        this(context, null);
    }

    public TRSScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    public void setRecyclerView(RecyclerView recyclerView) {
        this.recyclerView = recyclerView;
    }

    int downY;
    int moveY = 0;
    MotionEvent downEvent;

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //如果RecyclerView
        if (recyclerView != null) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downEvent = ev;
                    downY = (int) ev.getX();
                    moveY = 0;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int moveY = (int) ev.getY() - downY;
                    if (Math.abs(moveY) > 20) {
                        //表示滑动
                        if (moveY > 0) {
                            //向下滑动,如果recyclerView还没有显示则拦截事件
                            if (getScrollY() < recyclerView.getTop()) {
                                return true;
                            }
                        } else {
                            //向上滑动
                            if (getScrollY() == recyclerView.getTop()) {
                                //如果第一个item已经显现才拦截事件
                                LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                                if (layoutManager.findFirstVisibleItemPosition() == 0) {
                                    return true;
                                }
                            }
                        }
                    }
                    break;
            }
        }

        return super.onInterceptTouchEvent(ev);
    }
}

最终运行代码

package com.trs.studyview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.trs.studyview.adpater.CommentAdapter;
import com.trs.studyview.view.TRSScrollView;
import com.trs.studyview.view.TRSWebView;

public class MainActivity extends AppCompatActivity {
    TRSWebView webView;
    RecyclerView recyclerView;
    String url = "http://app.nxnews.net/ningxia/cfwz/zt/201708/t20170807_1859270.html";
    CommentAdapter adapter;
    TRSScrollView scrollView;
    Mobile mobile = new Mobile();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }


    private void initView() {
        scrollView = $(R.id.scrollView);
        webView = $(R.id.webview);
        recyclerView = $(R.id.recyclerView);
        WebSettings setting = webView.getSettings();
        setting.setJavaScriptEnabled(true);//支持js
        webView.addJavascriptInterface(mobile, "mobile");
        // webView.setWebViewClient(mClient);
        webView.setOnContentChangeListener(() -> {
            mobile.onGetWebContentHeight();
        });
        webView.loadUrl(url);
        adapter = new CommentAdapter();
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        scrollView.setRecyclerView(recyclerView);
    }

    private class Mobile {
        @JavascriptInterface
        public void onGetWebContentHeight() {
            //重新调整webview高度
            webView.post(() -> {
                webView.measure(0, 0);
                int measuredHeight = webView.getMeasuredHeight();
                ViewGroup.LayoutParams layoutParams = webView.getLayoutParams();
                layoutParams.height = measuredHeight;
                webView.setLayoutParams(layoutParams);
                ViewGroup.LayoutParams layoutParams1 = recyclerView.getLayoutParams();
                layoutParams1.height = scrollView.getHeight();
                Log.i("zzz", "scrollView height=" + scrollView.getHeight());
                recyclerView.setLayoutParams(layoutParams1);
            });

        }
    }

    private WebViewClient mClient = new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
        }
    };

    protected <T extends View> T $(int id) {
        return (T) findViewById(id);
    }
}

总结
这个需求难度在于知识的广度,例如对JavaScript的熟悉程度,对View事件拦截的理解。研究的过程很有趣,克服重重困难,完成任务的感觉很不错的。

小礼物走一走,来简书关注我

 Android开发 © 著作权归作者所有 举报文章
96 zhuguohui
写了 20647 字,被 421 人关注,获得了 1047 个喜欢

CSDN博客:http://blog.csdn.net/qq_22706515 GitHub:https://github.com/zhuguohui 欢迎交流
   更多分享
Web note ad 1
 后发表评论
3条评论 只看作者 按时间倒序按时间正序
 jokerrou
3楼 · 2018.08.31 16:20
webView.measure(0, 0);
int measuredHeight = webView.getMeasuredHeight();
这个代码测量出来的高度一直是0 在web加载完成后测的,换了个代码就可以了
int measureWidth= View.MeasureSpec.makeMeasureSpec(( 1 << 30 )-1, View.MeasureSpec.AT_MOST);
int measureHeight= View.MeasureSpec.makeMeasureSpec(( 1 << 30 )-1, View.MeasureSpec.AT_MOST);
wvPage.measure(measureWidth,measureHeight);
height=wvPage.getMeasuredHeight();

1人赞  回复
 有用, 感谢
2018.11.29 17:30  回复

以上是关于如何获取webView的高度的主要内容,如果未能解决你的问题,请参考以下文章

text 如何获取的WebView内容高度

iOS 终极方案精准获取webView内容高度,自适应高度

iOS获取WKWebView的高度

webview加载网页获取高度

iOS野路子精准获取webView内容高度,自适应高度

iOS获取webview高度