在android webview中添加数据后如何调整其大小

在android webview中添加数据后如何调整其大小,android,layout,webview,Android,Layout,Webview,在布局(线性、垂直)层次结构中,我有几个视图,其中一个是WebView。 它们都有相同的参数: android:layout_width="fill_parent" android:layout_height="wrap_content" 对于所有视图,元素之间的间距都得到了正确处理,但是对于Webview,在显示的文本后面有很多空格 我使用布局在活动的“onCreate”方法中设置webview的(HTML)文本 有没有办法让webview自行调整大小,以匹配其内容大小 顺便说一句,剩余空间

在布局(线性、垂直)层次结构中,我有几个视图,其中一个是WebView。 它们都有相同的参数:

android:layout_width="fill_parent"
android:layout_height="wrap_content"
对于所有视图,元素之间的间距都得到了正确处理,但是对于Webview,在显示的文本后面有很多空格

我使用布局在活动的“onCreate”方法中设置webview的(HTML)文本

有没有办法让webview自行调整大小,以匹配其内容大小

顺便说一句,剩余空间因设备而异(emulator vs Milestone vs Hero)


有什么想法吗?谢谢

目前看来,只有当内容太大时,Webview才会自行调整大小。如果webview比内容更大,它不会收缩以回收空间。

有点复杂,但工作正常

private ViewGroup mScrollView //linearlayout encapsuled in a scrollView;
private WebView mWebView;

private Handler mHandler = new Handler(){      
  public void handleMessage(Message msg){
    mWebView.reload();
    mScrollView.addView(mWebView, 0);
  }
};

private updateWebView(){
  //update the content of your web view
  mScrollView.removeView(mWebView);
  mWebView.clearView();
  mHandler.sendMessageDelayed(mHandler.obtainMessage(0), 200);
}
我发现:

(1) webview中有两种高度。测量体重和身高。请注意,contentHeight是从webcoreThread计算的。这两个高度在任何时候都不一致

(2) 布局完成后,webview将重新加载内容。含量高度与测量高度一致

所以我认为一个解决方案是:让webview在布局完成后重新加载内容

我的解决方案:

(1) 扩展webview。 (2) 重写onlayout(),dispatchDraw()

(3) webview在加载每个内容之前都需要初始化

public void intiFlag() {
    mchanged = true;
        finished = false ;
}

希望这有帮助。

我也有同样的问题。我通过更改WebView的可见性解决了这个问题

mWebView.setVisibility(View.GONE);
mWebView.loadData(".....");
mWebView.reload();
mWebView.setVisibility(View.VISIBLE);

在通过javascript调整文本大小后,我还遇到了WebView大小不合适的问题。我通过将WebView的可见性设置为View.GONE直到onPageFinished()解决了这个问题。在页面加载之后,我通过javascript调整字体大小等,设置可见性(View.VISIBLE)和WebView大小,使之完美匹配

webView.setVisibility(View.GONE);
webView.setWebViewClient(new WebViewClient() {  
    @Override  
        public void onPageFinished(WebView view, String url)  
        {  
         int jsSize = (int)fBioTextSize; //a double set in the owning class...
         String sizeTweak = "" ;
         if (jsSize > 0.00)
         {
             sizeTweak = 
                "document.getElementsByTagName('body')[0].style.fontSize = '" + jsSize + "px'; ";
         }
            view.loadUrl("javascript:(function() { " +  
                    "document.getElementsByTagName('body')[0].style.color = '#9e9e9e'; " +
                    "document.getElementsByTagName('body')[0].style.background = 'black'; " +
                    sizeTweak +
                    "})()");  
           view.setVisibility(View.VISIBLE); 

        }  
    });  

更简单的解决方案是在加载完成后使webview无效:

  webView.setWebViewClient(new WebViewClient() {

            @Override
            public void onPageFinished(final WebView view, final String url) {
                super.onPageFinished(view, url);
                webView.invalidate();
            }
        });

如果您只是删除视图,然后再添加一个新视图,问题就解决了

以下是一个例子:

WebView current_view = (WebView) view.getChildAt(i);
CharSequence current_text = current_view.getText();
int index = parent.indexOfChild(current_view);
parent.removeView(current_view);
current_view = new WebView(context);
parent.addView(current_view, index, layoutParams);
current_view.loadDataWithBaseURL( ...however you want... );
view.invalidate();

总之。。。它只是添加了一个新的WebView,就像旧的右视图一样,以相同的索引返回到其父视图

我对包含TextView、ProgressBar和WebView的FrameLayout也有类似的问题。取决于服务器返回的对象,我隐藏视图,有时在onPageFinished()中显示网页并隐藏TextView和ProgressBar时,WebView的ProgressBar值很高。通过以下代码设法修复它:

public void onPageFinished(WebView view, String url) {
    super.onPageFinished(view, url);
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            progressBar.setVisibility(View.GONE)
        }
    });
}

我确信这已经太晚了,但是添加了对我有效的方法,以防其他人来这里寻找解决方案

