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

[Android] Adding both TapGestureRecognizer and ContextActions to ViewCell will result in ContextActions not responding #1932

Open ammarMheir opened 6 years ago

ammarMheir commented 6 years ago

Description

When working with ViewCells, adding ContextAction by itself will result in a successful build and expected functionality. However when both a TapGestureRecognizer and ContextActions is set on the same ViewCell, only the TapGestureRecognizer will respond and ContextActions no longer work.

A previous bug has been reported but apparently resolved:

https://bugzilla.xamarin.com/show_bug.cgi?id=46363

Steps to Reproduce

  1. Create a ViewCell with TapGestureRecognizer and ContextAction as so:

The following is a simple example that demonstrates the issue:

public class TableViewCellIssuePage : ContentPage
    {
        #region Constructors
        public TableViewCellIssuePage()
        {
           TapGestureRecognizer tap = new TapGestureRecognizer();
            ViewCell viewCell = new ViewCell()
            {
                View = new Label() { Text = "Cell" }
            };

            viewCell.ContextActions.Add(new MenuItem() { Text = "Never Shows" });

            // If you remove this gesture recognizer then the context action will work.
            viewCell.View.GestureRecognizers.Add(tap);

            this.Content = new StackLayout()
            {
                Children =
                {
                    new TableView()
                    {
                        Root = new TableRoot()
                        {
                            new TableSection()
                            {
                                viewCell
                            }
                        }
                    }
                }
            };
        }
        #endregion
    }
  1. Build and deploy application to Android or iOS Emulator
  2. Notice how long press does no respond while TapGestureRecognizer is. See commented code above to remove GestureRecognizer to have ContextActions work again.

Expected Behavior

Both TapGestureRecognizer and ContextActions should respond when both being added to a single ViewCell.

Actual Behavior

ContextActions do not respond when adding a TapGestureRecognizer to the same ViewCell.

Basic Information

Microsoft Visual Studio Enterprise 2017 Version 15.5.4 VisualStudio.15.Release/15.5.4+27130.2024 Microsoft .NET Framework Version 4.7.02556

Installed Version: Enterprise

Xamarin 4.8.0.757 (7f9ec2a) Xamarin.Android SDK 8.1.3.0 (HEAD/ef47226b7) Xamarin.iOS and Xamarin.Mac SDK 11.6.1.2 (6857dfc)

NUGET: Xamarin.Forms - 2.5.0.280555

hartez commented 6 years ago

@ammarMheir Are you seeing this behavior on both iOS and Android?

PureWeen commented 6 years ago
public Page CreateDefaultMainPage()
        {
            TapGestureRecognizer tap = new TapGestureRecognizer();

            tap.Command = new Command(() =>
            {

            });

            ViewCell viewCell = new ViewCell()
            {
                View = new Label() { Text = "Cell" }
            };

            viewCell.ContextActions.Add(new MenuItem() { Text = "Never Shows" });

            // If you remove this gesture recognizer then the context action will work.
            viewCell.View.GestureRecognizers.Add(tap);

            return new ContentPage()
            {
                Content = 
                    new StackLayout()
                    {
                        Margin = new Thickness(0,100,0,0),
                        Children =
                        {
                            new TableView()
                            {
                                Root = new TableRoot()
                                {
                                    new TableSection()
                                    {
                                        viewCell
                                    }
                                }
                            }
                        }
                    }
            };
        }
bentmar commented 6 years ago

also ItemTapped doesnt work when doing this: https://github.com/xamarin/Xamarin.Forms/issues/2026

acaliaro commented 6 years ago

there are some news? it exists in 3.1.0-469394-pre1

jonkas2211 commented 6 years ago

Does anybody has found an workaround or has a idea for one?

ianjonesau commented 6 years ago

Xam.Forms v3.1.0697729 has same issue. A quick work-around on Droid is to put an image on right hand side of cell and attach TapGestureRecogniser that triggers same logic as normal cell tap.

15mgm15 commented 6 years ago

@jonkas2211 Did you found a solution?

15mgm15 commented 6 years ago

Adding a GestureRecognizer to the ViewCell worked as a workaround for now.

jonkas2211 commented 6 years ago

