Handling multiple touch in android such as Pinch In and Pinch Out - android

I am trying to achieve multi touch in such as way that when user pinch out with two finger outside I need to handle one event and on pinching In other event. No ZOOMING IN or ZOOMING OUT NEEDED.
So I am handling onTouchEvent on layout, but could not get conditions true for pinching in and pinching out.
Here is code,
layout.setOnTouchListener(new View.OnTouchListener() {
private int mActivePointerId;
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
mActivePointerId = motionEvent.getPointerId(0);
Log.d(TAG, "COUNT"+motionEvent.getPointerCount());
if(motionEvent.getPointerCount() > 1){
if((motionEvent.getAction() == motionEvent.ACTION_UP) && (motionEvent.getAction() == motionEvent.ACTION_POINTER_DOWN))
Log.d(TAG, "Multi Touch Upwards ");
return true;
} else if((motionEvent.getAction() == motionEvent.ACTION_DOWN) && (motionEvent.getAction() == motionEvent.ACTION_POINTER_UP)){
Log.d(TAG, "Multi Touch DownWard ");
return true;
}
else{
Log.d(TAG, "It is signal Touch");
}
return true;
}
});
I referred this link but not very clear example
Any suggestion to make it work...thanks

You can make it work with the help of ScaleGestureDector. Just need to check the scalefactor if the scale factor would be more then 1 then it would be Pinch Out otherwise Pinch In.
Here is good example, it is very easy and fits your need well,
Just follow the instruction from this link ScaleGestureDector

So , you need to use a GestureDetector.
Whatsoever you need to do with that pinching out and in, you can most likely do with a gesture listener.
Check out this link and take 5 minutes to read, your answer is there for sure: http://developer.android.com/training/gestures/detector.html
Just for the record:I have been using GestureListener recently ,so it's a "sure thing".

Related

Looking for a listener that differentiates between up and down events

I apologise for the somewhat noobish question.
I've tried googling it, searching this site and the android developer site, yet didn't manage to find an answer.
I'm looking for a listener that differentiates between up and down events. Currently I'm using OnTouchListener, but it gets triggered very fast, causing a noticable lag, even when I immediately return after an event that is not Down and Up.
I've also tried OnClickListener, but it seems to only get triggered when you lift your finger up, rather than have seperate events for down click and up click like I need.
Would appreciate some help,
Thanks!
YourBtn.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_UP){
//do stuff
}
else if(event.getAction() == MotionEvent.ACTION_DOWN){
//do stuff
}
else if(event.getAction() == MotionEvent.ACTION_CANCEL){
//do stuff
}
return true; //return false can be used it depends
}
});
P.S: it can be: a button, a textview, an imageview or any UI element
I strongly recommend to always add ACTION_CANCEL to avoid any misbehaviours or crashes
See this:
https://developer.android.com/training/graphics/opengl/touch.html
Override the following method on your activity, then you can treat each case, when the user touch the screen, and when he take of his finger.
#Override
public boolean onTouchEvent(MotionEvent e) {
// MotionEvent reports input details from the touch screen
// and other input controls. In this case, you are only
// interested in events where the touch position changed.
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
// do your stuff
break;
case MotionEvent.ACTION_UP:
// do your stuff
break;
}
return true;
}
You should look at GestureDetector to simplify your touch event handling.

Detect two finger touch and zoom out image

Good Day, I'm newbie in android, and I would like to add one functionality to my app, but I haven't idea how to do that.
I would like to Zoom Out image by Two-finger touch
I had implemented Zoom In functionality using Subsampling Scale Image View library, but how to add Zoom Out I don't know.
What I have for now? What I must to add under the Toast to get ImageView normal state?
ImageView mImageView;
mImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
int action = motionEvent.getAction();
int fingersCount = motionEvent.getPointerCount();
if((action == MotionEvent.ACTION_POINTER_UP) && (fingersCount == 2)){
Toast.makeText(getActivity(), "Double tap", Toast.LENGTH_SHORT).show();
}
return false;
}
});
Anyway, thank you!

MotionEvent.ACTION_DOWN in Android is too sensitive. This event is received even if the screen is simply touched for a moment

