Android - Detect End of Long Press
I think your best bet is to use a combination of the onLongClickListener() and onTouchListener() for that button. You'll need to catch certain events on the touch listener since it will trigger for every touch event.
Try something like the following:
class Blah extends Activity {
private Button mSpeak;
private boolean isSpeakButtonLongPressed = false;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.blahlayout);
Button mSpeak = (Button)findViewById(R.id.speakbutton);
mSpeak.setOnLongClickListener(speakHoldListener);
mSpeak.setOnTouchListener(speakTouchListener);
}
private View.OnLongClickListener speakHoldListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View pView) {
// Do something when your hold starts here.
isSpeakButtonLongPressed = true;
return true;
}
}
private View.OnTouchListener speakTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View pView, MotionEvent pEvent) {
pView.onTouchEvent(pEvent);
// We're only interested in when the button is released.
if (pEvent.getAction() == MotionEvent.ACTION_UP) {
// We're only interested in anything if our speak button is currently pressed.
if (isSpeakButtonLongPressed) {
// Do something when the button is released.
isSpeakButtonLongPressed = false;
}
}
return false;
}
}
}
Detecting a long press in Android
Try this:
final GestureDetector gestureDetector = new GestureDetector(new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
Log.e("", "Longpress detected");
}
});
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
};
How to detect how long a button was pressed in Android?
You need to capture the time when the user presses down on the button, and the time when the user releases the button. The difference between these times is the duration of the press.
In order to achieve this, you will need to apply a View.OnTouchListener
to the button, and use SystemClock.elapsedRealtime
(as opposed to System.currentTimeMillis
for this reason) to capture the time of the events.
button.setOnTouchListener (object : View.OnTouchListener {
var startTime = 0L
var endTime = 0L
override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean {
when (motionEvent?.action) {
MotionEvent.ACTION_DOWN -> {
// user pressed down on the button; capture start time
startTime = SystemClock.elapsedRealtime()
return true
}
MotionEvent.ACTION_CANCEL, // if user moves their finger off the button before releasing
MotionEvent.ACTION_UP -> {
// user released the button; capture end time and calculate the result
endTime = SystemClock.elapsedRealtime()
if (endTime > startTime) {
val ellapsedTime = endTime - startTime
// do something with ellapsedTime
}
return true
}
}
return false
}
})
Distinguish between short tap (click) and long press in OnTouchListener
The Android way to handle this is using a gesture detector. The guide topic Detect common gestures discusses how to do this and provides sample code.
The only reason you would want to operate at the relatively low level of a touch listener is if the logic you want to implement isn't already packaged up by one of the library gesture detectors. Fortunately for you, long press and dragging are already supported gestures.
If you want to write your own logic anyway, the source code for the appropriate gesture detectors can provide you a good starting point. However, I strongly discourage that because the logic can be very tricky, with lots of edge cases to get right.
EDIT: Okay, after reading the documentation, I confess that it isn't quite as simple as I thought. But it shouldn't be very complicated, either. The problem is clear from the documentation for setIsLongpressEnabled
(emphasis added):
Set whether longpress is enabled, if this is enabled when a user presses and holds down you get a longpress event and nothing further.
So after a long press is detected, you won't get any scrolling call-backs. You can work around this as follows. The usual way a gesture detector is used is to write your onTouchEvent
method as follows:
override fun onTouchEvent(event: MotionEvent): Boolean {
return if (mDetector.onTouchEvent(event)) {
true
} else {
super.onTouchEvent(event)
}
}
You can change this to something like the following:
var isLongPress = false
override fun onTouchEvent(event: MotionEvent): Boolean {
if (mDetector.onTouchEvent(event)) {
val action = MotionEventCompat.getActionMasked(event)
if (isLongPress && action == MotionEvent.ACTION_MOVE) {
// process the drag
}
return true
}
return super.onTouchEvent(event)
}
Then in the onLongPress
call-back, capture the event coordinates and set isLongPress
. You can clear isLongPress
in the onDown
call-back. You should then ignore any call-backs to onScroll
because, by definition, they will be happening without a long press.
Related Topics
How to Download a PDF File in Android
Using Webview Sethttpauthusernamepassword
Send Intent from Service to Activity
Gradle Flavors for Android with Custom Source Sets - What Should the Gradle Files Look Like
How to Change Actionbar Tab Indicator Programmatically
Displaying Android Asset Files in a Webview
Uploading Image from Android to Gcs
How to Show/Hide Password in Textformfield
Android: How to Measure Total Height of Listview
Chaining Requests in Retrofit + Rxjava
How to Download a Video File to Sd Card
E/Surface﹕ Getslotfrombufferlocked: Unknown Buffer: 0Xab7519C0
Start Google Hangout from Intent in New Hangouts Android App
Add an Array of Buttons to a Gridview in an Android Application
How to Set Searchview Textsize
How to Detect "Recent Apps" System Button Clicks (Honeycomb+)