No @15mgm15, I didnt find a solution

fernandovm commented 5 years ago

There are some news? This problem is more than two years old (https://bugzilla.xamarin.com/show_bug.cgi?id=46363). It has gone and back several times, version after version. :((

@15mgm15, the ViwCell does not accpet gestures, right? I have tried to find a workaround, but still unsuccessful. :((

mfeingol commented 5 years ago

A workaround I found for this on Android was to override StartSupportActionMode and OnSupportActionModeFinished on my main activity, and use those calls to set a global flag that allows the tap handler to know to ignore the single click event because the context menu is being displayed.

It's kind of horrible, but it does work for my scenario: I'm able to cleanly handle both the long press from context actions and the tap from the gesture recognizer.

mfeingol commented 5 years ago

This is still an issue in 4.0.0.482894.

fatderda commented 4 years ago

Still an issue in 4.4.0.991640

samhouts commented 4 years ago

This issue doesn't seem to have had any activity in a long time. We're working on prioritizing issues and resolving them as quickly as we can. To help us get through the list, we would appreciate an update from you to let us know if this is still affecting you on the latest version of Xamarin.Forms, since it's possible that we may have resolved this as part of another related or duplicate issue. If we don't see any new activity on this issue in the next 30 days, we'll evaluate whether this issue should be closed. Thank you!

mfeingol commented 4 years ago

This is still an issue with Xamarin Forms 4.8.0.1269.

It is exacerbated by https://github.com/xamarin/Xamarin.Forms/issues/7642, which requires a GestureRecognizer in order for long-press to work at all.

The best workaround for all this is to implement IOnLongClickListener.OnLongClick on a ButtonRenderer, and then call MainActivity.Activity.StartActionMode and manually add IMenuItem instances to the IMenu provided in the ActionMode callback.

This of course requires a lot of Android-specific code. Ideally there would be Xamarin Forms-native ways to make all this work.

boris-df commented 3 years ago

My problem with this seems to be a little bit different: I have the problem, that the Action-Action shows up AND the Tap Gesture is triggered (on Android only; because on iOS it's a swipe to show the context action)

I have a ListView using my custom ViewCell. The ViewCell:

Now on Android, if i Tap&Hold => the Context menu item shows up If i lift my finger, the Tap event is fired :)

so - both working - fine - so maybe a valid workaround for you (to put the GestureRecognizer on a StackLayout inside the ViewCell instead of directly to the ViewCell.View)

BUT: How would i know that the Context-Menu is shown so that i can disable or ignore the Tap Gesture? Ideas?

andreiionita commented 3 years ago

I'm seeing the same behavior as described by @boris-df

boris-df commented 3 years ago

My current workaround:

In the Xamarin.Forms Code i've added an Interface: public interface IContextManager { bool IsContextMenuVisible { get; } }

In the ViewModel, where i have the Tap-Command of the ListView-Item, i check this bool to ignore the Tap (that occurs on Android after an Tap-and-hold to show the context item): if (Device.RuntimePlatform == Device.Android) { if (DependencyService.Get<MyServices.IContextManager>().IsContextMenuVisible) return; }

In the Android-Project i have this to access this Interface: `[assembly: Xamarin.Forms.Dependency(typeof(ContextManager))] namespace my.namespace { public class ContextManager : IContextManager { public static Android.Support.V7.View.ActionMode LastActionMode { get; set; }

    public bool IsContextMenuVisible
    {
        get
        {
            return LastActionMode != null;
        }
    }
}

} `

and finally: In the Android-Project "MainActivity.cs" add this to set the property: ` public override Android.Support.V7.View.ActionMode StartSupportActionMode(Android.Support.V7.View.ActionMode.ICallback callback) { return Services.ContextManager.LastActionMode = base.StartSupportActionMode(callback); }

    public override void OnSupportActionModeFinished(Android.Support.V7.View.ActionMode mode)
    {
        Services.ContextManager.LastActionMode = null;
        base.OnSupportActionModeFinished(mode);
    }

`

andreiionita commented 3 years ago

@boris-df Thank you for the workaround!

mfeingol commented 3 years ago

@boris-df: I'm using the same workaround, fwiw.