¿Cómo volver a la página anterior si se presiona el botón Atrás en WebView?


327

Tengo una aplicación en la que tengo un lugar WebViewdonde mostrar algunos sitios web. Funciona, hacer clic en un enlace en la página web va a la página siguiente en el sitio web dentro de mi aplicación. Pero cuando hago clic en el botón Atrás del teléfono, me lleva directamente a mi aplicación. En cambio, quiero volver a la página anterior del sitio web. ¿Cómo puedo hacer esto?

Aquí está el ejemplo de código que estoy usando:

public class Webdisplay extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
        setContentView(R.layout.webdisplay);

        getWindow().setFeatureInt(Window.FEATURE_PROGRESS,
                Window.PROGRESS_VISIBILITY_ON); 

        Toast loadingmess = Toast.makeText(this,
                "Cargando El Diario de Hoy", Toast.LENGTH_SHORT);
        loadingmess.show();

        WebView myWebView;

        myWebView = (WebView) findViewById(R.id.webview);
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadUrl("http://www.elsalvador.com");
        myWebView.setWebViewClient(new WebViewClient());
        myWebView.setInitialScale(1);
        myWebView.getSettings().setBuiltInZoomControls(true);
        myWebView.getSettings().setUseWideViewPort(true);

        final Activity MyActivity = this;
        myWebView.setWebChromeClient(new WebChromeClient() 
        {
            public void onProgressChanged(WebView view, int progress)   
            {
                MyActivity.setTitle("Loading...");
                MyActivity.setProgress(progress * 100); 

                if(progress == 100)
                    MyActivity.setTitle(R.string.app_name);
            }
        });
    }
}

Respuestas:


520

Utilizo algo como esto en mis actividades con WebViews:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_DOWN) {
        switch (keyCode) {
            case KeyEvent.KEYCODE_BACK:
                if (mWebView.canGoBack()) {
                    mWebView.goBack();
                } else {
                    finish();
                }
                return true;
        }

    }
    return super.onKeyDown(keyCode, event);
}

Editar:

Para que este código funcione, debe agregar un campo al que Activitycontiene WebView:

private WebView mWebView;

Inicialícelo en el onCreate()método y debería estar listo para comenzar.

mWebView = (WebView) findViewById(R.id.webView);

1
¿Dónde debo colocar ese código? bajo todo mi código? o justo debajo del loasUrl al igual que el BuiltinZoom?
zvzej

3
Lo pondría dentro de su actividad, pero fuera del método onCreate ().
FoamyGuy

cuando coloco su código me da un error para la variable mWebView ya que está fuera de la creación, ¿dónde debo colocar esa variable?
zvzej

44
en lugar de finish()ponerreturn super.onKeyDown(keyCode, event)
Bostone

66
o, de hecho, simplemente elimine todo el elsebloque
Bostone

301

Si usa Android 2.2 y superior (que es la mayoría de los dispositivos ahora), el siguiente código le dará lo que desea.

@Override
public void onBackPressed() {
    if (webView.canGoBack()) {
        webView.goBack();
    } else {
        super.onBackPressed();
    }
}

55
Agradable. Utilizo una variación de esta respuesta, pero sin el bloque "else". De lo contrario, cuando el usuario presiona demasiadas veces, termina en una pantalla de "inicio" de la aplicación en blanco, sin ninguna opción para que el usuario avance.
George Armhold

1
Esta parece la respuesta más adecuada. @CaffeineComa, probablemente podría codificar la pantalla de inicio de su aplicación para que no se muestre en el historial de "actividad" de la aplicación. Simplemente agregue el android:noHistory="true"atributo <activity>que desee, en AndroidManifest.xml
LocalPCGuy el

¿Debería esto return;? Lo hace en la guía de entrenamiento .
Keith el

¡Muchas gracias!
DmitryKanunnikoff

113

Esta es mi solución Funciona también en Fragment.