I have a layout(A table layout). Whenever the user performs a "down" gesture, a specific function needs to be called. However,the ontouchlistener captures the event immediately instead of waiting until the user performs a proper "pull down" gesture.
My code is :
homePageTableLayout.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_DOWN)) {
startSyncData();
}
return true;
}
});
Currently, what's happening is that the startSyncData() function gets called immediately.
The end result should be somewhat similar to the commonly used "pulltorefresh" library for android but in this usecase, I don't have to update the view. I just have to post some data to the server.
I can't use the "pulltorefresh" library because it does not support "pulling" a tablelayout. I tried putting the tablelayout inside a scrollview but that only spoiled the UI.
You can try doing it in ACTION_MOVE or ACTION_UP - if you need it to be done exclusively on swipe down gesture, this should help, introduce four global floats: x, y, x1, y1, then in ACTION_DOWN:
x = event.getX();
y = event.getY();
ACTION_MOVE or ACTION_UP:
x1 = event.getX();
y1 = event.getY();
and then in ACTION_UP:
if (y1 > y) { //pointer moved down (y = 0 is at the top of the screen)
startSyncData();
}
Its not that easy. It works properly since you are catching MotionEvent.ACTION_DOWN. It doesn't mean a gesture like swipe down it means that user touched the screen (finger down, the touch or gesture just started). Now you need to catch MotionEvent.ACTION_UP (finger up, gesture or touch ends here) and decide if there was a gesture you need. http://developer.android.com/training/gestures/detector.html
http://developer.android.com/training/gestures/index.html
MotionEvent.ACTION_MOVE repeatedly gets called. So if you want startSyncData() to run after moving a certain distance, calculate how much you want the user to move before running the method.
The key is that ACTION_DOWN is not a downwards movement on the screen, but it means the user pressed down onto the screen.
homePageTableLayout.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_DOWN)) {
startFlg = 1;
} else if ((event.getAction() == MotionEvent.ACTION_MOVE)) {
if (startFlg==1){
// Calculate distance moved by using event.getRawX() and event.getRawX() and THEN run your method
startSyncData();
}
}
return true;
}
});

How to detect if a device is tapped with a pen/stick or something

Hi I want to find out if a tablet is hit with a stick lightly. I thought maybe implementing accellerometer should do it. But all I see people are trying to find shake movements with it. Is there any way I can find if a tablet is tapped? Thanks.
EDIT: By saying tapping I mean tapping on top of the tablet. Not in screen.
I'd say the easier route for detecting a tap would be by measuring the time between a MotionEvent.ACTION_DOWN and the corresponding ACTION_UP - if it's less than, say, 350 milliseconds, the user was probably doing a tap and not a press or some other sort of gesture.
Consider something like the following, where TAP_CONSTANT would be an integer constant for the tap duration:
private class TapListener implements OnTouchListener
{
long time;
#Override
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
time = System.currentTimeMillis();
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
if ((System.currentTimeMillis() - time) <= TAP_CONSTANT)
{
// We have a tap event, call our tap logic methods!
return true;
}
}
return false;
}
}

Overriding onTouchEvent competing with ScrollView

From a simplistic overview I have a custom View that contains some bitmaps the user can drag around and resize.
The way I do this is fairly standard as in I override onTouchEvent in my CustomView and check if the user is touching within an image, etc.
My problem comes when I want to place this CustomView in a ScrollView. This works, but the ScrollView and the CustomView seem to compete for MotionEvents, i.e. when I try to drag an image it either moves sluggishly or the view scrolls.
I'm thinking I may have to extend a ScrollView so I can override onInterceptTouchEvent and let it know if the user is within the bounds of an image not to try and scroll. But then because the ScrollView is higher up in the hierarchy how would I get access to the CustomView's current state?
Is there a better way?
Normally Android uses a long press to begin a drag in cases like these since it helps disambiguate when the user intends to drag an item vs. scroll the item's container. But if you have an unambiguous signal when the user begins dragging an item, try getParent().requestDisallowInterceptTouchEvent(true) from the custom view when you know the user is beginning a drag. (Docs for this method here.) This will prevent the ScrollView from intercepting touch events until the end of the current gesture.
None of the solutions found worked "out of the box" for me, probably because my custom view extends View, not ViewGroup, and thus I can't implement onInterceptTouchEvent.
Also calling getParent().requestDisallowInterceptTouchEvent(true) was throwing NPE, or doing nothing at all.
Finally this is how I solved the problem:
Inside your custom onTouchEvent call requestDisallow... when your view will take care of the event. For example:
#Override
public boolean onTouchEvent(MotionEvent event) {
Point pt = new Point( (int)event.getX(), (int)event.getY() );
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (/*this is an interesting event my View will handle*/) {
// here is the fix! now without NPE
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(true);
}
clicked_on_image = true;
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (clicked_on_image) {
//do stuff, drag the image or whatever
}
} else if (event.getAction() == MotionEvent.ACTION_UP) {
clicked_on_image = false;
}
return true;
}
Now my custom view works fine, handling some events and letting scrollView catch the ones we don't care about. Found the solution here: http://android-devblog.blogspot.com.es/2011/01/scrolling-inside-scrollview.html
Hope it helps.
There is an Android event called MotionEvent.ACTION_CANCEL (value = 3). All I do is override my custom control's onTouchEvent method and capture this value. If I detect this condition then I respond accordingly.
Here is some code:
#Override
public boolean onTouchEvent(MotionEvent event) {
if(isTouchable) {
int maskedAction = event.getActionMasked();
if (maskedAction == MotionEvent.ACTION_DOWN) {
this.setTextColor(resources.getColor(R.color.octane_orange));
initialClick = event.getX();
} else if (maskedAction == MotionEvent.ACTION_UP) {
this.setTextColor(defaultTextColor);
endingClick = event.getX();
checkIfSwipeOrClick(initialClick, endingClick, range);
} else if(maskedAction == MotionEvent.ACTION_CANCEL)
this.setTextColor(defaultTextColor);
}
return true;
}

Categories

Resources