Giter Club home page Giter Club logo

xamarinformsgesture's Introduction

New version for MAUI here: https://github.com/vapolia/MauiGestures/

Below is version for Xamarin.Forms

Build status

NuGet
NuGet
Nuget

Supported Platforms

iOS, Android, UWP

Xamarin Form Gesture Effects

Add "advanced" gestures to Xamarin Forms. Available on all views. Most gesture commands include the event position.

    <Label Text="Click here" IsEnabled="True" ui:Gesture.TapCommand="{Binding OpenLinkCommand}" />

Or in code:

    var label = new Label();
    Vapolia.Lib.Ui.Gesture.SetTapCommand(label, new Command(() => { /*your code*/ }));

Quick start

Add the above nuget package to your Xamarin Forms project (only the netstandard one is enough).

In your platform projects (android,ios,uwp), before initializing xamarin forms, call Vapolia.Lib.Effects.PlatformGestureEffect.Init(); to force the discovery of this extension by the Xamarin Forms plugin engine.

The views on which the gesture is applied should have the property IsEnabled="True" and InputTransparent="False" which activates user interaction on them.

Examples

Add Gesture.TapCommand on any supported xaml view:

        <StackLayout ui:Gesture.TapCommand="{Binding OpenLinkCommand}">
            <Label Text="1.Tap this to open an url"  />
        </StackLayout>

Declare the corresponding namespace:

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             ...
             xmlns:ui="clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture"
    >

And in the viewmodel:

 public Command OpenLinkCommand => new Command(() =>
 {
     //do something
 });

Supported Gestures

  • TapCommand (ICommand)
  • DoubleTapCommand (ICommand)
  • PanCommand (ICommand)
  • LongPressCommand (ICommand)
  • TapPointCommand (ICommand or Command<Point>) where point is the absolute tap position relative to the view
  • DoubleTapPoinCommand (ICommand or Command<Point>) where point is the absolute double tap position relative to the view
  • PanPointCommand (ICommand or Command<PanEventArgs>) where point is the absolute position relative to the view
  • LongPressPointCommand (ICommand or Command<Point>) where point is the absolute tap position relative to the view
  • SwipeLeftCommand
  • SwipeRightCommand
  • SwipeTopCommand
  • SwipeBottomCommand
  • PinchCommand (Command<PinchEventArgs>) where PinchEventArg contains StartingPoints, CurrentPoints, Center, Scale, RotationRadians, RotationDegrees, Status

Properties:

  • IsPanImmediate Set to true to receive the PanCommand or PanPointCommand event on touch down, instead of after a minimum move distance. Default to false.

Examples

Somme commands in XAML

<StackLayout ui:Gesture.TapCommand="{Binding OpenCommand}" IsEnabled="True">
    <Label Text="1.Tap this text to open an url" />
</StackLayout>

<StackLayout ui:Gesture.DoubleTapPointCommand="{Binding OpenPointCommand}" IsEnabled="True">
    <Label Text="2.Double tap this text to open an url" />
</StackLayout>

<BoxView
    ui:Gesture.PanPointCommand="{Binding PanPointCommand}"
    HeightRequest="200" WidthRequest="300"
    InputTransparent="False"
    IsEnabled="True"
     />

In the viewmodel:

public ICommand OpenCommand => new Command(async () =>
{
   //...
});

public ICommand OpenPointCommand => new Command<PointEventArgs>(point =>
{
    PanX = point.X;
    PanY = point.Y;
    //...
});

public ICommand PanPointCommand => new Command<PanEventArgs>(args =>
{
    var point = args.Point;
    PanX = point.X;
    PanY = point.Y;
    //...
});

Exemple in C# on a Grid containing an horizontal slider (set value on tap)

//Tap anywhere to set value
Gesture.SetTapPointCommand(this, new Command<PointEventArgs>(pt =>
{
    var delta = (pt.X - Padding.Left) / (Width - Padding.Left - Padding.Right);
    if(delta<0 || delta>1)
        return;
    Value = (int)Math.Round((Maximum - Minimum) * delta);
}));

Limitations

Only commands are supported (PR welcome for events). No .NET events. So you must use the MVVM pattern (https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/).

Swipe commands are not supported on UWP due to a bug (event not received). If you find it, notify me! PinchCommand is not supported (yet) on UWP. PR welcome.

If your command is not receiving events, make sure that:

  • you used the correct handler. Ie: the LongPressPointCommand should be new Command<PointEventArgs>(pt => ...)
  • you set IsEnabled="True" and InputTransparent="False" on the element

UWP requires fall creator update

Breaking changes

Version 3.3.3 has breaking changes:

  • Point commands now gives a PointEventArgs instead of a Point. ie: Command<PointEventArgs>
  • Initialization namespace is unified across platforms: Vapolia.Lib.Effects.PlatformGestureEffect.Init();

Version 3.3.0 has breaking changes:

  • Command names have changed
  • PanPointCommand returns an absolute position, not a relative position anymore. It also returns the gesture state. The gesture can also be cancelled.

