在android webview中添加数据后如何调整其大小
在布局(线性、垂直)层次结构中,我有几个视图,其中一个是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自行调整大小,以匹配其内容大小 顺便说一句,剩余空间
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);
});
}
}
});