一旦页面完成加载,我将注入一个javascript方法来回调我的JS钩子。在这个方法中,我传递的是

    private void setupWebView() {
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            webView.loadUrl("javascript:MyApp.resize(document.body.getBoundingClientRect().height)");
            super.onPageFinished(view, url);
        }
    });
    webView.addJavascriptInterface(this, "MyApp");
}
@JavascriptInterface
public void resize(final float height) {
    MyActivity.this.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            webView.setLayoutParams(new LinearLayout.LayoutParams(getResources().getDisplayMetrics().widthPixels, (int) (height * getResources().getDisplayMetrics().density)));
        }
    });
}

同样的解决方案也可以看到

我只将webview放在ScrollView中,并设置layout_height=wrap_content,它就成功了

<ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/web_scrollview"
        android:layout_below="@id/question_title_section"
        android:layout_marginBottom="60dp"
        android:scrollbars="vertical">
        <WebView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/question_content"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:padding="4dp">
        </WebView>
    </ScrollView>

经过几个小时的搜索和尝试,我找到了最简单的工作解决方案。只需将其称为“重新绘制”:

对于我的webview,它在scrollView中工作得非常好。
如果不想使用WRAP_内容,可以使用自己的参数。

可以根据javascript主体高度定期更新WebView高度,如下所示:

public class WrapContentWebView extends WebView {

    private static final long UPDATE_INTERVAL = 100; // ms

    public WrapContentWebView(Context context) {
        super(context);
        init();
    }

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

    public WrapContentWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        addJavascriptInterface(new JavascriptInterface(), "java");
        postDelayed(scheduleRunnable, UPDATE_INTERVAL);
    }

    private Runnable scheduleRunnable = new Runnable() {
        @Override
        public void run() {
            loadUrl("javascript:window.java.onNewHeight(document.body.offsetHeight);");
            postDelayed(scheduleRunnable, UPDATE_INTERVAL);
        }
    };

    private class JavascriptInterface {
        @android.webkit.JavascriptInterface
        public void onNewHeight(String bodyOffsetHeight) {
            if (bodyOffsetHeight == null) {
                return;
            }

            final int newHeight =
                    (int) (Integer.parseInt(bodyOffsetHeight) *
                            getScaleY() *
                            getResources().getDisplayMetrics().density);

            if (getLayoutParams().height != newHeight) {
                ((Activity) getContext()).runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        getLayoutParams().height = newHeight;
                        requestLayout();
                    }
                });
            }
        }
    }
}
layout.xml:

<WrapContentWebView
            android:layout_width="match_parent"
            android:layout_height="0dp">
</WrapContentWebView>


在安卓5、4.1、4.04上检查的p.S.

同意@Fernilter。但改变顺序对我来说很有效

mWebView.setVisibility(View.GONE);
mWebView.reload();
mWebView.setVisibility(View.VISIBLE);
mWebView.loadData(".....");
ViewTreeObserver viewTreeObserver = dataWebView.getViewTreeObserver();
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (dataWebView.getMeasuredHeight() > 0) {
                    dataWebView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    ((Activity) getContext()).runOnUiThread(() -> {
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0));
                        dataWebView.setVisibility(View.GONE);
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                        dataWebView.setVisibility(View.VISIBLE);

                    });
                }
            }
        });
这对我有用

mWebView.setVisibility(View.GONE);
mWebView.reload();
mWebView.setVisibility(View.VISIBLE);
mWebView.loadData(".....");
ViewTreeObserver viewTreeObserver = dataWebView.getViewTreeObserver();
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (dataWebView.getMeasuredHeight() > 0) {
                    dataWebView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    ((Activity) getContext()).runOnUiThread(() -> {
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0));
                        dataWebView.setVisibility(View.GONE);
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                        dataWebView.setVisibility(View.VISIBLE);

                    });
                }
            }
        });

好的,关于如何强制它调整大小有什么想法吗?这个方法需要重新加载webview url吗?看看[类似的问题链接][1][1]:到目前为止,这个方法对我很有效。我做了一个小小的修改,将可见性的显示放在onPageFinished中。似乎如果您的内容高度大于最大可见高度
WebView
height,您将尝试将此较大的高度值设置为
LayoutParams
,您的
WebView
将完全消失。使用layout.xml中的WrapContentWebView仅此??说真的…我的意思是,我想知道这个简单的标记更改是否能解决问题??正如您所看到的,这个标记是随实现提供的,它捕获javascript端的文档高度更改,然后更新webview的高度以匹配javascript内容高度。非常棒的解决方案,我得到了一个超级古怪的HTML来显示,所以我不得不将它与
document.body.firstElementChild.offsetHeight
添加
webView.requestLayout()
webView.invalidate()之后为我工作。可能只需要一个。这是在列表项中使用my WebView的唯一解决方案。列表项根据需要展开,但从不缩小。不过,这是有道理的,因为我使用的是MATCH_PARENT。在将layout参数更改为WRAP_CONTENT之后,我甚至不必调用invalidate()或requestLayout()。
ViewTreeObserver viewTreeObserver = dataWebView.getViewTreeObserver();
        viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (dataWebView.getMeasuredHeight() > 0) {
                    dataWebView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    ((Activity) getContext()).runOnUiThread(() -> {
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0));
                        dataWebView.setVisibility(View.GONE);
                        dataWebView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
                        dataWebView.setVisibility(View.VISIBLE);

                    });
                }
            }
        });