xamarinformsgesture's People

Contributors

djordje200179 avatar softlion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xamarinformsgesture's Issues

TapCommand2 usage with TabbedPage

I have added the TapCommand2 to a contentpage which is part of an overall tapped page, but it is not working. The code was tested on a stand alone content page and works fine, but when the page was added to a tabbed layout it did not function. Is this expected to work on a tabbed page?

Item not selecting/tap not firing on ListView

I have the left and right gestures set up on my ListView like this
xmlns:gestures="clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture"

<ListView SelectedItem="{Binding SelectedBooking}" gestures:Gesture.SwipeLeftCommand="{Binding ForwardDateCommand}" gestures:Gesture.SwipeRightCommand="{Binding BackwardDateCommand}">

I cannot tap or select an item in the ListView, my guess is that the gestures are blocking it. What am I doing wrong?
When I use InputTransparent="True" I cannot even swipe on the ListView.

PanCommand raise unhandled error at Android

Hello.

I found an issue of Pan gesture command.

I set PanCommand to a BoxView like this;

<BoxView BackgroundColor="#0C000000" gesture:Gesture.PanCommand="{Binding PanSideToolbarHandlerCommand}" InputTransparent="False"/>

When I run my app and perform pan gesture at Android device, the following error occurred;

Unhandled Exception: System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Android.Util.DisplayMetrics'. occurred

I tried to debug XamarinFormsGesture by downloading Github full source and compiling. However, All gesture defined in GitHub Demo app did not work at Android device though there were not compile error except I changed Target Framework to Android 8.0 to Android 9.0. I confirmed PlatformGestureEffect was called but OnFling method was not called never, tough I did not change your source code.

My environment -
Windows 10 Pro
Visual Studio 2019
XamarinFormsGeture version – 3.0.1
Target Framework – Android 9.0
Device OS – Android 5.0.1 and 6.0

Best regards.

Getting an error on iOS

Works fine in Droid but gettin below error in iOS.
Xamarin.Forms.Xaml.XamlParseException: Position 9:92. Type Gesture not found in xmlns clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="Test.TestPage"
    xmlns:ui="clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture">
    <StackLayout>
        <Label Text="Test Page"></Label>
        <Image Source="https://s3-us-west-1.amazonaws.com/powr/defaults/image-slider2.jpg" ui:Gesture.TapCommand2="{Binding ImageTappedCommand}"></Image>
        
    </StackLayout>
</ContentPage>

iOS 13.2

Hello,

This library not work with iOS 13.2 only tested emulator.

ScrollView not working with gestures

It seems like there are several problems with swipe gestures in a ScrollView.
On UWP I've got the problem, that swipe gestures aren't working anyway but scrolling does.
On Android (tested on Nexus 5X) scrolling isn't working anymore but swipe gestures seem to work.
iOS unfortunately currently not testable for me.

You can find a sample project in https://github.com/JohBa/XFIntro/tree/master/XFIntro/XFIntro concerned files are called ScrollViewWithSwipe.

Let me know if I can help to fix, I would like to!
Completely working, this feature would be awesome.

Update ok, sorry my bad. It surely works when I move the gesture to the stacklayout, but it is really hard to hit the swipe gesture and not trigger the scrollview. Is there anything we can do about it?!

Tap gestures not working in iOS release builds

I recently ran into an issue where the routing effect which installs the gesture recognizers was not properly resolved in iOS release builds (I only tried on iOS 12, with the build running on MacOS Mojave/XCode 10, using the latest Visual Studio 2017 for Windows and VS for Mac).

The core issue may be an over eager iOS build optimization which strips out the call to Init, resulting in the iOS assembly not being loaded and the effect failing to resolve silently.

I described the issue in more details and a possible workaround here xamarin/Xamarin.Forms#3910.

Hope this helps.

Pinch Gesture Not Working on Android

Firstly, thanks so much for an awesome library!

I'm not getting any pinch events when running the demo app.

I did some digging, and it looks like the issue is in the Android PlatformGestureEffect:

public override bool OnDown(MotionEvent? e)
{
    if (e!=null && IsPanImmediate && e.PointerCount == 1 && PanAction != null)
        return PanAction.Invoke(e, e);

    if (e != null && IsPinchImmediate && e.PointerCount == 2 && PinchAction != null)
    {
        PinchAction?.Invoke(e, e);
        return true;
    }

    return false;
}

e.PointerCount is always 1. It doesn't fire again when my second finger touches the screen. Then when you move your 2 fingers, it enters the following method in the same file:

public override bool OnScroll(MotionEvent? initialDown, MotionEvent? currentMove, float distanceX, float distanceY)
{
    if (initialDown != null)
    {
        if(initialDown.PointerCount == 1 && PanAction != null)
            return PanAction.Invoke(initialDown, currentMove);

        if (initialDown.PointerCount == 2 && PinchAction != null)
        {
            PinchAction.Invoke(initialDown, currentMove);
            return true;
        }
    }
    return false;
}

