Bug 21177 - Using a UICollectionView in a ViewRenderer results in issues with selection.
Summary: Using a UICollectionView in a ViewRenderer results in issues with selection.
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: 1.2.3
Hardware: Macintosh Mac OS
: Normal normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2014-07-08 12:51 UTC by Geoff Armstrong
Modified: 2016-04-13 11:26 UTC (History)
13 users (show)

Tags: ac renderers
Is this bug a regression?: ---
Last known good build:

Test projects, one with the iOS CollectionView, one with it wrapped in a Xamarin Forms ViewRenderer. (61 bytes, text/plain)
2014-07-08 12:55 UTC, Geoff Armstrong

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Geoff Armstrong 2014-07-08 12:51:11 UTC
When I use Xamarin.Forms.Platform.iOS.ViewRenderer to render a UICollectionView, the ItemSelected delegate method of the UICollectionView no longer works.

I've attached two projects.

The first, TestUICollectionView, is a minimal demo that shows 25 randomly-colored rectangles. Clicking on any of them results in "Item selected." being output to the console.

The second, TestXamarinFormsUICV, is the UICollectionView from the previous project but wrapped in a Xamarin Forms ViewRenderer. This time, when you click on any of the rectangles, the console says nothing. (Just ignore the Android project.)

Ideally, when you click on the rectangles in the second project, the console should say "Item selected."

This mirrors my experience with a much more complex app I've ported to Xamarin Forms, which has had similar issues trying to get ItemSelected to work. In that project, similar things like ItemHighlighted don't work either, and attaching a special TapGestureRecognizer to each cell only works for the first cell. Subsequent cells register the gesture recognizer, but when tapped, the registered action doesn't fire.
Comment 1 Geoff Armstrong 2014-07-08 12:55:25 UTC
Created attachment 7295 [details]
Test projects, one with the iOS CollectionView, one with it wrapped in a Xamarin Forms ViewRenderer.
Comment 3 Geoff Armstrong 2014-07-14 11:34:40 UTC
Re-tested on Xamarin.Forms version
Comment 4 Eric Maupin 2014-07-17 13:45:58 UTC
Made public at the request of the reporter.
Comment 5 Geoff Armstrong 2014-07-22 11:21:04 UTC
Re-tested on Xamarin.Forms 1.2.2-pre2.
Comment 6 Rui Marinho 2014-07-24 21:01:36 UTC
Same issue here!
Comment 7 Rui Marinho 2014-07-24 21:03:03 UTC
Here's the renderer i m using that faces same issue:

Comment 8 Rajneesh Kumar 2014-08-19 09:33:55 UTC
I have checked this issue and able to reproduce with the help provided in bug description. I have run the both given attached project one by one. The first, TestUICollectionView, I observed that there are 25
randomly-colored rectangles. Clicking on any of rectangles results in "Item selected." being output to the console. The second, TestXamarinFormsUICV, I observed that there are 25randomly-colored rectangles. Clicking on any of rectangles nothing appears in XS output console.

Screencast: http://www.screencast.com/t/tUoWniqCMmWP

Environment info:

=== Xamarin Studio ===

