2012-06-01 16 views
19

Un botón desencadena una acción que solo debe invocarse una vez. El botón está desactivado y escondido en el controlador onClick antes de realizar la acción:Android: evitar múltiples eventos onClick en un botón (que se ha deshabilitado)

someButton.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     someButton.setEnabled(false); 
     someButton.setClickable(false); 
     someButton.setVisibility(View.GONE); 
     performTaskOnce(); 
     } 
    }); 

private void performTaskOnce() { 
    Log.i("myapp", "Performing task"); 
    //Do something nontrivial that takes a few ms (like changing the view hierarchy) 
} 

pesar de que el botón se desactiva de inmediato, no obstante es posible disparar múltiples eventos "onclick" pulsando varias veces muy rápidamente. (es decir, performTaskOnce se llama varias veces). Parece que los eventos onClick están en cola antes de que el botón esté realmente desactivado.

Podría solucionar el problema marcando en cada uno de los controles onClick si el botón correspondiente ya está desactivado, pero parece un truco. ¿Hay alguna forma mejor de evitar este problema?

El problema ocurre en Android 2.3.6, no puedo reproducirlo en Android 4.0.3. Pero dada la rareza de los dispositivos 4.x, no es una opción excluir los dispositivos más antiguos.

+0

ese problema me molestaba por días .. – mohnage7

Respuesta

7

podría establecer una variable booleana true cuando el botón se hace clic y se establece en falso cuando haya terminado de procesar el clic.

De esta manera puede ignorar múltiples clics y no tener que deshabilitar el botón, posiblemente evitando el molesto parpadeo del botón.

boolean processClick=true; 
someButton.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     if(processClick) 
     { 
     someButton.setEnabled(false); 
     someButton.setClickable(false); 
     someButton.setVisibility(View.GONE); 
     performTaskOnce(); 
     } 
     processClick=false; 
     } 
    }); 

private void performTaskOnce() { 
    Log.i("myapp", "Performing task"); 
    //Do something nontrivial that takes a few ms (like changing the view hierarchy) 
} 
+3

Esto parece más simple. En iOS, la clase UIApplication tiene un mensaje 'beginIgnoringInteractionEvents' que puede hacer esto globalmente. Eso puede ser agradable a veces. Sin embargo, no puedo encontrar un equivalente para Android. También podría usar un protector simple "if (! ProcessClick) return;". Eso te daría un poco menos de anidación. –

+0

@DaveCameron +1 Totalmente de acuerdo con usted –

-1

declarar una varieble y utilizarlo como

boolean boo = false; 
someButton.setOnClickListener(new OnClickListener() { 
@Override 
public void onClick(View v) { 
if(boo==false){ 
    someButton.setEnabled(false); 
    someButton.setClickable(false); 
    someButton.setVisibility(View.GONE); 
    boo = true; 
} 


    } 
}); 

por esta a prevenir varios clics en el botón

espero que ayude

+1

Usar un int para esto, y aumentarlo, es menos claro que un indicador. Tampoco has mostrado cómo/cuándo volver a ponerlo en cero. Además, ¿por qué una variable de clase en lugar de una variable de instancia? –

4

En el interés de mantener DRY:

// Implementation 
public abstract class OneShotClickListener implements View.OnClickListener { 
    private boolean hasClicked; 

    @Override public final void onClick(View v) { 
     if (!hasClicked) { 
      onClicked(v); 
      hasClicked = true; 
     } 
    } 

    public abstract void onClicked(View v); 
} 

// Usage example 
public class MyActivity extends Activity { 
    private View myView; 

    @Override protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     myView.setOnClickListener(new OneShotClickListener() { 
      @Override public void onClicked(View v) { 
       // do clicky stuff 
      } 
     }); 
    } 
} 
+0

el código de limpieza está limpio;) – mohnage7

1

poco tarde, pero esto podría ser de utilidad para alguien. En mi caso estoy llamando otra actividad así;

Declarar un booleano;

boolean clickable; 

En el oyente click;

if(clickable){ 
    // Launch other activity 
    clickable = false; 
} 

Activar cuando se llama onResume;

@Override 
public void onResume() { 
    Log.e(TAG, "onResume"); 
    super.onResume(); 
    clickable = true; 
} 
Cuestiones relacionadas