In this case initialDown.PointerCounter is always 1 (CurrentMove.PointerCounter is 2 though), so it never fires the PinchAction event.

I don't know much about Android gestures, I'm more familiar with iOS, so I couldn't quite work out how to fix that. The easy solution is to not include the initialDown point in the event or to somehow detect the first time the OnScroll method is called with 2 pointersm and then use that as the initialDown point. Neither of these feel like the right solution but that's how I'm going to try working around it for now.

Would love to get your input on this :-). Should OnDown be called twice and essentially convert a pan gesture into a pinch gesture?

link tapcommand2 to image pixel

Hi,
I linked the tapCommand2 to an image in the xaml.
<Image Source="{local:ImageResource Project.MyImage}" Aspect="AspectFill" " ui:Gesture.TapCommand2="{Binding test}"></Image>

I get the tapped position and now i am trying to get from it which image pixel it's corresponding to.
any idea how to do that?

Feature request - MinSwipeLength

Hello.

I found that min swipe length was fixed to 40 pt for Android and no definition for iOS.
Could you please add a Attached property of MinSwipeGestureLength?
I cannot do it myself because Github source does not work at my environment, but Nuget package works only.

Best regards.

Crash in Android in case of overlapping gesture

We are using swipe left and right gesture on a scrollview. The scrollview has a grid which has some children with a tap gesture. If I touch any child having a tap gesture and try to scroll the list, I get the below exception.

On debugging using the source code I found out the following:
In PlatformGestureEffect.cs there is overridden method OnFling which gets the first parameter which is MotionEvent? e1 as null. This I feel is probably due to the tap gesture on the grid already receiving the gesture request. Adding a null check in the method as shown below fixes the problem.

Possible solution:

public override bool OnFling(MotionEvent? e1, MotionEvent? e2, float velocityX, float velocityY)
            {
               if(e1 == null && e2 == null) // <----- This solved the issue
               {
                   return true;
               }
                var dx = e2.RawX - e1.RawX;
                var dy = e2.RawY - e1.RawY;
                if (Math.Abs(dx) > SwipeThresholdInPoints * Density)
                {
                    if(dx>0)
                        SwipeRightAction?.Invoke(e2);
                    else
                        SwipeLeftAction?.Invoke(e2);
                }
                else if (Math.Abs(dy) > SwipeThresholdInPoints * Density)
                {
                    if (dy > 0)
                        SwipeBottomAction?.Invoke(e2);
                    else
                        SwipeTopAction?.Invoke(e2);
                }
                return true;
            }

Exception Details:
PlatformGestureEffect+InternalGestureDetector.OnFling (Android.Views.MotionEvent e1, Android.Views.MotionEvent e2, System.Single velocityX, System.Single velocityY)
System.NullReferenceException: Object reference not set to an instance of an object.

PlatformGestureEffect+InternalGestureDetector.OnFling (Android.Views.MotionEvent e1, Android.Views.MotionEvent e2, System.Single velocityX, System.Single velocityY)
GestureDetector+SimpleOnGestureListener.n_OnFling_Landroid_view_MotionEvent_Landroid_view_MotionEvent_FF (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_e1, System.IntPtr native_e2, System.Single velocityX, System.Single velocityY)
(wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.127(intptr,intptr,intptr,intptr,single,single)

Pinch gesture doesn't work

There's no pinch gesture in this project, and using gestures in this project breaks the Xamarin.Forms pinch gesture. This issue was reported in https://stackoverflow.com/questions/52419986/when-i-add-tap-gesture-the-pinch-and-pan-does-not-work-in-xamarin-forms

It was suggested in
https://forums.xamarin.com/discussion/17767/touch-coordinates-in-tapgesturerecognizer
that this might be fixable in Android by adding

touchEventArgs.Handled = false;

to ControlOnTouch() in XamarinFormsGesture.Droid\PlatformGestureEffect.cs

How to pass CommandParameter?

I really need to pass the object in question or its position in the listview as a parameter to Command. How do I do this?

Swipe gesture not working on webview

Hello

I noticed that when you use the left or right swipe gestures on a webview, I'm unable to scroll the webview down or up.
I hope you can fix this as soon as possible

Thanks in advace

iOS: unable to parse ui:Guesture

Xamarin.Forms.Xaml.XamlParseException: Position 11:88. Type Gesture not found in xmlns clr-namespace:Vapolia.Lib.Ui;assembly=XamarinFormsGesture

<Image Source="https://s3-us-west-1.amazonaws.com/powr/defaults/image-slider2.jpg" ui:Gesture.TapCommand2="{Binding ImageTappedCommand}"></Image>

No issues on Droid.

Can you please look into it? Thanks

Long tap on ListView doesn't work when there is a Gesture attached to it.

Hello,

appreciate the effort, your gestures work very nicely.

But I have one issue, when using your gestures (swipe) on ListView, that ListView stops recognizing long tap that should popup context menu on listItem. Single taps are working, and also swipes work OK. When I remove your gestures long tap starts working again.

Is there anything I can do to make this work, or am I doing something wrong way?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.