Android-防止在旋转时重新加载WebView


91

旋转屏幕时,WebView会重新加载整个页面。我无法使用此功能,因为我的某些内容包含动态/随机材料。当前,屏幕旋转时会从loadUrl()方法重新加载原始URL。

知道我的代码有什么问题吗?

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>

1
简化的解决方案,我用我自己,可以建议是在这里:twigstechtips.blogspot.com/2013/08/...
安德Baruckis

Answers:


103

我认为主要问题是您调用了web.loadUrl(webURL); 当saveInstanceState!= 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);
}

注意:也请在您的Activity android:configChanges =“ orientation | screenSize”中添加您的AndroidManifest.xml


1
是! 这对我有用(编辑后,Tim发现了!)!谢谢!您能否解释为什么以及如何工作以及为什么这些方法需要重写?
2012年


最后一件事,我真的需要以下if语句吗:if(savedInstanceState!= null)((WebView)findViewById(R.id.web))。restoreState(savedInstanceState);
标记

21
这会保留相同的页面,但仍会在屏幕旋转时重新加载
Grasper 2015年

2
如果我将android:configChanges属性添加到AndroidManifest中的<activity>,则此方法有效,因此您的答案中有两件事加上那一项。这是一个更好的答案,其中包括所有三件事:stackoverflow.com/a/46849736/454780
trusktr

63

无需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
您在说什么变化?
2014年

@Mgamerz评论之后..当事情旋转时..这是您可以提供的最坏建议
Guilherme Oliveira

54
不,不,不。甚至不要考虑这样做。配置更改不仅限于轮换。同样,可以从低内存返回后恢复实例状态。这里的问题是,执行此操作时将无法正确更新配置。拜托,没有人这样做。
埃里克·科克伦

6
@EricCochran,如果您知道答案,您能写出正确的答案吗?接受的答案仍然为我重新加载页面,也丢失了会话信息。就我而言,这就像哇,您打开电话-您必须重新登录。
Atomosk

这可能只是完整答案的一部分。看到更好的一个:stackoverflow.com/a/46849736/454780
trusktr '18年

20

在标签中(清单)

android:configChanges="orientation|screenSize"

9
实际上onConfigurationChanged,由于没有添加自定义功能,因此没有理由覆盖此方法。只需在清单文件中进行更改就可以了。
i2097i

清单就足够了,只赞成添加orientation|screenSize
Varun Garg,

14

添加android:configChanges="orientation|screenSize"清单对我有用

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

您可以张贴您的MainActivity关于WebView的内容吗?
trusktr

8

我认为这将不再起作用。就我而言,使用恢复状态WebView.restore(Bundle savedInstanceState)仍会触发网址的重新加载。

查看文档restoreState()您会看到它说:

如果在此WebView有机会建立状态(加载页面,创建后退/转发列表等)之后调用它,则可能会有不良的副作用。

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

支持@ e4c5,让我在他的答案中指出正确的方向

当然,极端的行动是防止方向改变触发活动破坏/创造。有关如何执行此操作的文档在这里


6

在清单中添加此代码

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

4

覆盖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

在清单文件中尝试以下操作:

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

4

将此放置在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>

4

在这里

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

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

另外,请注意以下几点

切记:声明要处理配置更改的活动时,您有责任重置所有为其提供替代方案的元素。如果声明要处理方向变化的活动,并且图像应在横向和纵向之间改变,则必须在onConfigurationChanged()期间将每个资源重新分配给每个元素。


3

该解决方案对我来说效果很好:

(1)在AndroidManifest.xml中,添加以下行android:configChanges =“ keyboard | keyboardHidden | orientation | screenLayout | uiMode | screenSize | smallestScreenSize”

这样(和上面的答案一样)

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity
        android:name=".MainActivity"
        android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
        android:label="@string/app_name"
        android:theme="@style/AppTheme.NoActionBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

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

(2)然后在MainActivity.java中验证savedInstanceState

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mainContext = getApplicationContext();
    ----
    myWebView = (WebView) findViewById(R.id.webView);
    prepareWebView();
    myWebView.addJavascriptInterface(myJavaScriptInterface, "WEB2Android");

    if (savedInstanceState == null) {
        myWebView.post(new Runnable() {
            @Override
            public void run() {
                myWebView.loadUrl("http://www.appbiz.ro/foto_konta");
            }
        });
    }
    ----
}

(3)然后:

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

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

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState)
{
    super.onRestoreInstanceState(savedInstanceState);
    myWebView.restoreState(savedInstanceState);
}

0

在Androidmanifest.xml中添加此代码:

<activity android:name=".MyActivity"
    android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">

现在,当其中一种配置更改时,MyActivity不会重新启动。而是MyActivity接到一个呼叫onConfigurationChanged()

添加:

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

    // Checks the orientation of the screen
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    }
    else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.