2010-03-17 12 views
29

Tengo una actividad que contiene varios elementos editables por el usuario (un campo EditText, RatingBar, etc.). Me gustaría avisar al usuario si se presiona el botón Atrás/Inicio y se han realizado cambios que aún no se han guardado. Después de leer la documentación de Android, parece que este fragmento de código debe ir en el método onPause. Intenté poner un AlertDialog en OnPause, pero se muestra el cuadro de diálogo y luego se corta inmediatamente porque no hay nada para evitar que se complete la pausa.Android: Pedir al usuario que guarde los cambios cuando se presiona el botón Atrás

Esto es lo que he encontrado hasta el momento:

@Override 
protected void onPause() { 
    super.onPause(); 

    AlertDialog ad = new AlertDialog.Builder(this).setMessage(
      R.string.rating_exit_message).setTitle(
      R.string.rating_exit_title).setCancelable(false) 
      .setPositiveButton(android.R.string.ok, 
        new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog, 
           int whichButton) { 
          // User selects OK, save changes to db 
         } 
        }).setNeutralButton(android.R.string.cancel, 
        new DialogInterface.OnClickListener() { 
         public void onClick(DialogInterface dialog, 
           int whichButton) { 
          // User selects Cancel, discard all changes 
         } 
        }).show(); 
} 

estoy en el camino correcto o hay otra manera de lograr lo que estoy tratando de hacer aquí? ¡Cualquier ayuda sería genial!

Respuesta

95

No está del todo en la dirección correcta; lo que debe hacer es anular onKeyDown() y la escucha de la llave, a continuación, anulando el comportamiento por defecto:

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { 
     // do something on back. 
     return true; 
    } 

    return super.onKeyDown(keyCode, event); 
} 

Si sólo está apoyando a Android 2.0 y superior, han añadido una onBackPressed() se puede utilizar en su lugar:

@Override 
public void onBackPressed() { 
    // do something on back. 
    return; 
} 

Esta respuesta se ha arrancado esencialmente de this blog post. Leerlo si necesita largos prensas, compatibilidad apoyo, el apoyo a duros virtuales llaves o primas soluciones como onPreIme() etc.

+0

Utilizando el método onKeyDown() tendrá los mismos problemas que onPause(). Si intento mostrar un cuadro de diálogo de alerta en el bloque onKeyDown cuando detecto el código clave Atrás, el cuadro de diálogo aún no se bloqueará. Veré la alerta momentáneamente hasta que se presione el super.onKeyDown, lo que hará que se cierre la ventana. ¿Hay alguna manera de forzar una respuesta al AlertDialog antes de continuar? – chriskopec

+0

¿Está llamando a super.onKeyDown() si consume el botón Atrás? Supongo que debería usar "devolver verdadero" si abre el diálogo, para indicarle al sistema que ha consumido el botón Atrás, presione; de lo contrario, al llamar a super(), igual finalizará llamando a todas las cosas que terminan la actividad. –

+0

Eso es todo, ¡Gracias! – chriskopec

10

¿Qué opinas acerca de este enfoque ..

private void exit(){ 
    this.finish(); 
} 

@Override 
public boolean onKeyDown(int keyCode, KeyEvent event) { 
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { 

     AlertDialog.Builder alertbox = new AlertDialog.Builder(this); 
     alertbox.setTitle("Message"); 
     alertbox.setMessage("Quit ??? "); 

     alertbox.setPositiveButton("Yes", 
       new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface arg0, int arg1) { 
         exit(); 
        } 
       }); 

     alertbox.setNeutralButton("No", 
       new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface arg0, int arg1) { 
        } 
       }); 

     alertbox.show(); 

     return true; 
    } else { 
     return super.onKeyDown(keyCode, event); 
    } 

} 
0

Estoy haciendo lo mismo que tú. Tengo una actividad con información del cliente (EditText para nombre, apellido, correo electrónico, ..., ya sabes, EditText en todas partes) y utilicé AsyncTask para eso, y funciona maravillosamente.

@Override 
public void onBackPressed() 
{ 
      // start async task for save changes. 
    new GuardandoContactoHilo().execute() 
} 

public void VolverAtras() 
{ 
    super.onBackPressed(); 
} 

public class GuardandoContactoHilo extends AsyncTask< Void, Void, Void> 
{ 

    private ProgressDialog saving; 


    @Override 
    protected void onPreExecute() 
    { 
     super.onPreExecute(); 
     saving = new ProgressDialog(cont); 

     saving.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
     saving.setMessage("Saving customer ..."); 
     saving.show(); 
    } 

    @Override 
    protected void onPostExecute(Void result) 
    { 
     super.onPostExecute(result); 
     saving.dismiss(); 
     VolverAtras(); // go back !! 
    } 

    @Override 
    synchronized protected Void doInBackground(Void... arg0) 
    { 

     // do what you want to do before come back ! for example, save data ;) 
     return null; 
    } 

} 
2

Aquí hay un código de ejemplo:

@Override 
public void onBackPressed() {  
    if (isDirty) {   
     new AlertDialog.Builder(this) 
      .setTitle("You have made some changes.") 
      .setMessage("Would you like to save before exiting?") 
      //.setNegativeButton(android.R.string.no, null)    
      .setNegativeButton("No", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface arg0, int arg1) { 
        MyActivity.super.onBackPressed(); 
       } 
      })    
      .setPositiveButton("Yes", new DialogInterface.OnClickListener() { 
       public void onClick(DialogInterface arg0, int arg1) {      
        if (Save()) 
         MyActivity.super.onBackPressed(); 
       } 
      }).create().show(); 
    } 
    else { 
     MyActivity.super.onBackPressed(); 
    } 
} 
Cuestiones relacionadas