Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding long press gesture recognizer in Xamarin forms

Could you please let me know how can I recognize long press gesture in Xamarin Forms application?

This is my xaml page which i created referring to this thread: Xamarin.forms.DataGrid

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataGridSample_01"
xmlns:dg="clr-namespace:Xamarin.Forms.DataGrid;assembly=Xamarin.Forms.DataGrid"
x:Class="DataGridSample_01.MainPage">

 <ContentView BackgroundColor="White" Padding="20" >
  <dg:DataGrid ItemsSource="{Binding Data}" SelectionEnabled="True" RowHeight="70" HeaderHeight="50" BorderColor="#CCCCCC" HeaderBackground="#E0E6F8" ActiveRowColor="#8899AA">
     <dg:DataGrid.Columns>
     <dg:DataGridColumn Title="Logo" PropertyName="Logo" Width="50" SortingEnabled="False">
        <dg:DataGridColumn.CellTemplate>
           <DataTemplate>
              <Image Source="{Binding}" HorizontalOptions="Center" VerticalOptions="Center" Aspect="AspectFit" HeightRequest="60" />
           </DataTemplate>
        </dg:DataGridColumn.CellTemplate>
     </dg:DataGridColumn>
     <dg:DataGridColumn Title="Team" PropertyName="Name" Width="2*" >
     </dg:DataGridColumn>
     <dg:DataGridColumn Title="Win" PropertyName="Win" Width="2*">
        <dg:DataGridColumn.CellTemplate>
           <DataTemplate>
              <Picker x:Name="Fruits" Title="Fruits" HorizontalOptions="FillAndExpand">
                 <Picker.Items>
                    <x:String>Apple</x:String>
                    <x:String>Mango</x:String>
                    <x:String>PineApple</x:String>
                    <x:String>Orange</x:String>
                 </Picker.Items>
              </Picker>
           </DataTemplate>
        </dg:DataGridColumn.CellTemplate>
     </dg:DataGridColumn>
     <dg:DataGridColumn Title="Loose" PropertyName="Loose"  Width="1*">                    
     </dg:DataGridColumn>
     <dg:DataGridColumn PropertyName="Home">
        <dg:DataGridColumn.FormattedTitle>
           <FormattedString>
              <Span Text="Home" ForegroundColor="Black" FontSize="13" FontAttributes="Bold"/>
              <Span Text=" (win-loose)" ForegroundColor="#333333" FontSize="11" />
           </FormattedString>
        </dg:DataGridColumn.FormattedTitle>
     </dg:DataGridColumn>
     <dg:DataGrid.RowsBackgroundColorPalette>
        <dg:PaletteCollection>
           <Color>#FFFFFF</Color>
        </dg:PaletteCollection>
     </dg:DataGrid.RowsBackgroundColorPalette>
  </dg:DataGrid>
 </ContentView>
</ContentPage>

I want to add a Long Press Gesture recognizer on Image Control.I tried to do it referring to this StackOverflow Thread.But it doesn't seem to work.

I am very new to this. Any help is very much appreciated.

like image 594
Mars Avatar asked Dec 12 '18 07:12

Mars


People also ask

How to use tap gesture recognizer Xamarin forms?

