I am listening for a View's long click events via setOnLongClickListener(). Can I change the long click delay / duration?
7 Answers
This is my way for set duration to long press
private int longClickDuration = 3000;
private boolean isLongPress = false;
numEquipeCheat.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
isLongPress = true;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (isLongPress) {
Vibrator vibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(100);
// set your code here
// Don't forgot to add <uses-permission android:name="android.permission.VIBRATE" /> to vibrate.
}
}
}, longClickDuration);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
isLongPress = false;
}
return true;
}
});

- 2,334
- 1
- 19
- 22

- 251
- 3
- 2
AFAIK, no. It is hard-wired in the framework via getLongPressTimeout()
on ViewConfiguration
.
You are welcome to handle your own touch events and define your own "long click" concept. Just be sure that it is not too dramatically different from what the user expects, and most likely the user will expect what all the other apps use, which is the standard 500ms duration.

- 986,068
- 189
- 2,389
- 2,491
-
3How would you go about defining your own long click concept? – zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz Mar 31 '12 at 19:34
-
Thanks, I guess I will stick with the default for now. – fhucho Mar 31 '12 at 19:58
-
@zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz probably by overriding View. Cool username BTW ;-) – fhucho Mar 31 '12 at 19:59
I defined an extension function in Kotlin inspired by @Galoway answer:
fun View.setOnVeryLongClickListener(listener: () -> Unit) {
setOnTouchListener(object : View.OnTouchListener {
private val longClickDuration = 2000L
private val handler = Handler()
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN) {
handler.postDelayed({ listener.invoke() }, longClickDuration)
} else if (event?.action == MotionEvent.ACTION_UP) {
handler.removeCallbacksAndMessages(null)
}
return true
}
})
}
Use it like this:
button.setOnVeryLongClickListener {
// Do something here
}

- 34,185
- 17
- 113
- 116
-
-
-
1I suggest you add performHapticFeedback(HapticFeedbackConstants.LONG_PRESS) before listener.invoke() to add the same haptic feedback as in case of system long click event. – AndrazP Jan 12 '21 at 08:52
This is what I use. It is similar to Cumulo Nimbus' answer, with two notable differences.
- Use the already stored event values for down time and current time. Aside from not duplicating effort, this has the nice effect of making the listener usable for multiple views at the same time without tracking start times for each individual event.
- Check
view.isPressed
to ensure the user has not moved away from the view during the touch event. This mimics the default system behavior foronClick
andonLongClick
.
long longPressTimeout = 2000;
@Override
public boolean onTouch(View view, MotionEvent event) {
if (view.isPressed() && event.getAction() == MotionEvent.ACTION_UP) {
long eventDuration = event.getEventTime() - event.getDownTime();
if (eventDuration > longPressTimeout) {
onLongClick(view);
} else {
onClick(view);
}
}
return false;
}
If the view is not normally clickable you will need to call view.setClickable(true)
for the view.isPressed()
check to work.

- 6,994
- 2
- 27
- 44
This was the simplest working solution I found to this restriction:
//Define these variables at the beginning of your Activity or Fragment:
private long then;
private int longClickDuration = 5000; //for long click to trigger after 5 seconds
...
//This can be a Button, TextView, LinearLayout, etc. if desired
ImageView imageView = (ImageView) findViewById(R.id.desired_longclick_view);
imageView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
then = (long) System.currentTimeMillis();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if ((System.currentTimeMillis() - then) > longClickDuration) {
/* Implement long click behavior here */
System.out.println("Long Click has happened!");
return false;
} else {
/* Implement short click behavior here or do nothing */
System.out.println("Short Click has happened...");
return false;
}
}
return true;
}
});

- 8,785
- 9
- 47
- 68
This is what I did for handeling both onclick and custom long click on same button
public static final int LONG_PRESS_DELAY_MILLIS = 3000;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_save:
saveInfo();
break;
default:
break;
}
}
@Override
public boolean onLongClick(View v) {
switch (v.getId()) {
case R.id.btn_save:
initSendInfo(v, System.currentTimeMillis());
return true;
default:
return false;
}
}
private void initSendInfo(final View v, final long startTime) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (v.isPressed() && System.currentTimeMillis() - startTime >= LONG_PRESS_DELAY_MILLIS) {
sendInfo();
return;
} else if (!v.isPressed()) {
return;
}
}
}, LONG_PRESS_DELAY_MILLIS);
}

- 101
- 6
-
1This works fine! To make the v and startTime accessible in the run method, they must be declared final private void initSendInfo(final View v, final long startTime) { ... } – Lipsyor Jan 21 '21 at 11:18
-
Edit: For initSendInfo method, added final keyword for arguments, as per Lipsyor's comments. Thanyou Lipsyor. – Sunny Jha Feb 03 '21 at 11:07
This is what worked for me on API 29
, while retaining the button's visual down state using Kotlin:
fun AppCompatButton.setOnVeryLongClickListener(
holdDuration: Long = 1000L,
listener: () -> Unit
) {
val handler = Handler()
val originalText = this.text
setOnTouchListener { v, event ->
if (event?.action == MotionEvent.ACTION_DOWN) {
// update the copy of the button
text = "$originalText (KEEP HOLDING)"
// fire the listener after our hold duration
handler.postDelayed({ listener.invoke() }, holdDuration)
} else if(event?.action == MotionEvent.ACTION_UP) {
// update the copy of the button
text = "$originalText (TAP & HOLD)"
// in case of an interruption, cancel everything
handler.removeCallbacksAndMessages(null)
}
// return false in order to retain the button's visual down state
false
}
}
button.setOnVeryLongClickListener {
println("very long!")
}

- 3,800
- 1
- 25
- 31