I am trying to create view that sites underneath all others that will perform an action when 3 fingers are touched. These activities all have their own touches and swipes.
I have got this to kind of work by creating a class that extends linearlayout and intercepting touches. and adding this in xml.
But this is only being called when an item like button or view is a clickable or touchable surface and isn't becoming a touchable surface itself.
in
public class MyCatcher extends LinearLayout {
#Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
// multitouch!! - touch down
int count = event.getPointerCount(); // Number of 'fingers' in this
if (count > 3) {
doThis(mContext);
}
}
return super.onInterceptTouchEvent(event);
}
And in xml
<packagename.MyCatcher
....>
my normal layout
</packagename.MyCatcher>
So this code is working when an item that is touchable is touched but not becoming its own touch layer.
I have tried setontouchlister in the constructor with no luck.
Thanks for any help
EXTRA: When setting the touchlistener via onAttach I can get it to catch touches but I can't use event.getPointerCount() like normal as it's returning 1.
I'm worried this may take up lots of processing?/
Instead of a Layout, create a normal View and add it to your existing layout so that it spans the whole screen and lays "above" all other views (in z-order). Now it should get all touch events prior to all other views. Your onTouch... implementation should make sure to pass all touch events along to the other views (except if you want e.g. buttons not to work under certain circumstances, then do not pass the events along).
onintercepttouchevent()
Is called only whenever a touch event is occured. ie; touch event occurs only when a view item like button,textbox,etc having onclicklistener enabled is pressed . For your question you need to set the onclicklistener for the entire view.
Related
It's my understanding that Android event propagation goes from parent to child, that is to say, it starts with the outermost element and inwards from there. My question is, why is it that when I try to scroll vertically a listview that is inside a viewpager that is wrapped on a scrollview, the listview moves, and not the viewpager.
Okay, let me rephrase that:
I'm trying to create a menu that appears when the user pulls down the view pager, let me make that even clearer:
Scrollview
My custom Menu
ViewPager (with three fragments, all of them have a lisview)
ListView
I understand that what I'm trying to do is a bit odd, but bear with me just for this time. :)
What can I do to "disable" momentarily the list views scrolling.
Thanks
It seems you have to override the scrolling event. A good webpage is Disable scrolling in Android ListView .
Mainly look at dispatchTouchEvent. Snippet of it:
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int actionMasked = ev.getActionMasked() & MotionEvent.ACTION_MASK;
if (actionMasked == MotionEvent.ACTION_MOVE) {
// Ignore move events
return true;
}
Personally I wish it is simpler than this like disabling scroll method.
I'm working with Drag and Drop, everythings is OK, but, let consider this scene: i have a LinearLayout is parent view, and it have one child view is ImageView. LinearLayout is listen for OnDragListener, and ImageView is dragedView. So, when i drag the ImageView, the DragEvent.ACTION_DRAG_STARTED doesn't occurs, and then DragEvent.ACTION_DRAG_ENDED doesn't occurs too.
Mean while, the other actions are working as expected.
P/s: When working, there is one problem when i drag my ImageView (inside my LinearLayout) out side of my LinearLayout and drop it, so, my ImageView is disappear and there is no event is invoked. I want to detect this case to bring my ImageView turn back to it's original position.
Can anybody give me a suggestion?
Thanks!
accordding to the implementation of ViewGroup.dispatchDragEvent(), ViewGroup does not handle STARTED ENDED if any child has handled the event.
public boolean dispatchDragEvent(DragEvent event) {
.... // dispatch event to children
// If none of our children could handle the event, try here
if (!retval) {
// Call up to the View implementation that dispatches to installed listeners
retval = super.dispatchDragEvent(event);
}
}
I have a custom linearlayout in which I have two gridviews.
I want to have multitouch on the complete linearlayout, ie, first touch can be in one gridview and second touch can be in another gridview and the linear layout should be able to get multitouch events for this (ACTION_DOWN and ACTION_POINTER_DOWN). I am able to get this by overriding onInterceptTouchEvent in my custom layout.
Now I also want the gridview to scroll independently if required. Although gridview is a scrollable view, it is not able to do so, because I have intercepted the 'down' event. I see that when I try to scroll two events are generated : 'ACTION_DOWN' and 'ACTION_MOVE'.
Since I need ACTION_DOWN for multitouch use case I want it to be sent to linearlayout as well.
Is there a possibility to send the ACTION_DOWN event to both the linearlayout as well as my child view which is gridView in this case?
Need help.
You don't have to intercept ACTION_DOWN just to monitor that it flowed through your container view. In other words, you can override onInterceptTouchEvent() to monitor the touch events before they are passed to the appropriate child view by the framework, but as long as you don't screw with the return value it won't actually steal subsequent touch events from the grid elements. For example:
public boolean onInterceptTouchEvent (MotionEvent ev)
if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
//Touchdown!
}
//Don't modify this and touch interaction will happen normally
return super.onInterceptTouchEvent(ev);
}
This allows you to see the event without taking it away from the child element(s).
I tried to understand how Android handle touch event and got a little bit confused. From what I understand touch event are send to the root view and pass down to the children.
I have a FrameLayout that is a container for Fragment.
First fragment view is a ScrollView, second one is some kind of Gallery (HorizontalListView) and the last one is also FrameLayout. Only one fragment in the layout each time.
What I want to do is to identify user swipes on the screen, for the app use. I want to count the swipes and do something after some number of swipes.
I tried to put a OnTouchListener on the top FrameLayout but it doesn't get called when the child is the ScrollView or the Gallery. I tried to return false and also true in the end of onTouch, but I get same result - it's never being called.
How can I do it?
I just want to "transparently" handle the touch events and passing them on like I didn't even touch them.
My understanding is that it actually goes the other direction. The Child views get their event triggered first (sort of). The root view get's it's dispatchTouchEvent() called, which propagates the event down to the children's onTouchEvent(), and then, depending on whether they return true or false, the parent's onTouchEvent() is called.
The normal solution for intercepting things like this is to override dispatchTouchEvent(MotionEvent ev) in one's activity like so:
#Override
public boolean dispatchTouchEvent (MotionEvent ev) {
// Do your calcluations
return super.dispatchTouchEvent(ev);
}
The documentation for this one is here. Note that you can also override that method in any ViewGroup (such as a FrameLayout, etc)
I have 4 buttons on an activity. I have set Touch Listeners for all the buttons.
Button1.setOnTouchListener(this);
Button2.setOnTouchListener(this);
Button3.setOnTouchListener(this);
Button4.setOnTouchListener(this);
All I want to do is to get MotionEvent.ACTION_DOWN and MotionEvent.ACTION_UP when I am moving my finger over the buttons.
I am getting these events when I am touching INDIVIDUAL buttons, but not when I move my finger from one button to another.
In this case, first button should get ACTION_UP message and the next button should get ACTION_DOWN message.
Kindly help.
There is a certain logic in such behavior of touchevents.
I think the best decision for you will be to set OnTouchListener to parent view of Button1, Button2, etc or override its OnTouchEvent() method. After that you will be able to send MotionEvent to child views (buttons in your case) manually when it's necessary.
My initial instinct is that you are sending all of the touch events to the same function, causing some type of bottleneck.
What if you seperate the touch handlers into four seperate functions like this - that way, all buttons have independent touch handlers and there is no collission by having them all using the same function to handle their collective events. Make a seperate "onTouchEventListener" for each button and have it look like this:
Button1.setOnTouchListener(button1Listener);
Button2.setOnTouchListener(button2Listener);
Button3.setOnTouchListener(button3Listener);
Button4.setOnTouchListener(button4Listener);
Here is how to do it from the Android docs:
// Create an anonymous implementation of OnClickListener
private OnClickListener mCorkyListener = new OnClickListener() {
public void onClick(View v) {
// do something when the button is clicked
}
};
protected void onCreate(Bundle savedValues) {
...
// Capture our button from layout
Button button = (Button)findViewById(R.id.corky);
// Register the onClick listener with the implementation above
button.setOnClickListener(mCorkyListener);
...
}
Since you're trying to capture a MotionEvent that involves all of the buttons, as opposed to just one, you will have to capture the MotionEvents in the parent view, then dispatch them to children buttons in the form of MotionEvent.ACTION_DOWN followed by MotionEvent.ACTION_UP.
I did something similar to make a multitouch keyboard out of a RelativeLayout containing many buttons. I basically overrided dispatchTouchEvent and kept track of each finger, sending ACITON_DOWN and ACTION_UP in place of ACTION_POINTER_DOWN and ACTION_POINTER_UP for secondary fingers to children.
It may be useful to look at the source of ViewGroup and see how it dispatches events to its children, and tweak the behavior to check when the finger goes out of child button bounds, and if so, send an ACTION_UP on the old button then an ACTION_DOWN on the new button.