android: click event that's not being consumed - android

I need to create a click event, that's not being consumed, so that an underlying adapter receives the touch event.
I cant use an OnClickListener, because that would consume the event.
I tried my best with OnTouchListener, but if I return true the event gets consumed and if I return false the listener only registers ACTION_DOWN events.
How can I react on a click, but if its not a click the adapter will receive the move?
EDIT:
I'm using a lorentzos.swipecards SwipeFlingAdapterView, which uses touch-move-events. I put a layout over half of the view of the items of the adapter, which need to react on click events. But I either can't implement the click event, since I can't catch two events in a row without consuming them, or I can't have the SwipeFlingAdapterView react on the touch-move-event, since I, well, consumed it in the click event.
Don't know what sourcecode to share, since I tried many different ways and nothing works.

Related

How to stop an event when i click on another, when both events going to same activity

I have two events both are going to same activity, if i click on one event and again click on another event it shows the same action.How to resolve this
In you are using views in order to trigger those events, then after clicking on the first view which triggers the event, you can disable the second view.
You didnt upload your code so I am guessing that in the implementation of of your listeners class you are referencing the same view and ofcourse it gives the same result no matter how many events you fire.

Prevent WebView from grabbing onClickListener

I know this got asked often, but all solutions(, I found,) don't work for me.
What I have is a CardView with an OnClickListener making a Toast (#toast1).
Inside the CardView there are multiple views as also a WebView.
As mentioned elsewhere, to pass through the click through the WebView to the CardView I have done following:
Set android:clickable="false" in WebView XML
insert following under CardView.setOnClickListener(...)
WebView.setOnTouchListener( (view, event) -> true);
I also replaced the lambda with an anonymous method, to see if its just this. No change.
What happens now is:
At the border and over the other views, the clickListener is triggered and the toast appears
Over the webView the clickListener isn't triggered.
Also put a toast (#toast2) in touchLstener of WebView before returning true, and it gets triggered.
What I expect:
Click will passed through WebView
With #toast2 added: First show #toast2 then #toast1
What is a bit confusing, that in documentation of OnTouchListener, the return is following:
True if the listener has consumed the event, false otherwise.
For me that means:
true: Don't pass click to below views, as listener consumed it
false: Pass click to below views, as listener didn't consumed it
But setting to false didn't change anything.
First of all I would suggest you to get familiar with android touch handling system - you can find a really good description in this answer. To sum it up: touch event propagation starts on top level of hierarchy, but actual handling of the touch event starts on the lowest level of view hierarchy. As for solution of your problem I may suggest to sublcass the parent of your WebView and override onInterceptTouchEvent in the following way:
#Override
public boolean onInterceptTouchEvent(MotionEvent e) {
return true;
}
This will instruct this parent view to intercept all touch events that would otherwise go to its children views, thus limiting the first level of touch processing to this view.

capturing touch events without consuming them

I've got a big headache and spent a few hours to solve my problem withou any reasonable results.
I use a custom adapter (extending ArrayAdapter) to show listview items. This adapter implements OnTouchListener. There's also a background selector which color is changing when an item is touched and OnItemClickListener in ListViewActivity.
What I need is capture touch events (all of them, not only ACTION_DOWN) in the adapter. When onTouch returns false, the consecutive events (ACTION_CANCEL, ACTION_UP etc.) aren't captured. On the other hand returning true stops dispatching all other events (e.g. click) so that the ListViewActivity's onItemClick is never triggered.
I tried hard to find any working solution in SO and other resources, but with no success.
One idea was not worry about click events and background. I may set the background programatically and trigger click event the same way when the onTouch action is ACTION_UP, but view.performClick() does nothing (view is the 1st argument of onTouch method).
[EDIT]
To make it clear, I want to handle touch events in the adapter beacuse I need the textview in the item to marquee when the user touches it. Thus, in onTouch, when the action equals ACTION_DOWN, I assign true to setSelected property of the textview and, consequently, false when ACTION_CANCEL or ACTION_UP.
Any suggestions?
Thanks in advance.

what is considered `click event` in android?

in iOS world, there's a concept of touchUpInside, touch started within a view and user lifted a finger within a view bound.
I see touch vs click (event listeners) in android, and I'd like to know the difference between them.
Touch events are much more basic. There's many varieties. The most common being:
DOWN: The user touch the item
MOVE: The user shifts around the item after touching it
UP: The user stops touch the item
CANCEL: The user shifts off the item but is still touching the screen.
In Android, a click event is a composite of touch events. In the case of click it's both DOWN and UP action. There are others that can be found in a GestureDetector. Fling for example is a combination of DOWN, MOVE, and UP in a fast motion that signifies the user swiped the finger really fast.
EDIT:
Clarification on how Android handles the true and false in onTouchEvent().
It's not very well documented, but the way the Views work in Android is that when you touch a View, it will send that touch event from the parent view to all children views. Each child will then send the event to it's children. This is done in the dispatchTouchEvent() method.
When a parent View receives false from the child's onTouchEvent() method, it will no longer send touch events to that child. Meaning that when you're view returns false in onTouchEvent(), your View is really says:
I am done processing touch events and all of my children are done as well.
90% of the time, in onTouchEvent() you would do return super.onTouchEvent() to return the touch values of all the children in the View.
So let's look at your click example. Here's one way to do it in which you return false on a DOWN event, but true on an UP.
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return false;
case MotionEvent.ACTION_UP:
return true;
break;
default:
return false;
}
}
In this case, the parent of this View will receive false immediately. After which, it will stop sending touch events to this View because you said it was done.
Here's another way:
boolean mPossibleClick = false;
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mPossibleClick = true;
break;
case MotionEvent.ACTION_UP:
if(mPossibleClick) {
// UP event immediately after DOWN. Perform click action
}
default:
mPossibleClick = false;
}
return mPossibleClick;
}
It's rather crude, but basically here's what will happen. When the user first touches it, you will receive DOWN which will return true. If the user lifts the finger, it will perform a click action after which will return false because the event is done. If the user moves his finger or any other action is performed, it will return false and the click will be nulled out.
That last one is not the best way to implement a click, but I think it illustrates what I'm trying to say. In real life, move events are extremely common if even for a couple pixels.
onClickListener is used whenever a click event for any view is raised, say for example: click event for Button, ImageButton.
onTouchListener is used whenever you want to implement Touch kind of functionality, say for example if you want to get co-ordinates of screen where you touch exactly.
Definitions:
onClickListner: Interface definition for a callback to be invoked when a view is clicked.
onTouchListener: Interface definition for a callback to be invoked when a touch event is dispatched to this view. The callback will be invoked before the touch event is given to the view.
Details:
onClickListener: http://developer.android.com/reference/android/view/View.OnClickListener.html
onTouchListener: http://developer.android.com/reference/android/view/View.OnTouchListener.html
refer to the response of PH7
which one is better to use?
It really depends on your requirement.
onTouch gives you Motion Event. Thus, you can do a lot of fancy things as it help you separate state of movement. Just to name a few
ACTION_UP
ACTION_DOWN
ACTION_MOVE
Those are common actions we usually implement to get desire result such as dragging view on screen.
On the other hand, onClick doesn't give you much except which view user interacts. onClick is a complete event comprising of focusing,pressing and releasing. So, you have little control over it. One side up is it is very simple to implement.
do we need to implement both?
It is not necessary unless you want to mess up with your user. If you just want simple click event, go for onClick. If you want more than click, go for onTouch. Doing both will complicate the process.
From User point of view, it is unnoticeable if you implement onTouch carefully to look like onClick.
for more details : refer this and this

Reacting to touch events outside of a specific control

In a ListFragement I want to display additional edit options next to an item after the user long-clicks onto it.
This works fine using the following code in a custom ArrayAdapter (inside getView):
rowView.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
//Show the edit controls
View editArea = rowView.findViewById(R.id.editArea);
editArea.setVisibility(View.VISIBLE);
//Don't raise additional events for this touch
return true;
}
});
However, my problem is which event to use in order to hide those additional edit controls.
Ideally, when the edit controls are displayed, any touch outside them should be ignored in favor of hiding them (a little bit like when a dialog is opened and the user clicks somewhere besides it).
I tried overwriting dispatchTouchEvent in my MainActivity - if I generally intercept all ACTION_DOWN events, however, my edit controls are hidden before the click is dispatched to them (of course).
Is there any possibility to detect which control the user has touched without already dispatching the event?
If I intercept all ACTION_UPs, the edit-controls are removed when the user ends their long-click. And I am trying to avoid whether a specific ACTION_UP belongs to the long touch as this would produce some really messy code.
Any ideas which event to listen to?
Or do you know any better, alternate way to achieve my goal?

Categories

Resources