webView.setOnKeyListener(new OnKeyListener()
{
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event)
    {
        if(event.getAction() == KeyEvent.ACTION_DOWN)
        {
            WebView webView = (WebView) v;

            switch(keyCode)
            {
                case KeyEvent.KEYCODE_BACK:
                    if(webView.canGoBack())
                    {
                        webView.goBack();
                        return true;
                    }
                    break;
            }
        }

        return false;
    }
});

16
Esta es mi opinión, esta debería ser la respuesta adecuada.
Arvin

2
¿Por qué esta respuesta debería ser la respuesta correcta? ¿Algún problema con las dos respuestas principales?
ca9163d9

12
@ dc7a9163d9 una actividad puede querer tener varias vistas u objetos que dependen de keyDown. Esta respuesta resume la necesidad de que la actividad reduzca la dependencia a través de la vista web (que es un mejor diseño). Además, las aplicaciones más nuevas utilizan casi exclusivamente fragmentos en lugar de actividades, y esta respuesta admite ese caso de uso en comparación con los demás
David T.

Me gusta este enfoque. En lugar de toda la actividad escuchando solo el WebView
davejoem

De acuerdo, esto es mejor, por lo que la actividad principal no necesita tener una WebView solo utilizada por fragmentos.
Jannik

18

Referencia completa para el botón siguiente y la barra de progreso: volver a colocar el botón siguiente en la vista web

Si desea ir a la página de retroceso cuando hace clic en el botón de retroceso del teléfono, use esto:

@Override
public void onBackPressed() {
    if (webView.canGoBack()) {
        webView.goBack();
    } else {
        super.onBackPressed();
    }
} 

También puede crear un botón de retroceso personalizado como este:

btnback.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

            if (wv.canGoBack()) {
                wv.goBack();
            }
        }
    }); 

16

El enfoque también debe ser verificado en onBackPressed

    @Override
    public void onBackPressed() {
        if (mWebview.isFocused() && mWebview.canGoBack()) {
            mWebview.goBack();       
        } else {
            super.onBackPressed();
            finish();
        }
    }

2
Suena plausible, ¿podría explicar por qué?
SharpC

14

¿Por qué no usar onBackPressed()?

@Override
public void onBackPressed()
{
    // super.onBackPressed(); Do not call me!

    // Go to the previous web page.
}

porque solo sdk 2.2 y superior admite este método ... no funciona con sdk 1.6
Maher Abuthraa

1
otoh, Honeycomb y las más nuevas no tienen una tecla de retroceso de hardware, lo que hace que nunca se llame a onKeyDown
junkdog

10

Aquí hay un código con confirmación de salida:

@Override
    public void onBackPressed()
    {
        if(webView.canGoBack()){
            webView.goBack();
        }else{
            new AlertDialog.Builder(this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Exit!")
            .setMessage("Are you sure you want to close?")
            .setPositiveButton("Yes", new DialogInterface.OnClickListener()
            {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();    
                }

            })
            .setNegativeButton("No", null)
            .show();    
        }   
    }

6
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    // Check if the key event was the Back button and if there's history
    if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {
        myWebView.goBack();
        return true;
    }
    // If it wasn't the Back key or there's no web page history, bubble up to the default
    // system behavior (probably exit the activity)
    return super.onKeyDown(keyCode, event);
}

3

En kotlin:

override fun onBackPressed() {
    when {
        webView.canGoBack() -> webView.goBack()
        else -> super.onBackPressed()
    }
}

webView: identificación del componente webview en xml, si se usa una referencia sintética.


2

La primera respuesta de FoamyGuy es correcta pero tengo algunas adiciones; Las bajas reputaciones no me permiten hacer comentarios. Si por alguna razón su página no se carga, asegúrese de establecer una marca para tomar nota de la falla y luego verifíquela en la anulación onBackPressed. De lo contrario, su canGoBack () se ejecutará para siempre sin dirigirse a la actividad de respaldo real si estaba allí:

//flag with class wide access 
public boolean ploadFailFlag = false;

//your error handling override
@Override
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
    onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
    ploadFailFlag = true;       //note this change 
    .....
    .....
}

