2012-06-01 3 views
19

Eine Schaltfläche löst eine Aktion aus, die nur einmal aufgerufen werden sollte. Die Taste ist deaktiviert und in dem onClick-Handler versteckt, bevor die Aktion ausgeführt wird:Android: Verhindert mehrere onClick-Ereignisse auf einer Schaltfläche (die deaktiviert wurde)

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

Auch wenn die Taste sofort deaktiviert wird, ist es dennoch möglich ist, mehrere „onClick“ Ereignisse ausgelöst wird, um mehrere Male sehr schnell tippen. (d. h. performTaskOnce wird mehrfach aufgerufen). Scheint, dass die onClick-Ereignisse in die Warteschlange gestellt werden, bevor die Schaltfläche tatsächlich deaktiviert wird.

Ich könnte das Problem beheben, indem Sie jedes einzelne onClick-Handle einchecken, ob die entsprechende Schaltfläche bereits deaktiviert ist, aber das scheint wie ein Hack. Gibt es einen besseren Weg, dieses Problem zu vermeiden?

Das Problem tritt auf Android 2.3.6 auf, ich kann es auf Android 4.0.3 nicht reproduzieren. Aber angesichts der Seltenheit von 4.x-Geräten ist es keine Option, ältere Geräte auszuschließen.

+0

Dieses Problem war mir für Tage nervig. – mohnage7

Antwort

7

Sie eine boolean Variable auf true gesetzt könnte die Taste los, wenn wird angeklickt und auf false gesetzt, wenn Sie mit der Bearbeitung des Klicks fertig sind.

Auf diese Weise können Sie mehrere Klicks ignorieren und müssen die Schaltfläche nicht deaktivieren, um lästiges Flackern der Schaltfläche zu vermeiden.

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

Dies scheint am einfachsten. In iOS hat die UIApplication-Klasse eine 'beginIgnoringInteractionEvents'-Nachricht, die dies global tun kann. Das kann manchmal schön sein. Ich kann jedoch kein Äquivalent für Android finden. Du könntest auch einen einfachen Wächter verwenden, wenn (! ProcessClick) zurückkehrt; ". Das würde dir etwas weniger nisten. –

+0

@DaveCameron +1 Stimme völlig mit Ihnen überein –

-1

deklarieren eine varieble und verwenden Sie es als

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


    } 
}); 

durch diese mehrere Klicks auf Ihre Schaltfläche

hoffe, es zu verhindern, dass

+1

Verwenden Sie ein int für diese, und inkrementieren, ist weniger klar als eine Flagge. Sie haben auch nicht gezeigt, wie/wann es auf Null zurückgesetzt werden soll. Warum auch eine Klassenvariable anstelle einer Instanzvariablen? –

4

Im Interesse DRY zu halten:

// 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

sauberer Code ist sauber;) – mohnage7

1

Bit spät, aber dies könnte von Nutzen jemand sein. In meinem Fall rufe ich eine andere Aktivität an;

Einen Boolean deklarieren;

boolean clickable; 

Im Klick-Listener;

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

Aktivieren, wenn onResume aufgerufen wird;

Verwandte Themen