I have code that onTouchEvent passes the touch event to a member ScaleGestureDetector and if the scale GD triggers a onScaleEvent on my scale listener, I scale up the display item. If the onScale event is not triggered I treat this event as a potential drag and move the displayed item around. I have observed that on certain devices the ScaleGestureDetector triggers an onScale event for me, even if there is just a single finger touching the screen. Is this expected? What is the recommended mechanism to deal with scales and drags at the same time?
If I'm correct you're triggering mScaleGestureDetector.onTouchEvent(mEvent) with single pointer (mEvent.getPointersCount() == 1). It is supposed to be triggered with pointers greater than 1. Make sure you're triggering with pointersCount > 1 Eg.
if(pointersCount >1) {
TOUCH_GESTURE_MODE = GESTURE_MODE_SCALE;
mScaleGestureDetector.onTouchEvent(mEvent);
return true;
}
Related
I would like to have two overlapping image views in my layout. But I need both of them to receive the user input event, such as touchDown, touchUp, pinch, etc. Could you give me some hints? Thanks
Set an onTouchListener on both of the views. Then, get the bounds of both views (x and y location, width, height). When the onTouch method is fired, check to see which view was touched, then check to see if the x and y location of the touch falls within the bounds of the other view. If it does, then forward the touch event to the other view by doing:
otherView.onTouch(motionEvent);
I am pretty new to libgdx, and I'm trying to use gestures to move a ball across the screen when a flinging motion is made on the screen. I've made this gesture listener:
class MyGestureListener implements GestureListener {
public boolean fling(float velocityX, float velocityY, int button) {
if (Math.abs(velocityY) > 0) {
ballPositionY -= velocityY*Gdx.graphics.getDeltaTime();
}
return false;
}
}
I initialized a detector for the listener in create() and used the following for the ball image in render():
batch.draw(ballImage, ballPositionX, ballPositionY);
The ball moves on fling in proportion to the velocity of the fling. However, it jumps across the screen from its original position to the final position, but I want it to have continuous motion (i.e. see it move across the screen rather than just jump from one point to another). How would I do this? Is fling appropriate for this task, or would you use something else? I am guessing this might have something to do with the frame rate but am not sure.
Thanks in advance!
You're only updating the ball's position when there is an active fling. You need to apply changes (velocity) to the ball on every frame to get smooth continuous animation. In Libgdx, the render callback is called every frame and is where you should update the state of your objects.
In the "fling" callback you should store the new velocity, and then on each call to your render callback you should change the ball's position based on the velocity and the time that has passed since the last render (the Gdx.graphics.getDeltaTime()).
My parent view is a RelativeLayout, I added a triangle to it extending the View class. I draw the triangle using canvas and paint. The problem i am facing is that, when i touch on the relative layout, both touch listeners , the relative layout and triangle are being triggered. I just want the triangle to take the exact space as it requires. How can i limit my customview , triangle in this case to take it's space, rather than occupying the entire parent layout.
Actually my requirement is: i have one relative layout on the layout i am adding some custom views dynamically. those have touch listeners for for dragging points in the triangle,but those are taking full screen of my parent view, because of that i am unable to trigger touch listeners separately for parent and child view's.
I've spent countless hours developing solutions for this problem and I just couldn't get my head around it. Any help would be greatly appreciated.
From what I am gathering you are saying,you have a triangle drawn within a RelativeLayout in a CustomView. The actual View size is FILL_PARENT for both width and height. So the square representing the touchable area of the triangle is the same as the square representing the touchable area of the parent RelativeLayout.
You would like touch events inside the triangle's drawn area to be received by the triangle View and anything outside to be received by the parent. It is not possible to define a custom touch area from what I understand.
That doesn't stop you manipulating drawing bounds and touch focus to accomplish what you want though.
How it can be done
Ensure that your CustomView with the triange always receives the touch event. When it receives the touch event, it perform basic maths to figure out if the touch was within your triangle area (you must have your triangle bounds you use to draw your triangle saved as global variables for the CustomView).
Then a simple conditional statement to determine whether to act on and consume or pass the event on (do you even want a TouchEvent on your RelativeLayout to do anything? If not that makes this a lot easier).
Example code skeleton:
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean inTriangle = false;
float x = event.getX();
float y = event.getY();
// This really depends on what behaviour you want, if a drag extends outside the
// triangle bounds, do you want this to end the touch event? This code could be done
// more efficiently depending on your choices / needs
// Do maths to figure out if the point is actually inside the triangle. Once again,
// many solutions and some much easier than others depending on type of triangle
// This flow will only register events in the triangle, and do nothing when outside
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (inTriangle) {
// Do whatever it is you want to do
return true; // to say you consumed the event if necessary
} else {
return false; // parent RelativeLayout should now get touch event
}
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (inTriangle) {
// Do whatever it is you want
return true;
} else {
// Do nothing
return true; // So is stil consumed
}
}
return true;
}
To be honest, the question is way to open-ended / unclear to give anything more specific. But this is how you would accomplish what you asked. Just apply it to your specific scenario.
Note: I have encountered issues with TouchEvent passing, so if you really do want to pass them to specific places, you may have to investigate toying with View.dispatchTouchEvent() if the order your Touches are being processed becomes an issue.
You have an issue to handle the touch events of the triangle because you are getting touch on both the view RalativeLayout and Your customview.
To solve this issue you have to do some changes in the customview's onTouchEvent.
Like If you are touching on the customview and if you want to handle the event then from onTouchEvent you will have to return true instead of false so that your parent view will not get the touch events.
Speaking of events we know that the touch screen method onTouchEvent (MotionEvent events) allows you to capture touch events on the screen and event.getX () and
event.getY () give me the coordinates of the touch as float values (ie values with a comma).
Specifically, I realized that taking logcat using the fixed point the finger in a mobile phone screen and not moving it, the event is not only perceived but MotionEvent.ACTION_DOWN MotionEvent.ACTION_MOVE and returned coordinates are manifold. This i can understand because the surface of the finger touches more points and more by reading the device coordinates believe that the finger moves while holding it.
My problem is that I would read the color of one pixel of a color image when I hold your finger still. In particular I need the central area occupied by the finger.
First, assuming you have a Bitmap object, I have to round to integer coordinates of the touch as the getPixel (intX, int y) coordinates of the entire Bitmap wants to return the pixel color.
Then how do I get the central point of touch? Be that there is a function that can help me? Keep in mind that while I stopped and read the value of a pixel on the image then I start to move slowly and even though I always record every move the center pixel. I need this because every move, if you change the color of the image in pixels, I want to vibrate or not the device.
If I could stop thinking about themselves in a dynamic array to store the coordinates of different pixels and search for the center of gravity, but moving I do not know what to do. I think however, that the research center of gravity, if not done very efficiently, can be slow during the move and then give the wrong results. If the CG is not quite enough for me to another point belonging to the environment.
I hope you can help me maybe with a few lines of code sketched.
Thanks in advance.
To get the touch position of finger, just cast the getX() and getY() to int and perform your desired tasks.
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN ) {
getPixelAt((int)event.getX(), (int)event.getY());
}
}
you can put you on main activity class when you can want to touch event occurs. let see you can put following code or not ? and return is most important as well.
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mDistanceX = 0;
}
return super.onTouchEvent(event);
}
Please look at this picture
Basically you swipe your finger down in that area and it shows more.. how can i do this?
With ViewFlipper or (horizontal)ListView , each page/item of the ViewFlipper/ListView will contain one of these view (I bet they are images). For swiping you can implement``onTouchListener or GestureDetector. Override onFling() method, and measure the distance between the initial X-coordinate when the user touches the screen and the final x-coordinate when the user releases the touch screen with method event1.getX() and event2.getX(). Do not measure the motion on the y-axis since --->(to right, you have motion only on the x-axis). Intialize some MINIMUM_DISTANCE to compare with the result from difference between the first touch and release touch coordinate (event1.getX() - event2.getX()).