Bug 25943 - [Android] TapGestureRecognizer does not work with a nested StackLayout
Summary: [Android] TapGestureRecognizer does not work with a nested StackLayout
Status: RESOLVED FIXED
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms (show other bugs)
Version: 2.0.0
Hardware: Macintosh Mac OS
: High major
Target Milestone: ---
Assignee: E.Z. Hart [MSFT]
URL:
: 27903 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-01-12 15:04 UTC by Valentin Polushkin
Modified: 2017-10-10 09:50 UTC (History)
28 users (show)

See Also:
Tags: android tapgesturerecognizer stacklayout
Is this bug a regression?: ---
Last known good build:


Attachments

Description Valentin Polushkin 2015-01-12 15:04:44 UTC
Tested with XF 1.3.1.6296

The following code works correctly on iOS, eg. tapping either the inner or outer StackLayout prints "foo". On Android (4.3, API 18), only the outer StackLayout prints "foo".

using Xamarin.Forms;
using System.Diagnostics;

namespace XFTesty
{
    public class App : Application
    {
        public App()
        {
            StackLayout layout = GetNestedStackLayout();

            var tapGestureRecognizer = new TapGestureRecognizer();
            tapGestureRecognizer.Tapped += (sender, e) => Debug.WriteLine("foo");
            layout.GestureRecognizers.Add(tapGestureRecognizer);

            MainPage = new ContentPage
            {
                Content = layout
            };
        }

        public StackLayout GetNestedStackLayout()
        {
            var innerLayout = new StackLayout
                {
                    HeightRequest = 100,
                    Orientation = StackOrientation.Horizontal,
                    BackgroundColor = Color.Aqua,
                    Children =
                        {
                            new Label
                            {
                                Text = "inner label",
                                FontSize = 20,
                                HorizontalOptions = LayoutOptions.Center,
                                VerticalOptions = LayoutOptions.CenterAndExpand
                            }
                        }
                    };

            var outerLayout = new StackLayout
                {
                    Orientation = StackOrientation.Vertical,
                    BackgroundColor = Color.Blue,
                    Children =
                        {
                            innerLayout,
                            new Label
                            {
                                Text = "outer label",
                                FontSize = 20,
                                HorizontalOptions = LayoutOptions.Center,
                            }
                        }
                    };

            return outerLayout;
        }
    }
}
Comment 1 Sadik Ali 2015-01-13 05:23:15 UTC
I have checked this issue and I am able to reproduce this issue at our end.

When I run the code mentioned in bug description I observed that the TapGestureRecognizer is not working with a nested StackLayout on android. I have check the same on iOS and observed that for iOS it is working fine.

Application output: https://gist.github.com/RamChBachkheti/8802aab9eae9c455d693
IDE logs: https://gist.github.com/RamChBachkheti/a25926ee0d9f96406ca6
Device logs: https://gist.github.com/RamChBachkheti/82ca51f1a84d8c458e92

Environment Info:

Xamarin.Forms: 1.3.1.0

=== Xamarin Studio ===

Version 5.7 (build 661)
Installation UUID: 6ea47b0d-1852-4aaf-808d-373ff0a5002b
Runtime:
	Mono 3.12.0 ((detached/a813491)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 312000068

=== Apple Developer Tools ===

Xcode 6.1 (6604)
Build 6A1052d

=== Xamarin.iOS ===

Version: 8.6.0.51 (Trial Edition)
Hash: dfb682f
Branch: 
Build date: 2015-01-08 13:39:32-0500

=== Xamarin.Android ===

Version: 4.20.0.28 (Trial Edition)
Android SDK: /Users/jatin66/Desktop/Backup/android-sdk-macosx
	Supported Android versions:
		1.6    (API level 4)
		2.1    (API level 7)
		2.2    (API level 8)
		2.3    (API level 10)
		3.1    (API level 12)
		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)
		4.4.87 (API level 20)
		5.0    (API level 21)
