Android - Empêcher le rechargement de WebView lors de la rotation

90

Lorsque je fais pivoter mon écran, WebView recharge toute la page. Je ne peux pas avoir cela car une partie de mon contenu contient du matériel dynamique / aléatoire. Actuellement, lors de la rotation, l'écran recharge l'URL d'origine à partir de la méthode loadUrl ().

Une idée de ce qui ne va pas avec mon code?

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>
marque
la source
1
La solution simplifiée que j'ai utilisée moi-même et que je pourrais recommander est ici: twigstechtips.blogspot.com/2013/08/…
Andrius Baruckis

Réponses:

103

Je pense que le principal problème est que vous appelez web.loadUrl (webURL); également lorsque savedInstanceState! = null

ÉDITER

Essayer:

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

EDIT2 : Vous avez également besoin du remplacement onSaveInstanceState et 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);
}

Remarque: veuillez également ajouter votre AndroidManifest.xml dans votre activité android: configChanges = "orientation | screenSize" Merci

Giuseppe
la source
1
Oui! Cela fonctionne pour moi (après le montage, Tim l'a repéré!)! Merci! Pourriez-vous expliquer pourquoi et comment cela fonctionne et pourquoi ces méthodes devaient être remplacées?
marque
Une dernière chose, ai-je vraiment besoin de l'instruction if suivante: if (savedInstanceState! = Null) ((WebView) findViewById (R.id.web)). RestoreState (savedInstanceState);
marque
21
cela garde la même page mais toujours recharger sur la rotation de l'écran
Grasper
2
Cela fonctionne si j'ajoute la propriété android: configChanges à <activity> dans AndroidManifest, donc les deux choses de votre réponse plus celle-là. Voici une meilleure réponse qui comprend les trois choses: stackoverflow.com/a/46849736/454780
trusktr
63

Aucun codage Java nécessaire. utilisez ceci dans votre fichier manifeste.

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

comme:

<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>
Vettiyanakan
la source
2
de quels changements parlez-vous?
Pratik Poddar
suite au commentaire de @Mgamerz .. quand le sujet tourne .. c'est la pire suggestion que vous puissiez donner
Guilherme Oliveira
54
Noooooooooooo. Ne pensez même pas à faire ça. Les changements de configuration ne se limitent pas à la rotation. En outre, l'état de l'instance peut être restauré après être revenu d'une mémoire insuffisante. Le problème ici est que la configuration ne sera pas mise à jour correctement lorsque vous effectuez cette opération. S'il vous plaît, personne ne fait ça.
Eric Cochran
6
@EricCochran Pourriez-vous écrire la bonne réponse, si vous en connaissez une? La réponse acceptée recharge toujours la page pour moi, ainsi que les informations de session. Ce qui dans mon cas est comme wow, vous allumez le téléphone - vous devez vous reconnecter.
Atomosk
Cela ne peut faire partie que d'une réponse complète. Voir ce meilleur: stackoverflow.com/a/46849736/454780
trusktr
19

dans la balise (manifeste)

android:configChanges="orientation|screenSize"
01wifi01
la source
8
Il n'y a en fait aucune raison de remplacer la onConfigurationChangedméthode car aucune fonctionnalité personnalisée n'est ajoutée. Le simple fait de modifier le fichier manifeste a fait l'affaire pour moi.
i2097i
manifeste était suffisant, et vote favorable pour l'ajout uniquementorientation|screenSize
Varun Garg
14

L'ajout android:configChanges="orientation|screenSize"de manifeste fonctionne pour moi

<activity
            android:name="com.example.HelloWorld.WebActivity"
            android:label="@string/title_activity_web"
            android:configChanges="orientation|screenSize" >
</activity>
Rasel
la source
Pouvez-vous publier ce que fait votre MainActivity concernant la WebView?
trusktr
8

Je ne pense pas que cela fonctionnera plus. Dans mon cas, la restauration de l'état à l'aide de WebView.restore(Bundle savedInstanceState)déclenche toujours un rechargement de l'url.

En regardant les documents pour restoreState()vous le verrez dit:

Si elle est appelée après que cette WebView ait eu la possibilité de générer l'état (charger des pages, créer une liste précédente / suivante, etc.), il peut y avoir des effets secondaires indésirables.

et

Veuillez noter que cette méthode ne restaure plus les données d'affichage pour cette WebView.

Props à @ e4c5 pour m'avoir pointé dans la bonne direction dans sa réponse

Et bien sûr, la ligne de conduite extrême serait d'empêcher les changements d'orientation de déclencher la destruction / création d'activité. La documentation pour savoir comment faire est ici

Ranjeev Mahtani
la source
6

Ajouter ce code dans le manifeste

<activity 
     ...
     android:configChanges="orientation|screenSize">
Embrouiller
la source
4

Remplacer la onConfigChangeméthode pour éviter de recharger les données lors du changement d'orientation

sur votre activité dans le AndroidMainfestfichier.

android:configChanges="orientation|keyboardHidden" 

et les avoir également dans vos paramètres WebView

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

Essayez ceci dans votre fichier manifeste:

android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"
Ajeet Yadav
la source
4

Placez ceci dans l'activité du fichier Manifest.xml:

android:configChanges="orientation|screenSize"

Voici un exemple:

<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>
Carlos Alberto Gonzalez
la source
4

Comme cité ici ,

Attention: à partir d'Android 3.2 (niveau d'API 13), la «taille de l'écran» change également lorsque l'appareil bascule entre l'orientation portrait et paysage. Ainsi, si vous souhaitez empêcher le redémarrage de l'exécution en raison d'un changement d'orientation lors du développement pour le niveau d'API 13 ou supérieur (comme déclaré par les attributs minSdkVersion et targetSdkVersion), vous devez inclure la valeur "screenSize" en plus de la valeur "orientation". Autrement dit, vous devez decalare android: configChanges = "orientation | screenSize". Cependant, si votre application cible le niveau d'API 12 ou inférieur, votre activité gère toujours cette modification de configuration elle-même (cette modification de configuration ne redémarre pas votre activité, même lorsqu'elle est exécutée sur un appareil Android 3.2 ou supérieur).

le paramétrage android:configChanges="orientation|screenSize"de votre activité résoudra ce problème.

Prenez également note de ce qui suit

N'oubliez pas: lorsque vous déclarez votre activité pour gérer un changement de configuration, vous êtes responsable de la réinitialisation de tous les éléments pour lesquels vous fournissez des alternatives. Si vous déclarez votre activité pour gérer le changement d'orientation et que vous avez des images qui devraient changer entre paysage et portrait, vous devez réattribuer chaque ressource à chaque élément pendant onConfigurationChanged ().

Davejoem
la source
3

Cette solution fonctionne bien pour moi:

(1) Dans AndroidManifest.xml, ajoutez cette ligne android: configChanges = "keyboard | keyboardHidden | orientation | screenLayout | uiMode | screenSize | smallestScreenSize"

Comme ça (et comme les réponses ci-dessus)

<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) Puis dans MainActivity.java, vérifiez 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) puis:

@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);
}
Adrian S.
la source
0

Ajoutez ceci dans Androidmanifest.xml:

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

Maintenant, lorsque l'une de ces configurations change, MyActivityne redémarre pas. Au lieu de cela, MyActivityreçoit un appel à onConfigurationChanged().

Ajoute ça:

@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();
    }
}
Sunny Singh
la source