I have a canvas.DrawText. I want to use gestures to dynamically change the text color and font. This is all working nice using a popup view class. But I want to make this more direct maybe using Fling scroll.
There are millions of colors and by sliding finger on the screen I thought I could increase/decrease the colorInteger and send it to paint.setColor(colorInteger ); before I draw. I have tried all day using various methods.
I have public boolean onTouchEvent(MotionEvent event) {
I know I must catch the x/y in MotionEvent.ACTION_DOWN
Wanted to use the screen left edge for color change and screen right for Font change. I have 21 ttf fonts.
The thing is, I see there is the OnGestureListener onscroll implementation but that will disable my onTouchEvent right? I have lots of movement going on in there.
public boolean onTouchEvent(MotionEvent event) {
Any idea?
You can use GestureDetector. Implement a GestureDetector.OnGestureListener and catch gestures there.
class MyActivity extends Activity implements GestureDetector.OnGestureListener {
// ....
gestureDetector = new GestureDetector(getContext(), this);
Provide GestureDetector with touch events like this:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (gestureDetector.onTouchEvent(event))
return true;
else return super.onTouchEvent(event);
}
In GestureDetector.OnGestureListener's onDown you must return true if you want to process this gesture. E.g. then the user puts his finger donw in a specified area return true, and false otherwise. If false is returned here, complicated sequences (like fling or scroll) started with this event will not be detected.
Related
I have developed a game that shoots when player touches the screen by using onTouchListener for my custom SurfaceView and Thread.
But now I want to change the approach and instead of onTouchListener I added onTouchEvent to the SurfaceView o my Activity.
The problem is that I get some kind of offset when I click on the emulator.
Everything is working great, except that offset keeps appearing and I don't understand why.
Also let me mention that my app is running in landscape mode, maybe this is relevant.
I suspect that it isn't working properly because onTouchListener was added to the view and depended on it, but onTouchEvent doesn't depend on the view.
Also my view doesn't have any padding or margin properties, it is full-screen view (fill_parent).
Does anyone have any ideas on this?
I have done my application, and everything works correctly now, but i still do not know what the problem was.
After lots of debugging of my application the onTouchEvent returned random Y values that were always higher than the ones that the onTouchListener returned. And i am not sure why this is hapening since my view that recognizes the onTouchListener is a full-screen view.
So i figured out a way to get passed this by doing some math.
The first function that the android calls is the onTouch method which gives the correct values but just for one touch. I needed it to give right values even on the MotionEvent.ACTION_MOVE so i noticed that MotionEvent.ACTION_MOVE is actually doing correctly depending on the first touch recognized by the onTouchEvent.
So i just got the coordinate Y from the onTouch and the different coordinate with the offset from onTouchEvent calculated the difference and in every onTouchEvent from there, until the user lifts up their finger, i just subtract that difference and that gives me the correct value.
If anyone else has this problem, and doesn't know how to fix it, here is my code, maybe it will be helpful.
#Override
public boolean onTouchEvent(MotionEvent arg1) {
/*you can only touch when the thread is running*/
if(game.state() != STATE_PAUSE){
if(arg1.getAction() == MotionEvent.ACTION_DOWN){
coordinateX = arg1.getX();
coordinateY = arg1.getY();
differenceY = Math.abs(coordinateY - touchedY);
coordinateY = coordinateY - differenceY;
shootingIsOkay = true;
game.setDrawCircle(coordinateX,coordinateY);
}
if(arg1.getAction() == MotionEvent.ACTION_MOVE){
coordinateX = arg1.getX();
coordinateY = arg1.getY();
coordinateY = coordinateY - differenceY;
shootingIsOkay = true;
game.setDrawCircle(coordinateX,coordinateY);
}
if(arg1.getAction() == MotionEvent.ACTION_UP){
shootingIsOkay = false;
}
}
return false;
}
And the onTouch method that is called from the onTouchListener that depends on the view is just simple, here:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
touchedY = arg1.getY();
return false;
}
If anyone knows how to fix this problem, please post your answer, i am very curious why this is happening
My app needs to detect simple gestures (scroll, tap, long tap), and pinch zoom. Either detector works fine on its own - GestureDetector.SimpleOnGestureListener for tap / scroll and ScaleGestureDetector.SimpleOnScaleGestureListener for pinch zoom. The problem is combining the two. More specifically, it is very hard to start pinch zoom so that a couple of onScroll events are not generated before onScaleBegin.
Is there any good way to fix this? The only solution I can think about is buffer a few events before processing them (event queue), and discard onScroll / onTap without processing once onScaleBegin is detected. But that would introduce input lag (which my app already has and I don't want to make it even worse).
try this:
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean res = mScaleGestureDetector.onTouchEvent(event);
if (!mScaleGestureDetector.isInProgress()) {
res = mGestureDetector.onTouchEvent(event);
}
return res;
}
I have a problem with my app : I have a FrameLayout with a Fragment which contains a map from the Google Maps Android APi (v2), and a customized view which I use to display various buttons on top of the map.
I'd like some of these elements not to be shown while the map is being moved, for this I use the onTouchEvent() function of the View :
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
pressed = true;
invalidate();
break;
case MotionEvent.ACTION_UP:
pressed = false;
invalidate();
break;
}
return false;
}
The onDraw() function only displays the elements drawn over the map if pressed == false;
Now, my problem is in the return : if I put false, I say the event wasn't consumed, and the Android OS no longer notifies me when touch events are recorded, thus the MotionEvent.ACTION_UP isn't detected and the buttons stay hidden. If I put true, the touch events are no longer detected this time by the GoogleMap object, and I can't move the map around. Is there a way to keep detecting all future touch events, while not consuming the first event ?
Use onInterceptTouchEvent or dispatchTouchEvent.
You may read about the differences here: Android: Difference between onInterceptTouchEvent and dispatchTouchEvent?
What should I use if I want to have buttons on an image? I mean, being able to click on certain points of an image and see some info.
What if I want to display text on that points? Imagine I am having a map of my neighbor for example, and I want some info to be displayed (for example my home). And if someone press on my home he could see further details, like my name, my phone and so on. The image(aka the map) will be stable, it wont change, like a background.
You'll have to implement the method onTouch from the interface OnTouchListener. For example:
OnTouchListener listener = new OnTouchListener() {
#Override
public false onTouch(View v, MotionEvent event) {
if(!event.getAction() == MotionEvent.ACTION_DOWN)
return false; //If the touch event was not putting the finger down on the screen, return false(Actions may be move, up, and so on)
final float x = event.getX();
final float y = event.getY();
if(x and y are in some range)
doFirstThing();
else if(x and y are in another range..)
doSecondThing();
//... and so on...
//In the end, you must return a boolean saying whether you "consumed" the event - if you handled the event or not.
}
}
And don't forget to set the listener as the OnTouchListener for your ImageView!
imageView.setOnTouchListener(listener);
I believe for what you are trying to achieve you don't need to use buttons. Instead, create a custom view, in your onDraw method draw the images and handle the onTouch events as Jong suggested. Once you detected a click on your home for example, you could create another view with info about it and display it to user.
For info on how to create custom view you may refer to this queestion for example. Google around for it
I would like an android button to be triggered if a user drags across it and releases his finger on it in addition to the standard activation if it is clicked and released.
I was trying to use the ACTION_MOVE MotionEvent, but this event is only triggered between ACTION_DOWN and ACTION_UP events. I also think that ACTION_OUTSIDE might be a solution. Is there a way to do this?
Here is my code with the actions taken stripped out (b is a button):
b.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction()== MotionEvent.ACTION_DOWN){
//Tiggers correctly
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
//Triggers correctly between events, but not when the finger is dragged ontop outside of the element
} else if (event.getAction() == MotionEvent.ACTION_OUTSIDE){
//Can't get this to trigger in any case but I think it might be the solution
} else if (event.getAction() == MotionEvent.ACTION_UP){
//Triggers correctly
}
}
return false;
}
});
ACTION_OUTSIDE can be triggered only when your touch area is extended by the ViewRoot.
If you think about dragging, you have 2 options, but for both of them you can detect rectangle, where your button positioned on screen View.getHitRect(Rect) and then, basing on this knowledge you can decide wheter MotionEvent is inside Rect or not.
Otherwise you can create DragLayer and implement all logic there.
You might want to give the Gesture Listener a try. There is a rather good description about how to use it here.
It seems like you need to extend Button and add possibilities for gesture detection in order to accomplish this.