The tap gesture is used for tap detection and is implemented with the TapGestureRecognizer class. var tapGestureRecognizer = new TapGestureRecognizer(); tapGestureRecognizer. Tapped += (s, e) => { // handle the tap }; image. GestureRecognizers.

How do I use xamarin community toolkit?

The toolkit is available as a NuGet package that can be added to any existing or new project using Visual Studio. Open an existing project, or create a new project using the Blank Forms App template. In the Solution Explorer panel, right click on your project name and select Manage NuGet Packages. Search for Xamarin.


2 Answers

It is no longer required to define your own effect, since TouchEffect already exists in Xamarin Community Toolkit package (which is a package that gathers a lot of cool reusable/common controls, effects, behaviors, converters...).

xaml namespace:

 xmlns:xct="http://xamarin.com/schemas/2020/toolkit"

Sample of usage

You can set a duration of the long press required to trigger the command, or leave it by default = 500ms. In this example LongPressCommand will be fired/triggered after 2 seconds.

<Image Source="{Binding}" HorizontalOptions="Center" VerticalOptions="Center"
       Aspect="AspectFit" HeightRequest="60"
       xct:TouchEffect.LongPressCommand="{Binding LongPressCommand}"
       xct:TouchEffect.LongPressDuration="2000"/>
ICommand LongPressCommand = new Command(() =>
            {
                LongPressCount++;
                OnPropertyChanged(nameof(LongPressCount));
            });

Also, the same as CommandParameter you have an optional LongPressCommandParameter, where you can bind a custom parameter to your command.

Resource

Documentation (under work) https://learn.microsoft.com/en-us/xamarin/community-toolkit/

Repo https://github.com/xamarin/XamarinCommunityToolkit/

https://www.youtube.com/watch?v=BcFlZMhPmVk

like image 68
Cfun Avatar answered Oct 26 '22 01:10

Cfun


You can use Effect to add LongPressGestureRecognizer to any control.

in Forms ,creat a new shared Effect.

using System;
using System.Windows.Input;
using Xamarin.Forms;

namespace App15
{
  public class LongPressedEffect : RoutingEffect
  {
    public LongPressedEffect() : base("MyApp.LongPressedEffect")
    {

    }

    public static readonly BindableProperty CommandProperty = BindableProperty.CreateAttached("Command", typeof(ICommand), typeof(LongPressedEffect), (object)null);
    public static ICommand GetCommand(BindableObject view)
    {

        //do something you want 
        Console.WriteLine("long press Gesture recognizer has been striked");


        return (ICommand)view.GetValue(CommandProperty);
    }

    public static void SetCommand(BindableObject view, ICommand value)
    {
        view.SetValue(CommandProperty, value);

    }


    public static readonly BindableProperty CommandParameterProperty = BindableProperty.CreateAttached("CommandParameter", typeof(object), typeof(LongPressedEffect), (object)null);
    public static object GetCommandParameter(BindableObject view)
    {

        return view.GetValue(CommandParameterProperty);
    }

    public static void SetCommandParameter(BindableObject view, object value)
    {
        view.SetValue(CommandParameterProperty, value);
    }
  }
}

in Android Project

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

using App15;
using App15.Droid;    

[assembly: ResolutionGroupName("MyApp")]
[assembly: ExportEffect(typeof(AndroidLongPressedEffect), "LongPressedEffect")]
namespace AndroidAppNamespace.Effects
{

  public class AndroidLongPressedEffect : PlatformEffect
  {
    private bool _attached;

    public static void Initialize() { }

    public AndroidLongPressedEffect()
    {
    }

    protected override void OnAttached()
    {
        //because an effect can be detached immediately after attached (happens in listview), only attach the handler one time.
        if (!_attached)
        {
            if (Control != null)
            {
                Control.LongClickable = true;
                Control.LongClick += Control_LongClick;
            }
            else
            {
                Container.LongClickable = true;
                Container.LongClick += Control_LongClick;
            }
            _attached = true;
        }
    }


    // Invoke the command if there is one
    private void Control_LongClick(object sender, Android.Views.View.LongClickEventArgs e)
    {
        Console.WriteLine("Invoking long click command");
        var command = LongPressedEffect.GetCommand(Element);
        command?.Execute(LongPressedEffect.GetCommandParameter(Element));
    }


    protected override void OnDetached()
    {
        if (_attached)
        {
            if (Control != null)
            {
                Control.LongClickable = true;
                Control.LongClick -= Control_LongClick;
            }
            else
            {
                Container.LongClickable = true;
                Container.LongClick -= Control_LongClick;
            }
            _attached = false;
        }
    }
}

in iOS Project

using Foundation;
using UIKit;
using App15;
using App15.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ResolutionGroupName("MyApp")]
[assembly: ExportEffect(typeof(iOSLongPressedEffect), "LongPressedEffect")]
namespace App15.iOS
{
  public class iOSLongPressedEffect : PlatformEffect
  {
    private bool _attached;
    private readonly UILongPressGestureRecognizer _longPressRecognizer;

    public iOSLongPressedEffect()
    {
        _longPressRecognizer = new UILongPressGestureRecognizer(HandleLongClick);
    }


    protected override void OnAttached()
    {
        //because an effect can be detached immediately after attached (happens in listview), only attach the handler one time
        if (!_attached)
        {
            Container.AddGestureRecognizer(_longPressRecognizer);
            _attached = true;
        }
    }


    // Invoke the command if there is one       
    private void HandleLongClick(UILongPressGestureRecognizer sender)
    {
        if(sender.State==UIGestureRecognizerState.Began)
        {
            var command = LongPressedEffect.GetCommand(Element);
            command?.Execute(LongPressedEffect.GetCommandParameter(Element));
        }


    }

    protected override void OnDetached()
    {
        if (_attached)
        {
            Container.RemoveGestureRecognizer(_longPressRecognizer);
            _attached = false;
        }
    }

  }
}

Now,you can add LongPressGestureRecognizer to controls.Such as Label or Image.

<Label Text="Long Press Me!" local:LongPressedEffect.Command="{Binding ShowAlertCommand}" local:LongPressedEffect.CommandParameter="{Binding .}">
  <Label.Effects>
      <local:LongPressedEffect />
  </Label.Effects>
</Label>

<Image Source="{Binding}" local:LongPressedEffect.Command="{Binding ShowAlertCommand}" local:LongPressedEffect.CommandParameter="{Binding .}">
   <Image.Effects>
        <local:LongPressedEffect />
   </Image.Effects>
</Image>

For more detail about Effect you can refer here

like image 32
Lucas Zhang Avatar answered Oct 26 '22 01:10

Lucas Zhang