12

If i click fast to my button in my Android app, it seems that code behind it runs twice. If i click my menu button twice the activity that has to be launch onclick just starts twice and i have to quit from it twice.

This is really annoying because if i click too fast for menu buttons i can load up a whole bunch of activities in the background and i must quit them one by one, so this is clearly a buggy state of my app i want to fix this.

What can i do with this issue?

I use simple onClickListeners and Buttons

EDIT:

Regarding to answers and comments my menu buttons look like this:

top20Button.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        favButton.setClickable(false);
        nearButton.setClickable(false);
        highlightedButton.setClickable(false);
        top20Button.setClickable(false);

        Intent i = new Intent();
        i.putExtra("showDialog", false);
        i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        i.setClass(Search.this, Top20.class);
        startActivity(i);
        finish();

    }
});

After all this correction its still the same :S When i click like a mad person multiple activites are on the history stack and i must quit multiple times.

Any suggestions ? What m i doing wrong?

Adam Varhegyi
  • 11,307
  • 33
  • 124
  • 222

8 Answers8

8

You can use following code: btn.setEnabled(false);

btn.setOnclickListener(new View.onClickListener(){

      public void onClick(View v) {
            btn.setEnabled(false);

      }
});
Shrikant Ballal
  • 7,067
  • 7
  • 41
  • 61
  • but it will then disable further clicking of other, and then how do you enable again? – Miguel May 18 '14 at 10:33
  • @Miguel: In above example, the code written in OnClickListener, starts an activity, so when user comes back to previous activity, it will automatically gets enabled. But in other cases, like if any async task is started in onClickListener, then onPostExecute() would be the best placewhere you will enable the button again. – Shrikant Ballal May 19 '14 at 05:04
6

You can Disable the view temporarily like this

public static void disableTemporarly(final View view) {

        view.setEnabled(false);
        view.post(new Runnable() {
            @Override
            public void run() {

                view.setEnabled(true);
            }
        });
    }

Edit:

The above solution will work fine. But it will become even better when using the power of Kotlin

1) Create the SafeClikc Listener

class SafeClickListener(
        private var defaultInterval: Int = 1000,
        private val onSafeCLick: (View) -> Unit
) : View.OnClickListener {

    private var lastTimeClicked: Long = 0

    override fun onClick(v: View) {
        if (SystemClock.elapsedRealtime() - lastTimeClicked < defaultInterval) {
            return
        }
        lastTimeClicked = SystemClock.elapsedRealtime()
        onSafeCLick(v)
    }
}

2) Add extension function to make it works with any view, this will create a new SafeClickListener and delegate the work to it

fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {

    val safeClickListener = SafeClickListener {
        onSafeClick(it)
    }
    setOnClickListener(safeClickListener)
}

3) Now it is very easy to use it

settingsButton.setSafeOnClickListener {
    showSettingsScreen()
}

Happy Kotlin ;)

Simon K. Gerges
  • 3,097
  • 36
  • 34
  • I used a variation of the above to solve a similar issue. Efficient and effective answer without the complexity of other approaches. – AJW Nov 02 '16 at 05:25
5
 Button.setOnClickListener(new View.OnClickListener {  
   @Override
   public void onClick(final View v) {
        v.setEnabled(false);
        v.postDelayed(new Runnable() {
         @Override
         public void run() {
            v.setEnabled(true);
         }
        },150); //150 is in milliseconds
    }
 });  
anand krish
  • 4,281
  • 4
  • 44
  • 47
2

Well, that's the expected behaviour...

Launch your new acvitity with SINGLE_TOP flag

Or try setting android:launchMode="singleInstance" for Top20 activity in your AndroidManifest.xml

Bojan Radivojevic
  • 717
  • 3
  • 12
  • 23
  • If i add this statement a strange animation is appearing on activity changing: The layout moves to left a blank screen appears then my new activity is being shown. For some reason this setting skips all my activity animations which is currently: overridePendingTransition(0, 0); If you can tell me how to disable this blank screen animation i can select your answer as an answer to my problem because now i dont have duplicated activities. =) – Adam Varhegyi Jul 04 '12 at 07:59
  • try adding NO_ANIMATION flag when launching activity :) – Bojan Radivojevic Jul 04 '12 at 14:28
2

This solves the issue of multiple Instances of activity, and still play the default animation

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Miguel
  • 3,349
  • 2
  • 32
  • 28
0

This solution fits better to my requirements. Instead using enable/disable view feature. I use the time, first, create a variable to store the last time user pressed the view* then when the user presses the view, capture the time in a variable in order to compare the current moment and the last time user pressed the view, if the differential time between times is too small, which means fast,or extremely fast just ignore it and that's it. But if its a reasonable time to you, set the last time variable with the current time and do whatever else you want to do.

@Override
public void onListItemClick(ListView list, View item, int position, long id) {

    Long now = System.currentTimeMillis();
    if((now - lastTimeSelected) > 500){
        lastTimeSelected = now;
        // your code goes here
    } else {
        Log.i(TAG, "Too fast!");
    }

}

I saw a similar answer on other post, but nobody seems to like this approach.

Community
  • 1
  • 1
AXSM
  • 1,142
  • 1
  • 12
  • 27
0

Add the following code snipet to your Activity definition in Androidmanifest.xml

android:launchMode = "singleTask"
nzala
  • 374
  • 4
  • 10
0

Use frozen variable inside Application class.

That is

public class App extends Application {
public static boolean frozen = false;
}

somewhere while click:

//...
onClick() {
if (frozen) {
return;
}
frozen = true
}
//...

Somewhere to release, for instance, when new Activity has been launched

onCreate (...) {
super.onCreate(...);
frozen = false;
}

in AndroidManifest.xml:

<application
        android:allowBackup="true"
        android:largeHeap="true"
        android:name="com.example.App"
        android:icon="@drawable/icon"
        android:label="@string/app_alias"
        android:theme="@style/AppTheme" >
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194