1. crash1989's Avatar
    Hi,
    I have an image viewing sample app and I wish to provide zoom, pan and flick functionality. I plan on using the GestureListener class, however this is deprecated in the Silverlight Windows phone toolkit since Nov 2011. (http://www.jeff.wilcox.name/2011/11/...1phonetoolkit/)
    So doing something like this would not be recommended I guess.(http://wintellect.com/blogs/jprosise...-phones-part-4)

    Code:
    <Image Source="Dubai.jpg" Width="2048" Height="480" CacheMode="BitmapCache">
            <toolkit:GestureService.GestureListener>
                <toolkit:GestureListener DragDelta="OnDragDelta"
                    Flick="OnFlick" DoubleTap="OnDoubleTap" />
            </toolkit:GestureService.GestureListener>
            <Image.RenderTransform>
                <TranslateTransform x:Name="PanTransform"/>
            </Image.RenderTransform>
            <Image.Resources>
    Can someone please point me to some other solution and tutorials so that I can implement this. Also please tell me if my app would be rejected in case I use the deprecated methods.

    Please note I have used Manipulation Events but the zoom is really choppy as commented here http://stackoverflow.com/questions/1...s-phone-8?lq=1 and everything is not as smooth as GestureListeners.


    Thanks in advance.
    Last edited by crash1989; 05-15-2013 at 09:56 PM.
    05-15-2013 09:46 PM
  2. crash1989's Avatar
    Ok,
    Since there have been no replies (which is becoming quite a trend on Windows phone forums) I worked on this for quite some time and found the following solution.

    GestureListeners are deprectaed, use ManipulationEvents. Dont use MultiTouch from codeplex since it might have older libraries which can have your app rejected. The crude way is below

    You can find this solution at Windows Phone Image Recipes sample in C# for Visual Studio 2012

    Just posting the code below so that you can use it as Boilerplate code ;)

    Xaml Code:
    Code:
    <ViewportControl x:Name="viewport"  
                    ManipulationStarted="OnManipulationStarted" ManipulationDelta="OnManipulationDelta"  
                                 ManipulationCompleted="OnManipulationCompleted" ViewportChanged="viewport_ViewportChanged">
                    <Canvas x:Name="canvas">
                        <Image x:Name="TestImage"  
                                RenderTransformOrigin="0,0" CacheMode="BitmapCache"
                               ImageOpened="OnImageOpened">
                            <Image.RenderTransform>
                                <ScaleTransform x:Name="xform"/>
                            </Image.RenderTransform>
                        </Image>
                    </Canvas>
                </ViewportControl>
    C# Code
    Code:
    const double MaxScale = 10;
    
    
            double _scale = 1.0;
            double _minScale;
            double _coercedScale;
            double _originalScale;
    
    
            System.Windows.Size _viewportSize;
            bool _pinching;
            Point _screenMidpoint;
            Point _relativeMidpoint;
    
    
            BitmapImage _bitmap; 
    
    /// <summary> 
            /// Either the user has manipulated the image or the size of the viewport has changed. We only 
            /// care about the size. 
            /// </summary> 
            void viewport_ViewportChanged(object sender, System.Windows.Controls.Primitives.ViewportChangedEventArgs e)
            {
                System.Windows.Size newSize = new System.Windows.Size(viewport.Viewport.Width, viewport.Viewport.Height);
                if (newSize != _viewportSize)
                {
                    _viewportSize = newSize;
                    CoerceScale(true);
                    ResizeImage(false);
                }
            }
    
    
            /// <summary> 
            /// Handler for the ManipulationStarted event. Set initial state in case 
            /// it becomes a pinch later. 
            /// </summary> 
            void OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
            {
                _pinching = false;
                _originalScale = _scale;
            }
    
    
            /// <summary> 
            /// Handler for the ManipulationDelta event. It may or may not be a pinch. If it is not a  
            /// pinch, the ViewportControl will take care of it. 
            /// </summary> 
            /// <param name="sender"></param> 
            /// <param name="e"></param> 
            void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
            {
                if (e.PinchManipulation != null)
                {
                    e.Handled = true;
    
    
                    if (!_pinching)
                    {
                        _pinching = true;
                        Point center = e.PinchManipulation.Original.Center;
                        _relativeMidpoint = new Point(center.X / TestImage.ActualWidth, center.Y / TestImage.ActualHeight);
    
    
                        var xform = TestImage.TransformToVisual(viewport);
                        _screenMidpoint = xform.Transform(center);
                    }
    
    
                    _scale = _originalScale * e.PinchManipulation.CumulativeScale;
    
    
                    CoerceScale(false);
                    ResizeImage(false);
                }
                else if (_pinching)
                {
                    _pinching = false;
                    _originalScale = _scale = _coercedScale;
                }
            }
    
    
            /// <summary> 
            /// The manipulation has completed (no touch points anymore) so reset state. 
            /// </summary> 
            void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
            {
                _pinching = false;
                _scale = _coercedScale;
            }
    
    
    
    
            /// <summary> 
            /// When a new image is opened, set its initial scale. 
            /// </summary> 
            void OnImageOpened(object sender, RoutedEventArgs e)
            {
                _bitmap = (BitmapImage)TestImage.Source;
    
    
                // Set scale to the minimum, and then save it. 
                _scale = 0;
                CoerceScale(true);
                _scale = _coercedScale;
    
    
                ResizeImage(true);
            }
    
    
            /// <summary> 
            /// Adjust the size of the image according to the coerced scale factor. Optionally 
            /// center the image, otherwise, try to keep the original midpoint of the pinch 
            /// in the same spot on the screen regardless of the scale. 
            /// </summary> 
            /// <param name="center"></param> 
            void ResizeImage(bool center)
            {
                if (_coercedScale != 0 && _bitmap != null)
                {
                    double newWidth = canvas.Width = Math.Round(_bitmap.PixelWidth * _coercedScale);
                    double newHeight = canvas.Height = Math.Round(_bitmap.PixelHeight * _coercedScale);
    
    
                    xform.ScaleX = xform.ScaleY = _coercedScale;
    
    
                    viewport.Bounds = new Rect(0, 0, newWidth, newHeight);
    
    
                    if (center)
                    {
                        viewport.SetViewportOrigin(
                            new Point(
                                Math.Round((newWidth - viewport.ActualWidth) / 2),
                                Math.Round((newHeight - viewport.ActualHeight) / 2)
                                ));
                    }
                    else
                    {
                        Point newImgMid = new Point(newWidth * _relativeMidpoint.X, newHeight * _relativeMidpoint.Y);
                        Point origin = new Point(newImgMid.X - _screenMidpoint.X, newImgMid.Y - _screenMidpoint.Y);
                        viewport.SetViewportOrigin(origin);
                    }
                }
            }
    
    
            /// <summary> 
            /// Coerce the scale into being within the proper range. Optionally compute the constraints  
            /// on the scale so that it will always fill the entire screen and will never get too big  
            /// to be contained in a hardware surface. 
            /// </summary> 
            /// <param name="recompute">Will recompute the min max scale if true.</param> 
            void CoerceScale(bool recompute)
            {
                if (recompute && _bitmap != null && viewport != null)
                {
                    // Calculate the minimum scale to fit the viewport 
                    double minX = viewport.ActualWidth / _bitmap.PixelWidth;
                    double minY = viewport.ActualHeight / _bitmap.PixelHeight;
    
    
                    _minScale = Math.Min(minX, minY);
                }
    
    
                _coercedScale = Math.Min(MaxScale, Math.Max(_scale, _minScale));
    
    
            }
    05-16-2013 08:00 PM
  3. Jay Bennett's Avatar
    Should have replied here apologies.

    The Silverlight toolkit libraries might be deprecated but your app certainly won't fail certification for using them (we use the multitouch libraries in WPCentral). Saying that, I do need to upgrade to the phone.toolkit NuGet package sometime and will be looking at Manipulation events as the way to go.

    Also the GestureListeners are pretty buggy, I get about 2-3 bug reports a day where the libraries have error'd out.
    crash1989 likes this.
    05-23-2013 06:05 AM

Similar Threads

  1. Replies: 2
    Last Post: 04-02-2013, 10:34 AM
  2. Zune HD feature that SHOULD be in Windows Phone
    By JustinSalvato in forum Windows Phone 8
    Replies: 12
    Last Post: 02-04-2013, 01:27 PM
  3. Bing rewards should be implemented in Windows Phone!
    By irvin792 in forum Windows Phone 8
    Replies: 7
    Last Post: 12-04-2012, 09:47 PM
  4. Replies: 0
    Last Post: 05-21-2012, 04:40 PM
  5. Replies: 0
    Last Post: 03-14-2012, 11:28 AM
LINK TO POST COPIED TO CLIPBOARD