xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.62k stars 1.87k forks source link

[Bug] CollectionView not properly capturing Touch actions on Android #7159

Open josephlbailey opened 5 years ago

josephlbailey commented 5 years ago

Description

I've implemented an effect to capture touch events on a CollectionView, however, the MotionEvent ACTION_DOWN doesn't seem to be captured on Android. The MotionEvent ACTION_MOVE is properly being captured. I've tested this effect on other views with no issues. I've followed this link for creating the effect.

Steps to Reproduce

Touch down on CollectionView, without sliding.

Expected Behavior

Should fire the view's Touch event

Actual Behavior

Touch event is not fired on ACTION_DOWN

Basic Information

Reproduction Link

CollectionViewTouchBug.zip

PureWeen commented 5 years ago

When I ran your sample out of the box it was giving me exceptions so I just removed everything from the switch statement and it looks like it's hitting the Down part of the case for me

image

josephlbailey commented 5 years ago

So, you're correct that it does fire sometimes, however, it seems like it will only fire if you touch, drag and release first. I tested this on two separate physical devices and an emulator and each time it would fire after the Move MotionEvent had previously fired. To test this theory I went ahead and placed a BoxView above the CollectionView and applied the exact same effect to the BoxView. The Down event fires every single time, without the need for a Move first. Here's the updated project if you'd like to see what I mean. I log out the events as they fire to application output, and if you will only touch/click (no drag/move) first you'll see that the Down doesn't fire.

PureWeen commented 5 years ago

@josephlbailey I don't think this is specifically a CollectionView issue. I pulled down a RecyclerView sample here https://github.com/googlesamples/android-RecyclerView/ and if I add a touch listener to the RecyclerView it acts exactly the same. The reason is that the Viewholders in that samle also have touch listeners assigned which is also what our stacklayouts and such have assigned

I tested this with a ListView control and the result is exactly the same. In a perfect world you'd be able to use a GestureRecognizer

<CollectionView.GestureRecognizers>
                <TapGestureRecognizer NumberOfTapsRequired="1" Tapped="OnClicked"></TapGestureRecognizer>
            </CollectionView.GestureRecognizers>

Which is where I would say the bug lies. As far as what to do to make it work for your scenario and effects? I can't really say but my guess is that it'll be a little tricky. I think you would need to use a custom renderer for the CollectionView and override DispatchTouch or attach them to the parent layout inside CollectionView?

josephlbailey commented 5 years ago

Ah ok. Well, I guess that's just the way it goes sometimes. I had implemented this so I could capture the touch release on the collection view because I have a search entry that floats on top and auto-hides/shows on scroll down/up based on the vertical delta. I was going to check the position of the entry control when touch is released and finish hiding it if it was more than halfway hidden, or pop it back open otherwise. It ended up working quite well on iOS, but Android was the stubborn one. Thanks for checking in to this for me @PureWeen, much appreciated. I'll play around with some other options to see if I can get it to work.

PureWeen commented 5 years ago

yea :-/ it's a pretty funny result. After you just swipe around randomly then all the touch commands start working

It feels like the RecyclerView is waiting for some initial type of swipe or scroll event, at which point it attaches a TouchListener that is then able to bubble the touch events up 🤷‍♂