Java SDK: /usr
java version "1.7.0_65"
Java(TM) SE Runtime Environment (build 1.7.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

=== Xamarin.Mac ===

Version: 1.10.0.18 (Trial Edition)

=== Build Information ===

Release ID: 507000661
Git revision: b70bab61da996da29045ea8ee8aed1a6faedbe78
Build date: 2015-01-05 16:31:31-05
Xamarin addins: 82f6c71490562d6cd125a09287f441902fdac3d7

=== Operating System ===

Mac OS X 10.10.0
Darwin Jatin66s-iMac.local 14.0.0 Darwin Kernel Version 14.0.0
    Fri Sep 19 00:26:44 PDT 2014
    root:xnu-2782.1.97~2/RELEASE_X86_64 x86_64
Comment 2 rjcollingham 2015-05-28 07:23:24 UTC
Still seeing this issue in XF 1.4.2.6359
Comment 3 Stephane Delcroix 2015-06-15 08:22:19 UTC
*** Bug 27903 has been marked as a duplicate of this bug. ***
Comment 5 John Miller [MSFT] 2015-12-01 13:54:29 UTC
I still see a similar issue in 2.0.0. 

It seems related to the BackgroundColor being set. If the nested StackLayouts don't have a BackgroundColor, the gesture works OK.
Comment 7 John Miller [MSFT] 2016-01-25 03:49:27 UTC
Im bumping this up to 2.0 because I am still running into this with 2.0 and 2.1pre2. It's not limited to StackLayouts. It seems related more to nested layouts and background colors being set.
Comment 8 Jesse Hemstad 2016-02-09 00:14:57 UTC
FWIW, we thought we had found a workaround by setting the background color AFTER adding the gesture recognizer.  It worked in the Xamarin Android Player simulator, but when we deployed it to a device, we had the same problem.
Comment 9 Kaushal Panjwani 2016-07-22 13:56:14 UTC
Seeing this issue in XF 2.3.0 too. Strangely, if I change BackgroundColor to Transparent from White, TapGesture starts working.
Comment 10 adrianknight89 2016-09-23 11:25:12 UTC
On Android, you need to set IsInputTransparent to true if you want the outer view to handle taps. You don't need to do this on iOS.

The real question is, which platform is correct? XF doesn't seem to have a cross-platform concept of event bubbling / tunneling. By default, IsInputTransparent is false which means the inner view should block taps from reaching the outer view. In this case, I would expect iOS to behave the same.
Comment 11 adrianknight89 2016-09-23 11:27:47 UTC
I'd fix iOS instead so that foo does not print when inner layout is tapped. Developers can set IsInputTransparent to true if they like.
Comment 12 Thibault Durand 2016-10-17 06:32:10 UTC
Thank you for your enlightenment Adrian, it seems like a legitimate way to forward the touch event (better than the work-arounds). 

Native iOS views are input-transparent by default, if a view does not handle the touch event, the touch event is forwarded to its parent and so forth until it is handled. 
So todays behaviour is consistent with the Native iOS platform, but unfortunately not with the Android Xamarin.Forms platform. 
I thought the InputTransparent concept came from Android but after browsing the docs I can't find anything like that. Does it come from Windows Phone then? 
The iOS behaviour seems more logical to me, that the event is forwarded rather that you having to remember to set InputTransparent on every child your create. 

But either way, it does not seem likely that this will be normalized because it's potentially a huge breaking change.
Comment 13 stephen.machwirth 2016-11-15 10:40:13 UTC
IsInputTransparent is a property which doesn't exist. Still facing the issue that tapgesturerecognizer doesn't work.
Comment 14 Philipp Sumi 2017-01-25 00:19:35 UTC
Android, XF 2.3.4-pre1: Taps are also not registered if:

- outer layout is inputtransparent with background color
- nested layout has backgroundcolor

once the background is removed from the inner layout, the tap fires.


(I'm seeing this was reported _two_ years ago??)
Comment 15 Brian Erickson 2017-02-21 16:07:19 UTC
This XAML doesn't work on Android either.  Works on UWP and Winphone 8.1.  Can't test on IOS.

   <ScrollView x:Name="outerSV" InputTransparent="true">
      <ScrollView.GestureRecognizers>
         <TapGestureRecognizer Tapped="btnNextClick" />
      </ScrollView.GestureRecognizers>
      
      <StackLayout Orientation="Vertical">
         <Label x:Name="PrayerTitle" FontSize="20"></Label>
         <StackLayout Orientation="Vertical" Margin="20,0,0,0">
            <Label x:Name="PrayerTextBold" FontAttributes="Bold" FontSize="18"></Label>
            <Label x:Name="PrayerText" FontSize="18"></Label>
         </StackLayout>
         <Button x:Name="btnNext" Text="Next" Clicked="btnNextClick"/>
      </StackLayout>
   </ScrollView>
Comment 16 Brian Erickson 2017-02-21 19:33:56 UTC
Doesn't matter if InputTransparent is set or not...
Comment 17 fgiacomelli 2017-03-23 08:17:27 UTC
Same problem for me using Xamarin Forms 2.3.3.180, if I create a control that contains grids and I set their BackgroundColor tapgesturerecognizers doesn't work properly, sometime they are raised and sometime don't.
Comment 18 ryan.sapp 2017-04-23 21:12:26 UTC
I am seeing the exact same issue and is a huge problem for us.  Please let us know when a solution will be proposed.
Comment 19 Philipp Sumi 2017-04-26 10:40:10 UTC
Suffering now from the reverse issue as described by Adrian. I am having an overlay dialog (think gallery image), and tapping outside the dialog closes the dialog. The tap is accordingly registered to the dialog's parent:

<Grid Background="TintColor"
      TapCommand="OnTapped">
  <MyAlert Margin="BigMargin" />
<Grid>

On Android, tapping on the dialog itself doesn't do anything (unless I tap on a dialog button). On iOS, since the dialog is InputTransparent, this is the same as tapping the surrounding grid. This really should be aligned in both platforms.
Comment 20 vinnie1991 2017-06-08 06:04:43 UTC
Is there any ETA when I can expect the fix?
This is one of the most important bugs for me.

Thanks :)
Comment 21 ryan.sapp 2017-06-08 13:11:19 UTC
I second Vincent's motion for an ETA, this bug completely broke one of my input controls that is used repeatedly and often.
Comment 22 Samantha Houts [MSFT] 2017-06-08 17:45:43 UTC
https://github.com/xamarin/Xamarin.Forms/pull/935
Comment 23 Rui Marinho 2017-06-20 15:43:24 UTC
Should be fixed on 2.3.6-pre1
Comment 24 ryan.sapp 2017-08-16 17:20:58 UTC
Is there a timeline for when 2.3.6-pre1 with be available as a Git Package ?  As of now it does not show any 2.3.6 pre-releases, only up to 2.3.5.x
Comment 25 Samantha Houts [MSFT] 2017-08-16 23:42:52 UTC
We've actually jumped right over 2.3.6 and landed 2.4.0-pre1 today! This fix should be included in that build. Thank you!
Comment 26 post4me3 2017-08-24 10:11:45 UTC
No, its not fixed in 2.4.0.266-pre1. As an example from Comment 15 above , this code fragment doesnt work  :

 <ScrollView x:Name="outerSV" InputTransparent="true">
      <ScrollView.GestureRecognizers>
         <TapGestureRecognizer Tapped="btnNextClick" />
      </ScrollView.GestureRecognizers>
      
      <StackLayout Orientation="Vertical">
         <Label x:Name="PrayerTitle" FontSize="20"></Label>
         <StackLayout Orientation="Vertical" Margin="20,0,0,0">
            <Label x:Name="PrayerTextBold" FontAttributes="Bold" FontSize="18"></Label>
            <Label x:Name="PrayerText" FontSize="18"></Label>
         </StackLayout>
         <Button x:Name="btnNext" Text="Next" Clicked="btnNextClick"/>
      </StackLayout>
   </ScrollView>

i.e it is not possible to wrap content inside a scrollview and also allow the scrollview to be clickable via Tapped Gesture Recognizer (btnNextClick cannot be reached/activated)

Even reducing the code fragment to its simplest form and just having a single content inside a scrollview (No nested parent containers) still doesnt allow the events to be raised :

        <ScrollView
                    HeightRequest="200"
                    BackgroundColor="Red"
                    HorizontalOptions="FillAndExpand"
                    VerticalOptions="FillAndExpand">
                    <Label
                        HorizontalOptions="CenterAndExpand"
                        HorizontalTextAlignment="Center"
                        LineBreakMode="WordWrap"
                        Text="Some long text ...."
                    </Label>
 VerticalOptions="CenterAndExpand" />
                    <ScrollView.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped"></TapGestureRecognizer>
                    </ScrollView.GestureRecognizers>
                </ScrollView>



Or setting InputTransparent on the ScrollView to allow its container to get a chance to process the event doesnt work either :

<StackLayout>
    <StackLayout.GestureRecognizers>
        <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped"></TapGestureRecognizer>
    </StackLayout.GestureRecognizers>
        <ScrollView
                    InputTransparent="True"
                    HeightRequest="200"
                    BackgroundColor="Red"
                    HorizontalOptions="FillAndExpand"
                    VerticalOptions="FillAndExpand">
                    <Label
                        InputTransparent="True"
                        HorizontalOptions="CenterAndExpand"
                        HorizontalTextAlignment="Center"
                        LineBreakMode="WordWrap"
                        Text="Some long text ...."
                    </Label>
 VerticalOptions="CenterAndExpand" />
                    <ScrollView.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped"></TapGestureRecognizer>
                    </ScrollView.GestureRecognizers>
                </ScrollView>

</StackLayout>

So it would appear that the issue raised over two years ago remains unresolved.
Comment 27 ebourque 2017-08-29 09:01:16 UTC
Not working on UWP or IOS either. Really hope you guys get this working soon. If I understand correctly the only alternative right now is to turn the scrollview into several pages?

May I also suggest that you add a better way to locate which items are being rendered in the scroll view?

Imagine a scrollview being used to show many images and text, it is required that only images that are in the visible area of the scroll view should be loaded. Kinda like a OnAppearing / OnDisappearing for items inside the ScrollView.

Thanks
Comment 28 E.Z. Hart [MSFT] 2017-09-05 20:27:09 UTC
Looks like we fixed the original issue (StackLayout inside a StackLayout) but the issue raised in https://bugzilla.xamarin.com/show_bug.cgi?id=25943#c15 (StackLayout in ScrollView) may not be working on all platforms. Need to confirm and get whip up a repro project.
Comment 29 post4me3 2017-10-04 09:50:51 UTC
We have just updated our app with respect to XF 2.4.0.282 and it seems that this version has major regresssion bugs with respect to Tap Gesture support , especially in Android.

Previously, this bugzilla bug 25943 was raised because GR did not seem to get activated within a nested container hierarchy . Now with the release of XF 2.4.0.282, it would appear that ALL GR inside android do not work seamlessly.

The exact issues we are seeing is that now our current codebase requires MULTIPLE TAPS on controls that have GR's attached. All GR's are XAML based.

We have GR's on :

- Images
- Labels
- Grids
- StackLayouts 

etc


You cannot LITERALLY take your finger and TAP on a component - the GR on the control is not activated. You have to do a SOFT TOUCH (Place your finger on the control and gently press the control) in order for the GR to be recognized - this is broken and was working at least for this use case in 2.3.4.267.

Android Support libraries in use = v25.3.1

Note - you need to test GR support (or lack off)  on a LIVE device not with a mouse via a simulator in order to see the issue.
Comment 30 Paul DiPietro [MSFT] 2017-10-04 14:57:37 UTC
*** Bug 59961 has been marked as a duplicate of this bug. ***
Comment 31 E.Z. Hart [MSFT] 2017-10-04 21:07:35 UTC
(In reply to post4me3 from comment #29)
> Android Support libraries in use = v25.3.1
> 
> Note - you need to test GR support (or lack off)  on a LIVE device not with
> a mouse via a simulator in order to see the issue.

I'm testing this scenario on a Nexus 6 (using the repro project from https://bugzilla.xamarin.com/show_bug.cgi?id=59961 and updating it to the v25.3.1 support libraries) and so far everything seems to work fine. What physical device models are you testing on? Does the repro for 59961 seem like a reasonable representation of what's not working in your project? If not, what details might we be missing?
Comment 32 E.Z. Hart [MSFT] 2017-10-06 16:30:19 UTC
Setting this back to resolved; the original issue with tap gestures in nested stack layouts has been fixed.

For the problems mentioned in comment 29 and onward, please refer to https://bugzilla.xamarin.com/show_bug.cgi?id=59961.
Comment 33 ebourque 2017-10-10 09:50:28 UTC
Have you confirmed that TapGestureRecognizer in a stacklayout nested in a scrollview does not work?

Do you have a workaround for this?

Note You need to log in before you can comment on or make changes to this bug.