2012-06-01 11 views
19

Un pulsante attiva un'azione che deve essere richiamata una sola volta. Il pulsante è disabilitato e nascosta nel gestore onClick prima che venga eseguita l'azione:Android: impedisce più eventi onClick su un pulsante (che è stato disabilitato)

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) 
} 

Anche se il pulsante è disabilitato immediatamente, è comunque possibile attivare più eventi "onclick" toccando più volte molto rapidamente. (Ad esempio, performTaskOnce viene chiamato più volte). Sembra che gli eventi onClick siano in coda prima che il pulsante sia effettivamente disabilitato.

Potrei risolvere il problema controllando in ogni singolo handle onClick se il pulsante corrispondente è già disabilitato ma sembra un trucco. C'è un modo migliore per evitare questo problema?

Il problema si verifica su Android 2.3.6, non riesco a riprodurlo su Android 4.0.3. Ma data la rarità dei dispositivi 4.x, non è un'opzione per escludere i dispositivi più vecchi.

+0

che il problema mi dava fastidio per giorni .. – mohnage7

risposta

7

è possibile impostare una variabile booleana true quando il pulsante viene cliccato e impostato su false quando hai finito di elaborare il clic.

In questo modo è possibile ignorare più clic e non dover disabilitare il pulsante evitando eventualmente fastidiosi sfarfallii del pulsante.

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

Questo sembra più semplice. In iOS, la classe UIApplication ha un messaggio 'beginIgnoringInteractionEvents' che può farlo a livello globale. Questo può essere carino a volte. Non riesco a trovare un equivalente per Android, tuttavia. Potresti anche usare una semplice guardia "se (! ProcessClick) return;". Questo ti darebbe un po 'meno di nidificazione. –

+0

@DaveCameron +1 Totalmente d'accordo con te –

-1

dichiarano un varieble e usarlo come

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; 
} 


    } 
}); 

da questo a prevenire più clic sul pulsante

spero che aiutare

+1

Utilizzare un int per questo e incrementarlo è meno chiaro di un flag. Inoltre non hai mostrato come/quando riportarlo a zero. Inoltre, perché una variabile di classe invece di una variabile di istanza? –

4

Nell'interesse di mantenere 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

il codice pulito è pulito;) – mohnage7

1

Bit ritardo, ma questo potrebbe essere utile a qualcuno. Nel mio caso, sto chiamando un'altra attività così;

Dichiarare un valore booleano;

boolean clickable; 

Nell'ascoltatore del clic;

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

Abilitare quando viene chiamato onResume;

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