//finally to the answer to this question:
@Override
public void onBackPressed() {
    if(checkinWebView.canGoBack()){
        //if page load fails, go back for web view will not go back - no page to go to - yet overriding the super 
        if(ploadFailFlag){
            super.onBackPressed();
        }else {
            checkinWebView.goBack();
        }
    }else {
        Toast.makeText(getBaseContext(), "super:", Toast.LENGTH_LONG).show();
        super.onBackPressed();
    }
}

1

Las siguientes bibliotecas de su clase deben manejar onBackKeyPressed. canGoBack () comprueba si la vista web puede hacer referencia a la página anterior. Si es posible, utilice la función goBack () para hacer referencia a la página anterior (volver).

 @Override
        public void onBackPressed() {
          if( mWebview.canGoBack()){
               mWebview.goBack(); 
           }else{
            //Do something else. like trigger pop up. Add rate app or see more app
           }
  }

1

Aquí está la solución de Kotlin:

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    if (event?.action != ACTION_UP || event.keyCode != KEYCODE_BACK) {
        return super.onKeyUp(keyCode, event)
    }

    if (mWebView.canGoBack()) {
        mWebView.goBack()
    } else {
        finish()
    }
    return true
}

0

Camino oficial de Kotlin:

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    // Check if the key event was the Back button and if there's history
    if (keyCode == KeyEvent.KEYCODE_BACK && myWebView.canGoBack()) {
        myWebView.goBack()
        return true
    }
    // If it wasn't the Back key or there's no web page history, bubble up to the default
    // system behavior (probably exit the activity)
    return super.onKeyDown(keyCode, event)
}

https://developer.android.com/guide/webapps/webview.html#NavigatingHistory


0

Si alguien quiere manejar backPressed para un webView dentro de un fragmento , entonces puede usar el siguiente código.

  1. Copie el siguiente código en su Activityclase (que contiene un fragmento YourFragmmentName)

    @Override
    public void onBackPressed() {
    List<Fragment> fragmentList = getSupportFragmentManager().getFragments();
    
    boolean handled = false;
    for(Object f: fragmentList) {
        if(f instanceof YourFragmentName) {
            handled = ((YourFragmentName)f).onBackPressed();
            if(handled) {
                break;
            }
        }
    }
    
    if(!handled) {
        super.onBackPressed();
    }

    }

  2. Copia este código en el fragmento YourFragmentName

    public boolean onBackPressed() {
       if (webView.canGoBack()) {
           webView.goBack();
           return true;
       } else {
           return false;
       }
    }

Notas

  • Activity debe reemplazarse con la clase de actividad real que está utilizando.
  • YourFragmentName debe reemplazarse con el nombre de su Fragmento.
  • Declarar webViewen YourFragmentNameforma que se puede acceder desde dentro de la función.

0

Puede probar esto para webview en un fragmento:

private lateinit var webView: WebView

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val root = inflater.inflate(R.layout.fragment_name, container, false)
    webView = root!!.findViewById(R.id.home_web_view)
    var url: String = "http://yoururl.com"
    webView.settings.javaScriptEnabled = true
    webView.webViewClient = WebViewClient()
    webView.loadUrl(url)
    webView.canGoBack()
    webView.setOnKeyListener{ v, keyCode, event ->
        if(keyCode == KeyEvent.KEYCODE_BACK && event.action == MotionEvent.ACTION_UP
            && webView.canGoBack()){
            webView.goBack()
            return@setOnKeyListener true
        }
        false
    }
    return root
}

-2

use este código para volver a la página y cuando llegue la última página, salga de la actividad

 @Override
    public void onBackPressed() {
        super.onBackPressed();
        Intent intent=new Intent(LiveImage.this,DashBoard.class);
        startActivity(intent);
    }

-5

Webview en actividad, el siguiente código funcionó para mí, finalice la actividad después de cargar la URL en webview.in presionada de nuevo, vaya a la actividad anterior

 webView = (WebView) findViewById(R.id.info_webView);
 webView.loadUrl(value);
 finish();
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.