How can I detect any gesture in my Activity, even with many things there (Layouts, Images, RecyclerViews, etc).
I intent to create an gesture that can be done at any time.
Is it possible?
I've tried this:
findViewById(android.R.id.content).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("GESTURE", "GESTURE");
return false;
}
});
But it's not working. I think it's because the others views is intercepting the event.
Idk if is it possible to detect the gesture above the activity, like in the window.
Thank you!
You can, but it's a bit tricky. Read up on touch handling and especially onInterceptTouchEvent, which can be used on a parent to intercept touches going to the children.
You would implement that method in a (custom) root view, and then do your gesture magic in there.
Some valuable info here: Android: Difference between onInterceptTouchEvent and dispatchTouchEvent?
Related
I have a custom view that I created by extending the View class. My custom view overrides the onTouchEvent.
I want to be able to turn the view's ability to listen on and off. I need to do that from within the view. Does anyone know how I can accomplish this? Simply calling
setEnabled(false);
does not work.
Try by setting the following
setOnTouchListener(null)
I'm not sure if this is the right solution but it works:
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return true;
}
});
This blocks other touch related Listeners from receiving the Event, so onTouchEvent won't be invoked.
you can use setOnTouchListener(null) to go back to your normal state so that your onTouchEvent works again.
if you had figured out a better solution i hope that you post it.
In Android, I'm trying to capture user touches as well as User long-touches. I have an Activity and in it I override the onTouchEvent() method to handle a variety of screen touches.
I'm trying to incorporate "Long Presses" into my repertoire of User Interface choices.
I can't find a Activity.onLongTouchEvent() for me to override.
My application also has a SurfaceView and I see that I can do this:
sv.setOnLongClickListener (new View.OnLongClickListener()
{
#Override
public boolean onLongClick (View v)
{
SendAToast();
return false;
}
});
When I implement that code, it works exactly like it should.
However, now my onTouchEvent() code is never called even when I don't touch the screen long enough for it to be a "Long Press".
Is anybody aware of a way to get these two bits of code to work together?
Edit:
After I posted this, a co-worker showed me the "OnGestureListener" interface. Here's an example:
http://www.ceveni.com/2009/08/android-gestures-detection-sample-code.html
I use the interface to capture long presses, and it even provides the screen coordinates to work with (which the OnLongClickListener does not). So, it seems to do the trick.
Why this function not automatically part of the Activity? It sure seems like core functionality to me.
I would move the on touch stuff into the view's onTouchEvent instead of the Activity.
I've got an Android app which is mostly a wrapper around a WebView which show local files.
The WebView gets the events because setContentView(thewebview) is called. This works fine most of the times (since we also handle Android Webkit Browser in the online version).
Problem is that I want to add support for D-Pad/Trackball events. I've written the appropriate onKeyDown's, but the WebView is consuming the events, not the activity.
This can be fixed in two ways:
Handle the event keycode for D-Pad Down/Up/etc. in the Javascript onKeyDown function
Get and consume the appropriate key events before the webview can get them. (ofcourse also all events can be gotten, most will simply not be consumed)
Problem is I don't know how to do either. How can I do this or solve this in a different way?
Simply 'catch' the keypresses on the WebView by using View.setOnKeyListener() to handle the KeyEvents.
public void setOnKeyListener (View.OnKeyListener l)
Register a callback to be invoked when a key is pressed in this view.
In your example that would be used like this:
thewebview.setOnKeyListener(new OnKeyListener()
{
#Override
public boolean onKey(View v, int keyCode, KeyEvent event)
{
// do your stuff here
}
});
In our application we have a custom view (that extends ImageView) and in it we handle the touch events to record data. I wanted to add context menu functionality to this view and followed the guidelines in the official Android documents.
The onTouchEvent code works fine by itself. The context menu code also works fine. However, if I add them both, the context menu code stops working. I found out that with both pieces of code added, onCreateContextMenu is never called, therefore context menu is never displayed.
According to my interpretation of the Android documentation, returning false from onTouchEvent indicates that the event is not consumed, so it should be used for further processing. For some reason, it is not happening here. I would appreciate if anybody can tell me what I am missing. BTW, the target is Nexus One running 2.3.4 ROM.
Here's the code for the onTouchEvent in the custom view:
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
// Add event coordinates to an arraylist
break;
}
return false;
}
Thank you in advance for any help.
Elaborating on hackbod answer, you should probably have as last method statement return super.onTouchEvent(event);.
I guess that if you don't process the event, and if you don't invoke the default View behavior, than no one will do anything, and nothing will happen.
The point of return value might be for example to invoke some ancestor' default behavior, and let the derived class know if the ancestor processed the event or not.
After doing some search on Android Developers, referring to the topic override an existing callback method for the View here it says :
This allows you to define the default behavior for each event inside your custom View and determine whether the event should be passed on to some other child View.
Hence the main idea behind the return value is to let Android know whether the event should be passed down to child Views or not.
HTH
Edit:
Regarding the "directions" you mention in your comment, generally speaking (i.e. not only on Android) the UI event handling process goes on something like this:
At some point your derived custom control receives the event. In your event hook implementation, it's up to you whether to involve your ancestor's behavior or not. That's all you got regarding the class inheritance direction.
Then, there's the other direction, the one related to the UI controls hierarchy. Your custom control might be contained in one larger control container, and your control might as well contain other inner controls (textboxes, buttons, ...). Regarding this direction, if you declare not to process the event (returning false) then the UI event handling mechanism will pass the bucket to the containing (?) control (think the one on the background of yours).
You could call, from your long click listener,
openContextMenu(View view)
http://developer.android.com/reference/android/app/Activity.html#openContextMenu(android.view.View)
Do not register for context menu in OnCreate(), do it in onTouch() before
return true;
registerForContextMenu(View v);
openContextMenu(View v);
return true;
Returning false tells the parent that you didn't consume the event. The default implementation of View implements touch handling for that view; if you want that to execute, you must call super.onTouchEvent(event);
I encounter similar problem recently. When I enable long clickable in RecyeclerView's child, the ACTION_DOWN event can't not be received in RecyclerView's onTouchEvent.
If I changed to RecyclerView's dispatchTouchEvent, I would works. The ACTION_DOWN event can be received.
I want to listen to touch events for a viewFlipper. I've been able to listen to touch events in my activity and then modify the viewFlipper but these events are fired wherever the user is within the activity and I need to capture touch events specifically on the viewFlipper. I have tried adding setOnTouchListener but it is not called. I'm assuming the viewFlippers children (webviews) are 'consuming' the touch events.
One solution would be to setOnTouchListener's to each of the webviews but this feels like a hack. Does anyone know another way?
Thanks,
Ian
Sorry if this is a double post - but my previous post seems to have vanished.
Use ViewGroup.onInterceptTouchEvent(MotionEvent)
You should Reference the Android Documentation as it's usage is quite complicated.
Basic Summary of use:
You receive the touch event here. If you want to consume it, return true and control will be passed to the ViewFlipper's onTouchEvent(). Return false and it will continue to be passed to the child. onTouchEvent() should also return true to ensure all further events are returned to the ViewFlipper's method. The child will also receive the original event with the action ACTION_CANCEL.
Finally It worked for me. Return true by default to get multiple calls on this listener.
viewFlipper.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (this.gestureDetector.onTouchEvent(event)) {
return false;
}
return true;
}
});
I was having the same problem and found your page trying to google for an answer.
After a few very frustrating attempts I ended up finding a quite easy solution, I'm still listening to the touch on the whole activity just like you did, but on the OnTouchEvent I filter if the ViewFlippers is touched or not:
#Override
public boolean onTouchEvent(MotionEvent event) {
if(mFlip.isInTouchMode()){
return gestureDetector.onTouchEvent(event);
} else{
return super.onTouchEvent(event);
}
}
hope it helps!