MR.Gestures handles ALL touch gestures

MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭
edited February 2015 in Xamarin.Forms

With MR.Gestures you can handle the Tapping, Tapped, DoupleTapped, LongPressing, LongPressed, Panning, Panned, Swiped, Pinching, Pinched, Rotating and Rotated gestures on all layouts, cells, views and on the ContentPage.

The code can be as easy as

    var box1 = new MR.Gestures.BoxView { Color = Color.Red };
    box1.LongPressed += (s, e) => { Console.WriteLine("Code: Red LongPressed"); };

Or in XAML

<br /><mr:ContentView xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mr="clr-namespace:MR.Gestures;assembly=MR.Gestures"
             x:Class="GestureSample.Views.ContentViewXaml"

             Padding="50"

             TappingCommand="{Binding TappingCommand}"
             TappedCommand="{Binding TappedCommand}"
             DoubleTappedCommand="{Binding DoubleTappedCommand}"
             LongPressingCommand="{Binding LongPressingCommand}"
             LongPressedCommand="{Binding LongPressedCommand}"
             PanningCommand="{Binding PanningCommand}"
             PannedCommand="{Binding PannedCommand}"
             SwipedCommand="{Binding SwipedCommand}"
             PinchingCommand="{Binding PinchingCommand}"
             PinchedCommand="{Binding PinchedCommand}"
             RotatingCommand="{Binding RotatingCommand}"
             RotatedCommand="{Binding RotatedCommand}"
             >

MR.Gestures is available via NuGet. More info on http://www.mrgestures.com/.

There is also a sample app available to download from https://github.com/MichaelRumpler/GestureSample. The GestureSample demonstrates how to use all the gestures with all Xamarin.Forms elements.

Best Answer

«13456710

