Double Tap in android View - java

In a view I want to detect both single tap and double tap. It works fine with me. I can detect both single and double tap. Please find my code
#Override
public boolean onTouch(View view, MotionEvent me) {
// No dragging during animation at the moment.
// TODO: Stop animation on touch event and return to drag mode.
boolean result = true;
result = gestureDetector.onTouchEvent(me);//return the double tap events
if(result)
return false;
switch (me.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
private String fileName;
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
// event when double tap occurs
#Override
public boolean onDoubleTap(MotionEvent e) {
float x = e.getX();
float y = e.getY();
if(player!=null && player.isPlaying())
{
player.stop();
}
else
{
setFileName(x);
player = new AudioPlayer(fileName);
player.play();
}
return true;
}
}
I am doing some code in Action_UP event. So even when I do a double tap, for the first tap the ACTION_UP event is called and the corresponding code is executed. I want to prevent this from happening. How can I do this. I just want to make sure that the ACTION_UP is called only when the user is done with his gesture. Not immediately after his partial gesture . In this case its being called on finger up of first tap.
How can I make this work in android?
Thanks

According to gesture listener documentation, you need to return true for onSingleTapConfirmed & onDoubleTap. Otherwise the event is not consumed and gestureDetector.onTouchEvent(me); returns false.

Related

What is the difference between onDoubleTap listener and onDoubleTapEvent listener

I am pretty new in Android, and recently learned about gestures!
What is the difference between 2 of these methods?
#Override
public boolean onDoubleTap(MotionEvent e) {
return false;
}
And this one
#Override
public boolean onDoubleTapEvent(MotionEvent e) {
return false;
}
They seem to do the same thing. Which one do you use, and what is the difference
simple answer will be
boolean onDoubleTap (MotionEvent e) -
Notified when a double-tap occurs.
you can Notifi when a double-tap happens
and param motionEvent is forThe down motion event of the first tap.
boolean onDoubleTapEvent (MotionEvent e)` -
Notified when an event within a double-tap gesture occurs
you can Notifi an event within a double-tap gesture occurs, including the down, move, and up events and and param motionEvent is for the The motion event
so with doubleTapEvent you can get additional tab gestures along with the tap
have a look --> https://stackoverflow.com/a/19629851/5188159 this might helpful for your touch gestures
further more try to understand what happens here with this example
//initialize the Gesture Detector
gd = new GestureDetector(this);
//set the on Double tap listener
gd.setOnDoubleTapListener(new OnDoubleTapListener()
{
#Override
public boolean onDoubleTap(MotionEvent e)
{
//set text color to green
tvTap.setTextColor(0xff00ff00);
//print a confirmation message
tvTap.setText("The screen has been double tapped.");
return false;
}
#Override
public boolean onDoubleTapEvent(MotionEvent e)
{
//if the second tap hadn't been released and it's being moved
if(e.getAction() == MotionEvent.ACTION_MOVE)
{
//set text to blue
tvTapEvent.setTextColor(0xff0000ff);
//print a confirmation message and the position
tvTapEvent.setText("Double tap with movement. Position:\n"
+ "X:" + Float.toString(e.getRawX()) +
"\nY: " + Float.toString(e.getRawY()));
}
else if(e.getAction() == MotionEvent.ACTION_UP)//user released the screen
{
tvTapEvent.setText("");
}
return false;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e)
{
//set text color to red
tvTap.setTextColor(0xffff0000);
//print a confirmation message and the tap position
tvTap.setText("Double tap failed. Please try again.");
return false;
}
});

How do I get an image view to continually move across the screen when a button is held down?

I have searched high and low for an answer to this and can't find one anywhere that works.
For my university assignment i need to create an adventure game in android studio. I want it so when I click down and hold an arrow button (so in the case given its the up button), that the ImageView (player) will continually move across the screen until I release the button. Ive tried OnTouchListeners and mouse events using ACTION_UP and ACTION_DOWN and that works but not for what i need as it still only moves one step when clicked.
ImageView IV_player;
Button ButtonUp;
IV_player = (ImageView) findViewById(R.id.IV_player);
ButtonUp = (Button) findViewById(R.id.ButtonUp);
ButtonUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IV_player.setY(IV_player.getY() - 32);
}
});
Treat your touch listener like a state machine. When an ACTION_DOWN event occurs, start doing whatever action you want to do. When an ACTION_UP/ACTION_CANCEL event occurs stop your action. So how do you go about implementing this?
Your state flag can be a simple boolean:
boolean shouldCharacterMove = false;
Define your touch listener for the view.
ButtonUp.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
setShouldCharacterMove(true);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
setShouldCharacterMove(false);
break;
}
return true;
}
});
Before we define setShouldCharacterMove we need to figure out a way to move items. We can do this through a Runnable that runs after X milliseconds.
private final Runnable characterMoveRunnable = new Runnable() {
#Override
public void run() {
float y = IV_player.getTranslationY();
IV_player.setTranslationY(y + 5); // Doesn't have to be 5.
if (shouldCharacterMove) {
IV_player.postDelayed(this, 16); // 60fps
}
}
};
Now we can define setShouldCharacterMove:
void setShouldCharacterMove(boolean shouldMove) {
shouldCharacterMove = shouldMove;
IV_player.removeCallbacks(characterMoveRunnable);
if (shouldMove) {
IV_player.post(characterMoveRunnable);
}
}

onInterceptTouchEvent only gets ACTION_DOWN

Why do ViewGroup's only get ACTION_DOWN in the onInterceptTouchEvent? According to the docs, as long as false is returned it should receive all the event types.
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent%28android.view.MotionEvent%29
Point #3.
Sample code:
public class MainActivity extends Activity {
private static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Container(this));
}
private class Container extends LinearLayout {
public Container(Context context) {
super(context);
setBackgroundColor(0xFF0000FF);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG, "onInterceptTouchEvent");
int action = ev.getActionMasked();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "onInterceptTouchEvent.ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i(TAG, "onInterceptTouchEvent.ACTION_MOVE");
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
Log.i(TAG, "onInterceptTouchEvent.ACTION_UP");
break;
}
return super.onInterceptTouchEvent(ev);
}
}
}
I'll answer my own question: onInterceptTouchEvent only get called if the parent has a child view which returns "true" from onTouchEvent. Once the child returns true, the parent now has a chance to intercept that event.
I get the same problem. I had read many posts about it:
onInterceptTouchEvent only gets ACTION_DOWN
onInterceptTouchEvent's ACTION_UP and ACTION_MOVE never gets called
onInterceptTouchEvent, onTouchEvent only see ACTION_DOWN
onInterceptTouchEvent never receives action_move
I also had read android doc:
http://developer.android.com/training/gestures/viewgroup.html
http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent(android.view.MotionEvent)
All answers are same. I tried many times, always not get onInterceptTouchEvent
() be called if not down event.
I read source code, I guess that something is changed:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
}
boolean handled = false;
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
// Handle an initial down.
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Throw away all previous state when starting a new touch gesture.
// The framework may have dropped the up or cancel event for the previous gesture
// due to an app switch, ANR, or some other state change.
cancelAndClearTouchTargets(ev);
resetTouchState();
}
// Check for interception.
final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
|| mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action); // restore action in case it was changed
} else {
intercepted = false;
}
} else {
// There are no touch targets and this action is not an initial down
// so this view group continues to intercept touches.
intercepted = true;
}
According above code, onInterceptTouchEvent(ev) is only be called when MotionEvent.ACTION_DOWN, this is what we tried and found. So, what I guess is, the code is changed, but doc not.
If you want spy or monitor all the events include those been sent to child views, you can override dispatchTouchEvent() like this:
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
MyLog.d(MyLog.DEBUG, "dispatchTouchEvent(): "+event.getAction());
if (isEnabled()) {
MyLog.d(MyLog.DEBUG, "dispatchTouchEvent()2: "+event.getAction());
processEvent(event);//here you get all events include move & up
super.dispatchTouchEvent(event);
return true; //to keep receive event that follow down event
}
return super.dispatchTouchEvent(event);
}
I have the runnable code at: https://github.com/maxyou/gesturebutton/blob/master/src/com/maxproj/gesturebutton/GestureButtonLayout.java
dispatchTouchEvent, onInterceptTouchEvent, requestDisallowInterceptTouchEvent
[Touch event flow]
The official doc
Activity.dispatchTouchEvent(MotionEvent) - This allows your Activity to intercept all touch events before they are dispatched to the window.
ViewGroup.onInterceptTouchEvent(MotionEvent) - This allows a ViewGroup to watch events as they are dispatched to child Views. It is recursively function (from parent to parent)
ViewParent.requestDisallowInterceptTouchEvent(boolean) - Call this upon a parent View to indicate that it should not intercept touch events with onInterceptTouchEvent(MotionEvent).

Need boolean value isTouched()

I need to detect WHEN the screen is touched. The onTouchEvent method only detects when the finger is moving. I need method which returns boolean value true, when the finger touches screen and returns false, when its not.
Here's a very basic implementation of the onTouch method that modifies a boolean value to know if a the screen is touched. You may need to tweak it to suit your specific needs (and maybe handle multi touch)
private boolean mIsScreenTouched;
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN :
case MotionEvent.ACTION_MOVE :
mIsScreenTouched = true;
break;
case MotionEvent.ACTION_CANCEL :
case MotionEvent.ACTION_UP :
mIsScreenTouched = false;
break;
}
return true;
}
#Override
public boolean dispatchTouchEvent(MotionEvent e) {
// TODO Auto-generated method stub
super.dispatchTouchEvent(e);
if(btn.onTouchEvent(e)){
return btn.onTouchEvent(e);
}else{
return false;
}
}

Lower continuously my media volume with a button

I want to lower (or upper) my media volume in my application when an "OnLongClickEvent" is detected.
Here my sources :
buttongauche.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
playSound(R.raw.volumevoixdiminue);
audio.adjustStreamVolume(AudioManager.STREAM_MUSIC,AudioManager.ADJUST_LOWER,AudioManager.FLAG_SHOW_UI);
return true;
}
});
Actually, it's work : when I do a longClick on my "buttongauche", the volume is decreased by 1.
Now I would like to know how could I do if I want to lower the sound continuously (for example, decrease sound by 1 every 2 seconde when the button is down).
My button "buttongauche" has already an "onClickEvent", who do other things (change the index of a menu).
Thanks
Declare field boolean touching = false; that says whether or not you are touching the button and use OnTouchListener to change it. When you start touching also start volumeThread that lowers the volume every 1 second, and dies when you stop touching.
buttongauche.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touching = true;
Thread volumeThread = new Thread() {
public void run() {
while (touching) {
audio.adjustStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER,
AudioManager.FLAG_SHOW_UI);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
volumeThread.start();
break;
case MotionEvent.ACTION_UP:
touching = false;
break;
}
return false;
}
});

Categories

Resources