2012-08-26 209 views
52

当我旋转屏幕时,WebView将重新加载整个页面。我不能有这个,因为我的一些内容包含动态/随机材料。当前旋转时,屏幕会从loadUrl()方法重新加载原始URL。Android - 防止重新加载WebView旋转

任何想法我的代码有什么问题?

MainActivity.java

package com.mark.myapp; 

import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.view.Menu; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class MainActivity extends Activity { 

    WebView web; 
    String webURL = "http://www.google.co.uk/"; 

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

     if (savedInstanceState != null) 
      ((WebView)findViewById(R.id.web)).restoreState(savedInstanceState); 

     web = (WebView) findViewById(R.id.web); 
     web.getSettings().setJavaScriptEnabled(true); 
     web.loadUrl(webURL); 
     web.setPadding(0, 0, 0, 0); 
     web.getSettings().setLoadWithOverviewMode(true); 
     web.getSettings().setUseWideViewPort(true); 
     web.getSettings().setSupportZoom(true); 
     web.getSettings().setBuiltInZoomControls(true); 

     web.setWebViewClient(new HelloWebViewClient()); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.activity_main, menu); 
     return true; 
    } 

    private class HelloWebViewClient extends WebViewClient { 
     public boolean shouldOverrideUrlLoading(WebView web, String url) { 
      web.loadUrl(url); 
      return true; 
     } 
    } 

    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     if ((keyCode == KeyEvent.KEYCODE_BACK) && web.canGoBack()) { 
      web.goBack(); 
      return true; 
     } 
     return super.onKeyDown(keyCode, event); 
    } 

} 

AndroidManifest.xml中

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.mark.myapp" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="15" /> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name=".MainActivity" 

      android:configChanges="orientation|keyboardHidden"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 
    <uses-permission android:name="android.permission.INTERNET"/> 
</manifest> 
+0

我用它自己,可以建议简化的解决方案是在这里:http://twigstechtips.blogspot.com/2013/08/android-retain-instance-of-webview.html –

回答

59

我认为主要的问题是,你调用web.loadUrl(WEBURL); !还当savedInstanceState = NULL

编辑

尝试:

if (savedInstanceState == null) 
{ 
    web.loadUrl(webURL); 
} 

EDIT2:你还需要和的onSaveInstanceState覆盖onRestoreInstanceState。

@Override 
protected void onSaveInstanceState(Bundle outState) 
{ 
super.onSaveInstanceState(outState); 
web.saveState(outState); 
} 

@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) 
{ 
super.onRestoreInstanceState(savedInstanceState); 
web.restoreState(savedInstanceState); 
} 
+1

是的!这适用于我(编辑后,蒂姆发现!)!谢谢!你能否解释为什么以及如何工作以及为什么这些方法需要覆盖? – mark

+0

@mark见http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges – Giuseppe

+0

最后一件事,我真的需要以下if语句:if(savedInstanceState!= null) (( web视图)findViewById(R.id.web))restoreState(savedInstanceState)。 – mark

49

不需要java编码。 在你的清单文件中使用它。

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 

,如:

<application 
    android:allowBackup="true" 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" 
    android:theme="@style/AppTheme" > 
    <activity 
     android:name="com.Example.WebviewSample.webviewsample" 
     android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 
     android:label="@string/app_name" > 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity>   
</application> 
+2

你在说什么改变? –

+0

以下@Mgamerz评论..当事情正在旋转..这是最糟糕的建议,你可以给 –

+31

Noooooooooooo。甚至不要考虑这样做。配置更改不限于旋转。另外,从低内存返回后,实例状态可以恢复。这里的问题是,当你这样做时,配置不会被正确更新。请,没有人这样做。 –

2

覆盖的onConfigChange方法,以避免在AndroidMainfest文件,您的活动上方向变化

重新加载数据。

android:configChanges="orientation|keyboardHidden" 

,并在您的WebView有这些以及设置

webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
webview.loadUrl("Your URL To Load"); 
4

在清单

<activity 
    ... 
    android:configChanges="orientation|screenSize"> 
14

在标签(清单)

android:configChanges="orientation|screenSize" 

类添加以下代码

@Override 
    public void onConfigurationChanged(Configuration newConfig){   
    super.onConfigurationChanged(newConfig); 
    } 
+5

实际上没有理由重写'''onConfigurationChanged'''方法,因为没有添加自定义功能。简单地在清单文件中进行更改对我来说是个诀窍。 – i2097i

+0

更完整的答案:https://stackoverflow.com/a/46849736/454780 – trusktr

9

添加在manifest文件android:configChanges="orientation|screenSize"

<activity 
      android:name="com.example.HelloWorld.WebActivity" 
      android:label="@string/title_activity_web" 
      android:configChanges="orientation|screenSize" > 
</activity> 
+0

你可以发布你的MainActivity关于WebView的功能吗? – trusktr

5

我不相信,这将不再工作。在我的情况下,使用WebView.restore(Bundle savedInstanceState)恢复状态仍会触发URL的重新加载。

纵观docsrestoreState()你会看到它说:

如果WebView中有机会建立状态(负载页面,创建一个后退/前进列表等之后它被称为)可能会有不良的副作用。

请注意,这种方法不再恢复的显示数据这个的WebView。

道具@ e4c5在指着我在正确的方向他answer

当然,行动的极端做法是防止触发活动破坏/创作方向变化。对于如何做到这一点的文档是here

0

在manifest文件试试这个:

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" 
1

将此放在Manifest.xml文件活动:

android:configChanges="orientation|screenSize" 

下面是一个例子:

<activity android:name=".MainActivity" 
      android:label="@string/app_name" 
      android:theme="@style/AppTheme.NoActionBar" 
      android:configChanges="orientation|screenSize"> 
      <intent-filter> 
       <category android:name="android.intent.category.DEFAULT" /> 
      </intent-filter> 
</activity> 
1

如引用here,

注意:从Android 3.2(API级别13)开始,当设备在纵向和横向 方向之间切换时,“屏幕尺寸” 也会更改。因此,如果要在开发API级别13或更高级别(由minSdkVersion和targetSdkVersion属性声明的 )时为 方向更改而阻止运行时重新启动,则 除“方向”外还必须包含“screenSize”值为 。也就是说,你必须decalare android:configChanges =“orientation | screenSize”。但是,如果您的 应用程序的目标级别为12或更低,则您的活动始终会自行处理此配置更改(即使在更高版本的Android 3.2或更高版本的设备上运行此配置更改 也不会重新启动您的活动)。

设置为android:configChanges="orientation|screenSize"您的活动将解决此问题。

另外,还要注意以下

记住:当你宣布你的活动来处理配置 变化,你有责任为重置您 提供替代的任何元素。如果您声明自己的活动处理 方向更改,并且图像应该在 横向和纵向之间更改,则必须在onConfigurationChanged()期间将每个资源重新分配给每个 元素。