Posts

  • Will never Xamarin provide these events in Xamarin.Forms controls itself?, or do we need to go with MR.Gestures libraries in future also?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    I cannot answer for Xamarin here. But they provided the TapGestureRecognizer in the very first Xamarin.Forms version in June 2014 and nothing else in the last eight months. They not even revealed plans to do so.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭
    edited February 2015

    I've been asked if MR.Gestures can handle Swipe within a TabbedPage within a MasterDetailPage. This is not so easy because the swipe is also used by the MasterDetailPage on iOS and Android and the TabbedPage on Windows Phone.

    So I copied the MasterDetailPageDemoPage, TabbedPageDemoPage and NamedColorPage from the Xamarin FormsGallery and adjusted them so that the MasterDetailPage now shows the TabbedPage as Detail. Then I added my gesture handling.

    The NamedColorPage inherits from MR.Gestures.ContentPage. As the swipe needs to be handled by the MasterDetailPage it must not handle the Panning, Panned or Swiped gestures. If you do that, then you cannot swipe to the Master page anymore on iOS. All other gestures can be handled by the NamedColorPage as usual.

    I also changed the BoxView within the NamedColorPage to a MR.Gestures.BoxView. This element can handle all gestures without problems. If you swipe within that BoxView, it will be recognized. If you swipe outside from the border on iOS and Android, you can go back to the Master page.

    On Windows Phone, the swipe will be used by the TabbedPage to switch tabs. This will still happen no matter where you swipe. But the BoxView will also be notified in the Swiped handler.

    I committed the new sample to https://github.com/MichaelRumpler/GestureSample.

    If you have any other special cases, you can always clone GestureSample and change it yourself to try it out. The license key for the GestureSample app is included so it will work like a full version.

  • rgreenrgreen CAMember
    edited February 2015

    var box1 = new MR.Gestures.BoxView { Color = Color.Red };
    box1.LongPressed += (s, e) => { Console.WriteLine("Code: Red LongPressed");};

    Nice and simple, worked right off in Android using Version 1.0.4 NuGet.
    iOS didn't respond at all. Is there one extra bit of info I need to get it to function in iOS, like licensing? I didn't use the LicenseKey for my Droid app.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    LongPressed should work without LicenseKey, but if you don't call anything from the dll, the linker thinks you don't need it and throws it away. So you should add

    MR.Gestures.iOS.Settings.LicenseKey = "";
    

    This will include the library, but the properties of the EventArgs will be empty.
    If you only need LongPressed, this should suffice. If you need swipe, pan, pinch or rotate, empty EventArgs will not be enough and you'll need to buy a license.

  • I'am just playing around with your package, especially with the ContentPageXaml page on IPhone 4S.
    The sample works great, but if i change mr:ContentPage to ContentPage and Image to mr:Image and
    moving the commands to the mr:image, then the sample is slow and flicker.
    The panning goes wrong after rotating the image

    <RelativeLayout>
        <ContentView Padding="50"
                RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}"
                RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"
                RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}"
                RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}">
    
            <mr:Image 
                TappingCommand="{Binding TappingCommand}"
                TappedCommand="{Binding TappedCommand}"
                PanningCommand="{Binding PanningCommand}"
                PannedCommand="{Binding PannedCommand}"
                SwipedCommand="{Binding SwipedCommand}"
                PinchingCommand="{Binding PinchingCommand}"
                PinchedCommand="{Binding PinchedCommand}"
                RotatingCommand="{Binding RotatingCommand}"
                RotatedCommand="{Binding RotatedCommand}"
                Source="{Binding ImageSource}"
                Scale="{Binding Scale}"
                Rotation="{Binding Rotation}"
                TranslationX="{Binding TranslationX}"
                TranslationY="{Binding TranslationY}"
                AnchorX="{Binding AnchorX}"
                AnchorY="{Binding AnchorY}"
            />
        </ContentView>
    
    </RelativeLayout>
    

    The intention ist to have two images, one fullscreen for pinching and panning, a second on top of
    the first image for pinching, rotating and panning. Any idea?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    There are problems when you transform a view and listen to the gestures on that same view. E.g. when you rotate the image, the coordinates of the valid touch points cannot be expressed as X/Y/W/H anymore.
    I only knew that Android has a problem with that. Apparently iOS too.

    Therefore you should add the gesture listeners always to a container (layout or page) surrounding the element you want to transform. The container should not be transformed in any way.

    In your event handlers you can check the Touches property of the EventArgs for the coordinates of the fingers on the screen. You'll have to check on which image they are yourself.

    One more warning: if you have multiple elements on the screen which overlap and you want to listen to the gestures for both of them, there may also be problems. I'm currently working on getting the event bubbling right (event is not handled by a subview and should be forwarded to a superview). But the native gesture recognizer APIs are not very intuitive for me.

  • Thanks for the information.
    Now i handle the events from the page and obtain the touched image from the event args.
    Just for the demo is it ok, but not a clean MVVM pattern.
    Hope to handle this later witch custum renderes using your GestureHandlers.

  • zurbaszurbas ESMember
    edited February 2015

    Hello
    it seems to be it does´t work for ListView?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @zurbas

    The ListView works exactly as it should on iOS and Windows Phone.
    On Android Xamarins renderer consumes the gesture events and does not send them outside. But you can add the gesture handlers to the cells instead. This works on all platforms.

    This information is also available at http://www.mrgestures.com/#Compatibility

    I'm close to submitting a new version which fixes most incompatibilities on iOS. I just need a few hours more, but it will probably be too much for today.

  • GeorgeCookGeorgeCook PEUniversity ✭✭✭

    I can't get it to work in my project
    added nuget dependencies to iOS project and to my forms project -but it just doesn't work...

    Whenever I open a xaml page with a mr gestures name spaced control I get an error : which say's that that

    Could not load file or assembly 'MR.Gestures' or one of its dependencies. The system cannot find the file specified.

    with FileName MR.Gestures.
    not sure what I'm doing wrong, and it's really a shame as I'm trying to do some spikes to appraise it's suitability beyond the samples that bundle with it.

  • zurbaszurbas ESMember
    edited March 2015

    thanks MR, thats was it i tried to do but i found some problems.

    I need from my ListView the ItemSelected with the LongPressing and Tapped Gestures.
    LongPressing works but without saving the ItemSelected and Tapped doesn´t works.

    This is my code:

    <ListView ItemsSource="{Binding List1}" SelectedItem="{Binding Item}"> <ListView.ItemTemplate> <DataTemplate> <mr:ViewCell LongPressing="Cell_LongPressing" Tapped="Cell_Tapped"> ....................` </mr:ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView>

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @zurbas

    You should also use the ListView from MR.Gestures. Like you can see in https://github.com/MichaelRumpler/GestureSample/blob/master/GestureSample/GestureSample/Views/ImageCellXaml.xaml

    Just add "mr:" to the ListView tags.

    <br /><mr:ListView   ItemsSource="{Binding List1}"     SelectedItem="{Binding Item}">
        <ListView.ItemTemplate>
        <DataTemplate>
                <mr:ViewCell   LongPressing="Cell_LongPressing" Tapped="Cell_Tapped">
                        ....................`          
                </mr:ViewCell>
        </DataTemplate>
        </ListView.ItemTemplate>
    </mr:ListView>
    
    

    Then the Cell_Tapped handler should work.

    Unfortunately the SelectedItem does not work at the same time yet. So you would have to set the Item manually in Cell_Tapped.

    Fetch the latest changes of the https://github.com/MichaelRumpler/GestureSample. I added

    • a Item property to ListOfObjectsViewModel.cs
    • SelectedItem="{Binding Item}" to ImageCellXaml.xaml
    • code to set the Item in Cell_Tapping in ImageCellXaml.xaml.cs
  • zurbaszurbas ESMember

    @MichaelRumpler with " Tapped " has not worked for me , but with "Tapping " works , thank you very much

  • I'm using the latest version on a android htc one s and i think the viewposition in the eventargs
    is not correct for this android device.
    Resolution 540 x 960 pixel, 256 dpi, scale 1.5 --> 360 x 640 dpi
    In the evenargs i got 270 x 480 dpi, are you using scale fixed with 2.0?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @HolgerRousselle.4906

    Yes, I do.
    I asked how Xamarin works with dimensions on Android in November in https://forums.xamarin.com/discussion/28131/absolutelayout-layoutbounds-units#latest

    But I didn't get an answer so I hardcoded the scale to 2. I thought thats what Xamarin.Forms expects on all devices.
    Where did you get your scale value from? Maybe I could use this instead?

  • KenKenKenKen HKMember

    is this free or ?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @KenKen

    It costs € 10,- per App. You can find this information at http://www.mrgestures.com/

  • I used:

    Resources.DisplayMetrics

    density=1.5,
    width=540,
    height=960,
    scaledDensity=1.5,
    xdpi=279.91837,
    ydpi=280.27585

    Android.Util.DisplayMetrics

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    OK, I'll use DisplayMetrics.Density in the next version. But I'm currently refactoring all the Android renderers so right now is a bad time to deploy a new version. It'll come out in a day or two.

  • Thanks.
    It would be nice to have a changelog for the new versions.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭
  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    I just released version 1.0.8. This includes some major improvements for Android. Now all events work on all elements and the Xamarin events work too at the same time.

    • [Android] handle all touch events on all elements additionally to Xamarins handlers
    • [Android] better resource management
    • [Android] use DisplayMetrics.Density instead of hardcoded 2 for calculating ViewPosition, Touches and PanEventArgs.DeltaDistance
    • [Android] don't start pan when lifting one finger after multi touch gesture

    I even placed a map within an AbsoluteLayout and I get the events from the AbsoluteLayout. This way I can see the coordinates where the user tapped on the map.

  • OtaMaresOtaMares DEMember ✭✭
    edited March 2015

    Hey, is it possible to differentiate between a tap down and up event? We would like to colorize a cell on tap down and restore the custom color on tap up.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @OtaMares

    Currently not, but it should be no problem to add it.

  • OtaMaresOtaMares DEMember ✭✭

    Oh, that would make our live so much easier. :)

  • binbin.9006binbin.9006 CNMember ✭✭

    m Chinese, I is the individual developers, each app will need to buy one? If each app to buy, then I can not afford to buy, because my app is not to make money for the purpose of, what is a good solution.

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @binbin.9006

    This info is on http://www.mrgestures.com/#Buy

    MR.Gestures is licensed per app name. I.e. if your app has the same name on all three platforms, you only need one license key. If you have different versions of your app (e.g. a free and a pro one) with different names, then you need a separate key for each version.

    You can use it for as many developers on as many computers as you like.

    The price for one license is EUR 10.00 (+VAT).

    So you only pay once for each app name. Even if you have many developers working on your app, you don't need a separate license key for all of them.

    After all you already payed USD 999 per developer per platform per year to Xamarin. So I do understand that you cannot afford too much for an additional component.

  • binbin.9006binbin.9006 CNMember ✭✭

    Software name refers to what? The name of the package? To use and buy a tutorial? Only in this way to buy at a 10? I'm Chinese, and individual developers, the money is out of pocket. After the learning phase.

  • CharlesHoranCharlesHoran USMember ✭✭

    Does Mr.Gestures provide gesture recognizers that can be added to any Xamarin.Forms compliant control, or does it only work with the controls that Mr.Gestures wraps?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @CharlesHoran , it works only with the controls from MR.Gestures but it wraps all Xamarin.Forms controls. You can find a list at http://www.mrgestures.com/#Compatibility

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    @OtaMares @PhaseCore

    MR.Gestures version 1.1.0 has been released. This version adds the Down and Up events.

    Those events are raised when one or more fingers come down to or up from the touch screen. If the fingers do not move at the same time, then you get multiple events.
    Those two events use new DownUpEventArgs which include an int[] TriggeringTouches. This array holds indexes in the Touch array and tell you, which fingers came down/up.
    So Up is the only event, where the Touch array contains coordinates of a finger, which is not on the screen anymore.

    Unfortunately I still have a problem with the Down/Up events on iOS with the Button, Slider and Stepper. They do not work when you listen to the new events. On all other controls and the other platforms, Down+Up work as expected. See http://www.mrgestures.com/#Compatibility for details.

    This version also fixes a NullReferenceException which occured when you had an async event handler which disposed of the control it was attached to. I added a test page to the GestureSample app for this bug and it works with the new version.

  • Yay, Thanks you very much!

  • OtaMaresOtaMares DEMember ✭✭

    Yes, thank you :)

  • ZayarMin.6413ZayarMin.6413 SGMember, University

    I try to add image zooming to ViewCell in ListView. It works fine in iOS. In Andriod, ViewCell pinching is mixing with ListView scrolling event and user experience in zooming is not nice. During pinching, scrolling becomes active and pinching stops. User need to pinch very carefully not to trigger scrolling. Is there any way to block ListView scrolling during view cell is pinching?

  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    I don't think that you can stop a ListView from scrolling.

  • EmilSvrdEmilSvrd USMember
    edited April 2015

    I'm trying to get an image to move on the screen with the panning gesture. I understood by reading this thread that in order to get the correct X and Y values I had to wrap the image in a Layout. So, I did that, and it works. And the image moves, sometimes. It stops before I have lifted my finger from the screen, even if I continuously move my finger over the screen. Sometimes it doesn't move at all when I do the panning gesture. The response I get from the pinching gesture is similar. Sometimes it works, sometimes it doesn't.

    I tried changing the ScrollView tag to StackLayout and AbsoluteLayout, but it makes no difference. It acts the same.
    I have only tested this on an Android device.
    I'm using Xamarin Forms in a PCL project.
    I have configured the application with a MR.Gestures registration code, so I'm getting actual X and Y values.

    Have I misunderstood how to use the gestures?

    My XAML code:

          <mr:ScrollView x:Name="wrapper" Pinching="PinchingHandler" Panning="PanningHandler" DoubleTapped="DoubleTappedHandler" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
            <mr:Image x:Name="imageHolder" Source="{Binding ImageSource}" />
          </mr:ScrollView>
    

    My code behind:

            void PinchingHandler(object sender, MR.Gestures.PinchEventArgs e)
            {
                imageHolder.Scale += 0.01;
            }
    
            void DoubleTappedHandler(object sender, MR.Gestures.TapEventArgs e)
            {
                imageHolder.Scale += 1;
            }
    
            void PanningHandler(object sender, MR.Gestures.PanEventArgs e)
            {
                var d = e.DeltaDistance;
                info.Text = "x: " + d.X + ", y: " + d.Y;
                imageHolder.TranslationX += d.X;
                imageHolder.TranslationY += d.Y;
            }
    
  • MichaelRumplerMichaelRumpler ATMember ✭✭✭✭✭

    This looks very similar to what I did in the https://github.com/MichaelRumpler/GestureSample, just without ViewModel.
    You can move an image around in the ContentPage sample and a Frame in the StackLayout sample. The AbsoluteLayout and ScrollView samples do not use the PanEventArgs.

    Did you try the GestureSample? Did it work on your device?

    I think your code should work. No idea why it doesn't. Can you send me your solution so that I can try it myself?

    (The Image doesn't have to be a MR.Gestures.Image. A Xamarin.Forms.Image should suffice.)

  • EmilSvrdEmilSvrd USMember

    It works when I put the image inside a RelativeLayout. For some reason I didn't try that.

«13456710
Sign In or Register to comment.