I am pulling my hair out trying to find a reliable way to consistently allow a user to long press on a gridview item for up to 15 seconds and ALWAYS ALWAYS receive a ACTION_UP when the users finger is released. I also would like to allow unlimited movement once a long press is detected NOTHING besides a finger being lifted should interrupt this process.
Some additional info this is all inside of a gridview which is inside of a pager , but ik what i want to do is possible bc ik of other apps that do such a thing flawlessly
Here is my most recent attempt, but ive tried dozens:
public class recordVideo implements OnLongClickListener,OnTouchListener {
private int position;
private String clicked_uid;
public recordVideo(int position){
this.position=position;
}
#Override
public boolean onLongClick(View v){
//do things
// Do something when your hold starts here.
isSpeakButtonLongPressed = true;
Log.i("START_RECORD","longClick");
return true;
}
#Override
public boolean onTouch(View pView, MotionEvent pEvent) {
pView.onTouchEvent(pEvent);
if (pEvent.getAction() == MotionEvent.ACTION_DOWN) {
Log.i("START","video");
}
// 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.
Log.i("STOP_RECORD","video");
if (isSpeakButtonLongPressed) {
// Do something when the button is released.
isSpeakButtonLongPressed = false;
// Log.i("STOP_RECORD","video");
}
}
return true;
}
Related
I would like to create a RecyclerView in which a user can long click an image and preview the full sized image until they release the long click.
I have it mostly working but the issue I am having is that if I begin the long click, then drag my finger (while still holding the click down), the listener no longer waits for my ACTION_UP event and the preview image never goes away. Is there a way to sort of ignore the dragging/scrolling so that my preview image view goes away when I release the long click?
This is what I have for event listeners:
/* Long press will trigger hover previewer */
holder.thumbnailImageView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View pView) {
holder.thumbnailImageView.setOnTouchListener(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) {
if (isImageViewPressed) {
// Do something when the button is released.
isImageViewPressed = false;
mHoverView.setVisibility(View.GONE);
}
}
return false;
}
});
isImageViewPressed = true;
GlideApp.load(item.getUrl()).into(mHoverView);
mHoverView.setVisibility(View.VISIBLE);
return true;
}
});
/* Long press will trigger hover previewer */
holder.thumbnailImageView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View pView) {
isImageViewPressed = true;
GlideApp.load(item.getUrl()).into(mHoverView);
mHoverView.setVisibility(View.VISIBLE);
return true;
}
});
holder.thumbnailImageView.setOnTouchListener(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 (isImageViewPressed && pEvent.getAction() == MotionEvent.ACTION_UP) {
// Do something when the button is released.
isImageViewPressed = false;
mHoverView.setVisibility(View.GONE);
}
return true;
}
});
This will work and your code is not working as longClickListener does't get's the event of action down(and neither of action down) and what you are doing currently is setting the listener for touch which never got Action_DOWN i.e by default the View's ontouch() return false on Action_Down so u have to override and return true before action down is called so that it get's action move and action up etc.
I have a mouse connected to my Android 6.0 tablet. I'm trying to listen to left and right mouse pressed and released events in my onTouch. It works fine when pressing mouse buttons, but when releasing mouse buttons getButtonState() always returns 0 so I cannot tell which button (left or right?) has been released.
Here is my code:
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getSource() == InputDevice.SOURCE_MOUSE) {
int action = event.getActionMasked();
int mouseButton = event.getButtonState();
Log.v("Test", "Action: " + action + " MouseButton: " + mouseButton);
return true;
}
return false;
}
When Action is 1 (i.e. ACTION_UP), mouseButton is always 0 so I cannot tell if the left or right mouse button has just been released. When Action is 0 (i.e. ACTION_DOWN), mouseButton is correctly set to BUTTON_PRIMARY or BUTTON_SECONDARY.
So does anybody have an idea how to distinguish between left and right mouse button releases on ACTION_UP?
To answer my own question, isButtonPressed() is the key to this problem. By monitoring isButtonPressed() and caching its result whenever you get a MotionEvent from InputDevice.SOURCE_MOUSE you can tell which button has been pressed or released. You also need to be careful not to limit those observations to ACTION_UP and ACTION_DOWN because when one button is already down and another one is pressed or released, you won't get ACTION_DOWN or ACTION_UP for it but an ACTION_MOVE event will be generated as soon as there's already one button down.
So in terms of code, a solution could look like this:
private static boolean mLeftDown = false, mRightDown = false, mMiddleDown = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getSource() == InputDevice.SOURCE_MOUSE) {
boolean leftDown = event.isButtonPressed(MotionEvent.BUTTON_PRIMARY);
boolean rightDown = event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
boolean middleDown = event.isButtonPressed(MotionEvent.BUTTON_TERTIARY);
if(leftDown != mLeftDown) {
// left button pressed or released
mLeftDown = leftDown;
}
if(rightDown != mRightDown) {
// right button pressed or released
mRightDown = rightDown;
}
if(middleDown != mMiddleDown) {
// middle button pressed or released
mMiddleDown = middleDown;
}
return true;
}
return false;
}
This works fine on Android 6.0.
In an Android app, I have a feature to record audio. The idea is to have a button that has 2 types of actions.
I can click on button and start recording, and when I click again it stops recording.
I can hold the button and while its being held the app records, when I release it, the app stops recording.
I tried with a OnTouchListener
private static int CLICK_ACTION_THRESHHOLD = 250;
public long lastTouchDown;
public boolean isClick;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()){
case R.id.main_record_button:
case R.id.main_record2:
if (event.getAction() == MotionEvent.ACTION_DOWN) {
lastTouchDown = System.currentTimeMillis();
//... do stuff
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
if (System.currentTimeMillis() - lastTouchDown < CLICK_ACTION_THRESHHOLD) {
isClick = true;
//...do other stuff
}
Whats the best way to achieve this ?
OnTouchListener is not very intuitive to work with.
I have used GestureDetector to track userbehavior. I think that is what you should use. Check out the implementation and callbacks here: https://developer.android.com/training/gestures/detector.html
You should go through this library to understand whats he is doing or you can use it too.
Also the this Thread.
Consider an Activity where button named "Scan", is disabled as soon as Bluetooth device gets connected, for preventing further scanning.
mScan.setEnabled(false);
But as soon as it is connected I need the same button mScan to show some dialog which has additional functionalities when it is Long Pressed.
The problem is as I disabled the mScan button I can't perform onLongClick function.
How Can I achieve the same?
Seeking your help.
You can use a custom OnTouchListener:
long lastDown;
long lastDuration;
public class YourOnTouchListener implements View.OnTouchListener
{
public YourOnTouchListener(some parameters) {
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
lastDuration = System.currentTimeMillis() - lastDown;
if (lastDuration > the duration you want) {
//do what you want here
return true;
}
return false;
}
}
Then you can control what you want to do according to a duration, and it works with a OnClickListener as well.
I am currently trying to detect an ongoing touch event in my Android app.
In detail I want to recognize within a fragment whether the user touches any part of the app's screen.
Android's OnTouchListener works as expected except if the touch event lasts longer than a few seconds without moving.
For example the first 1-2 seconds of touch are being detected but everything after won't.
Is there something like an "OnPressListener" or a workaround?
If it's a well defined gesture you are trying to detect, have a look at GestureDetector.
http://developer.android.com/reference/android/view/GestureDetector.html
You can use
aButton.setOnLongClickListener(new OnLongClickListener() {
public boolean onLongClick(View arg0) {
Toast.makeText(getApplicationContext(), "Long Clicked " ,
Toast.LENGTH_SHORT).show();
return true; // <- set to true
}
});
on your aButton and if you are using API < 19 you have to add
android:longClickable="true"
Attribute to your aButton in layout xml.
I finally found it out.
The solution is to use a simple OnTouchListener:
private boolean pressed = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
pressed = true;
} else if ((action == MotionEvent.ACTION_UP)
|| (action == MotionEvent.ACTION_CANCEL)) {
pressed = false;
}
return true;
}