Version 5.2.1 (build 1)
Installation UUID: 011d70a5-dede-428b-ab04-ef451c2e539d
	Mono 3.8.0 ((no/62a857e)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 308000007

=== Xamarin.Android ===

Version: 4.16.0 (Enterprise Edition)
Android SDK: /Users/MM/Desktop/android-sdk-macosx
	Supported Android versions:
		2.1   (API level 7)
		2.2   (API level 8)
		2.3   (API level 10)
		3.1   (API level 12)
		3.2   (API level 13)
		4.0   (API level 14)
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.2   (API level 17)
		4.3   (API level 18)
		4.4   (API level 19)
Java SDK: /usr
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

=== Apple Developer Tools ===

Xcode 5.1.1 (5085)
Build 5B1008

=== Xamarin.iOS ===

Version: (Enterprise Edition)
Hash: 141adb9
Build date: 2014-08-15 12:54:28-0400

=== Xamarin.Mac ===

Version: (Enterprise Edition)

=== Build Information ===

Release ID: 502010001
Git revision: d06832ce9807d6be24aca225457e8b37c7669f6f
Build date: 2014-08-07 12:10:47-04
Xamarin addins: 1de032531be4cecf2f39dbee3b87aac78204058c

=== Operating System ===

Mac OS X 10.9.2
Darwin MacMini.local 13.1.0 Darwin Kernel Version 13.1.0
    Thu Jan 16 19:40:37 PST 2014
    root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64
Comment 9 timo 2014-10-09 14:21:43 UTC
Any information when this will be fixed ?

We're facing the same issue and this is a show stopper for us.

Comment 10 Geoff Armstrong 2014-10-17 20:19:35 UTC
Here's the link to the Xamarin Forms Labs bug associated with it.

Comment 11 Geoff Armstrong 2014-11-11 15:48:42 UTC
I unfortunately cannot find even a decent workaround for this issue. Attaching a UITapGestureRecognizer to the cell can work with some simple UICollectionViews, but it doesn't work on our main collection view.

Doing a horizontal swipe does work (as long as you don't have other stuff that's using the horizontal swipe gesture, such as some kind of ScrollView) but that is not a good solution.
Comment 12 Geoff Armstrong 2015-01-30 17:32:05 UTC
Okay, I've done more testing with this. If instead of using a plain UICollectionViewCell, we use a customized UICollectionViewCell:

	public class TestCell : UICollectionViewCell {
		public TestCell(CGRect frame) : base(frame)

		public override void TouchesBegan(NSSet touches, UIEvent evt)
			base.TouchesBegan(touches, evt);
			Console.WriteLine(touches + " - " + evt);

		public override void TouchesMoved(NSSet touches, UIEvent evt)
			base.TouchesMoved(touches, evt);
			Console.WriteLine(touches + " - " + evt);

		public override void TouchesEnded(NSSet touches, UIEvent evt)
			base.TouchesEnded(touches, evt);
			Console.WriteLine(touches + " - " + evt);

		public override void TouchesCancelled(NSSet touches, UIEvent evt)
			base.TouchesCancelled(touches, evt);
			Console.WriteLine(touches + " - " + evt);

And of course, this requires you to change the registration:

				collectionView.RegisterClassForCell(typeof(TestCell), Key);

Anyway, what do we learn?

On the plain UICollectionView, all touches, even light touches, register. You have a TouchesBegan, zero to many TouchesMoved, and a TouchesEnded.

On the Xamarin Forms UICollectionView, light taps don't register at all. Heavy taps register a TouchesBegan, zero to many TouchesMoved, and a TouchesCancelled.

Wait, what?!

A TouchesCancelled!?

No wonder it's not registering taps. Something in there is canceling the touch events. And on light taps, the touch events aren't even coming through.

By the way, the behavior hasn't changed from when it was initially logged through updating to the Unified API and it persists in the latest prerelease 1.3.2pre2.

Please, this bug needs to be considered a priority.
Comment 13 Adam Kemp 2015-01-30 18:15:20 UTC
What do you mean by "light" vs. "hard" touch? There is no distinction in any iOS touch/gesture API.

UICollectionView is a UIScrollView, and as such it has a property called CanCancelContentTouches (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScrollView_Class/index.html#//apple_ref/occ/instp/UIScrollView/canCancelContentTouches). When you first touch on a subview of a scroll view the touch is delivered to the subview at first, but if you start a gesture that the scroll view wants to handle then it cancels that touch because the scroll view is handling it. The intent is if you touch on a button or table view row or something and see a highlight effect then scrolling should unhighlight and not invoke the button/row selected event.

There's also a feature (DelaysContentTouches, https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScrollView_Class/index.html#//apple_ref/occ/instp/UIScrollView/delaysContentTouches) that causes the touches began event in the subviews to be delayed a bit until the scroll view has determined that it is NOT a scroll gesture. Table views use this to avoid highlighting rows when you scroll. If you put your finger down and immediately move it then you won't get a highlight because the touch is delayed and then canceled altogether. If you put your finger down and hesitate before scrolling then the highlight appears until you move, and then the touch is cancelled and the highlight goes away. This was described in a WWDC presentation ("Advanced Scrollviews and Touch Handling Techniques", https://developer.apple.com/videos/wwdc/2014/). I would guess that the UICollectionView uses a similar approach.
Comment 14 Adam Kemp 2015-01-30 18:54:12 UTC
The problem is the tap gesture attached to each PageRenderer. In PageRenderer.ViewDidLoad there is this code:

    UITapGestureRecognizer uITapGestureRecognizer = new UITapGestureRecognizer(delegate(UITapGestureRecognizer a)
        MessagingCenter.Send<IVisualElementRenderer>(this, "Xamarin.ResignFirstResponder");
    uITapGestureRecognizer.ShouldRecognizeSimultaneously = ((UIGestureRecognizer recognizer, UIGestureRecognizer gestureRecognizer) => true);
    uITapGestureRecognizer.ShouldReceiveTouch = new UITouchEventArgs(this.OnShouldReceiveTouch);
    uITapGestureRecognizer.DelaysTouchesBegan = (uITapGestureRecognizer.DelaysTouchesEnded = false);

In order to prevent interfering with views that uses the UIResponder touch handling methods this gesture should also have CancelsTouchesInView set to false. Otherwise when the tap gesture recognizes it will cause the touch to be canceled.

To work around this I made a custom page renderer and added this code:

        public override void ViewDidLoad()

            var tapGesture = View.GestureRecognizers.OfType<UITapGestureRecognizer>().FirstOrDefault();
            if (tapGesture != null)
                tapGesture.CancelsTouchesInView = false;

With that in place the collection view ItemSelected delegate method was called.
Comment 15 Geoff Armstrong 2015-01-30 19:52:48 UTC
That works! Thank you so much, Adam! That makes things much better.
Comment 16 Jason Smith [MSFT] 2016-04-04 22:27:28 UTC
Should be fixed in 2.2.0-pre1
Comment 17 Parmendra Kumar 2016-04-11 11:56:58 UTC
I have tried to verify this issue and observed that the sample project has been removed from provided dropbox link in comment #1 as well as github url in comment #7.

Could you please reattached the sample project? so that I can verify this issue at my end.

Comment 18 Geoff Armstrong 2016-04-11 21:32:37 UTC
I was able to find the original files and put them back in my public Dropbox folder.

Try again.
Comment 19 Parmendra Kumar 2016-04-12 13:02:43 UTC
@Geoff, I have again tried to download the attached sample which is attached in comment #1 and I am still getting #404 error page.

Screencast: http://www.screencast.com/t/3DCeSpWrNv

Could you please reattached sample project? so that I can verify this issue at my end.

Comment 21 Parmendra Kumar 2016-04-13 11:26:28 UTC
Thanks @Geoff form provide me sample.

I have checked this issue with provided sample in comment #20 and Xamarin.Forms 2.2.0-pre2. now its working fine.

Hence closing this issue.