Support for "flick"?

6 posts, 0 answers
  1. Philip
    Philip avatar
    1 posts
    Member since:
    Aug 2012

    Posted 10 Aug 2012 Link to this post

    I've installed the Telerik sample app on my phone and I'm particularly interested in using the PanAndZoom control.
    When you zoom into the image, it doesn't seem to be possible to scroll, exactly. The behaviour seems to be that you swipe your finger and the image moves a bit but then stops. If you try to "flick", as you might do on a list, the image does not move a greater distance - it still only moves a smallish amount and then stops.
    Is there a way for the control to provide a smoother scrolling behaviour? I want to make sure the control will meet my needs before purchasing it.
    Thanks.
    Philip

  2. Victor
    Admin
    Victor avatar
    1351 posts

    Posted 10 Aug 2012 Link to this post

    Hi Philip,

    Thanks for writing.
    Current PanAndZoomImage does not support the flick gesture however this is a great feature and we will probably implement it in a future release.

    Please write again if you have other questions.

    Regards,
    Victor
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. DevCraft banner
  4. Bart
    Bart avatar
    1 posts
    Member since:
    Jun 2014

    Posted 11 Jun 2014 in reply to Victor Link to this post

    It's been nearly two years since this request was made. I recently started using this control and I'd like to know if there's any update.
  5. Tsvyatko
    Admin
    Tsvyatko avatar
    832 posts

    Posted 16 Jun 2014 Link to this post

    Hello Bart,

    Thank you for contacting us. With the current release we do not support this feature. However, in the light 
    of windows universal application solution we are re-evaluating all customer feedback, so we will reconsider this feature as well.

    Regards,
    Tsvyatko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  6. Sven
    Sven avatar
    1 posts
    Member since:
    Oct 2013

    Posted 21 Jun 2014 Link to this post

    Hello Tsvyatko,

    thanks for that info. I'd really like to see an integrated flick within the PanAndZoomImage.

    @Bart and all others who are looking for a flick animation and can't wait until Telerik integrates one:
    I've used the following code to get an acceptable flick within one of my apps. It's still not perfect but didn't received any complaints yet.

    There might be some members you don't need/want, e.g. the ColorTheme. I'm using it to let the user customize the look of the app.
    In addition there's an event called AlternateDoubleTap. It's kind of hackish. I'm subscribing to the Tap and DoubleTap event. Unfortunately both are fired on double tap. To work around I fire the AlternateDoubleTap first to indicate that it's not a single tap.

    Please review the code below. Feel free to play around with the InertiaDeceleration property.

    001.namespace DirtySharp.Phone.NineGAG.Controls
    002.{
    003.  using System;
    004.  using System.Windows;
    005.  using System.Windows.Controls;
    006.  using System.Windows.Input;
    007.  using System.Windows.Media.Animation;
    008.  using DirtySharp.Phone.NineGAG.Theming;
    009.  using Telerik.Windows.Controls;
    010.  using GestureEventArgs = System.Windows.Input.GestureEventArgs;
    011. 
    012.  public class PanAndZoomImage : Telerik.Windows.Controls.SlideView.PanAndZoomImage
    013.  {
    014.    #region Events
    015. 
    016.    public event EventHandler<GestureEventArgs> AlternateDoubleTap;
    017. 
    018.    protected virtual void RaiseAlternateDoubleTap( GestureEventArgs e )
    019.    {
    020.      var handler = AlternateDoubleTap;
    021.      if ( handler != null ) handler( this, e );
    022.    }
    023. 
    024.    #endregion
    025. 
    026. 
    027.    #region Private Fields
    028. 
    029.    private Image _image;
    030. 
    031.    private readonly Storyboard _flick;
    032. 
    033.    private readonly Storyboard _panAndZoom;
    034. 
    035.    private readonly PointAnimation _flickAnimation;
    036. 
    037.    private readonly PointAnimation _panAnimation;
    038. 
    039.    private readonly DoubleAnimation _zoomAnimation;
    040. 
    041.    private static readonly ColorTheme Theme = new ColorTheme();
    042. 
    043.    private double _maxPanDown;
    044. 
    045.    private double _maxPanUp;
    046. 
    047.    #endregion
    048. 
    049. 
    050.    #region Constructor
    051. 
    052.    public PanAndZoomImage()
    053.    {
    054.      // flick
    055.      var easing = new CircleEase { EasingMode = EasingMode.EaseOut };
    056.      _flickAnimation = new PointAnimation();
    057.      _flickAnimation.EasingFunction = easing;
    058.      _flickAnimation.Duration = new Duration( TimeSpan.FromMilliseconds( 1000 ) );
    059. 
    060.      Storyboard.SetTargetProperty( _flickAnimation, new PropertyPath( "Pan" ) );
    061.      Storyboard.SetTarget( _flickAnimation, this );
    062. 
    063.      _flick = new Storyboard { AutoReverse = false };
    064.      _flick.Children.Add( _flickAnimation );
    065. 
    066.      // pan and zoom, used for double tapping
    067.      _panAnimation = new PointAnimation
    068.      {
    069.        Duration = new Duration( TimeSpan.FromMilliseconds( 150 ) ),
    070.        EasingFunction = easing
    071.      };
    072. 
    073.      _zoomAnimation = new DoubleAnimation
    074.      {
    075.        Duration = new Duration( TimeSpan.FromMilliseconds( 150 ) ),
    076.        EasingFunction = easing,
    077.        From = 1
    078.      };
    079. 
    080.      Storyboard.SetTargetProperty( _panAnimation, new PropertyPath( "Pan" ) );
    081.      Storyboard.SetTargetProperty( _zoomAnimation, new PropertyPath( "Zoom" ) );
    082.      Storyboard.SetTarget( _panAnimation, this );
    083.      Storyboard.SetTarget( _zoomAnimation, this );
    084. 
    085.      _panAndZoom = new Storyboard();
    086.      _panAndZoom.Children.Add( _panAnimation );
    087.      _panAndZoom.Children.Add( _zoomAnimation );
    088. 
    089.      Loaded += ( s, e ) => _image = ElementTreeHelper.FindVisualDescendant<Image>( this );
    090.      ManipulationCompleted += DoFlick;
    091.    }
    092. 
    093.    #endregion
    094. 
    095. 
    096.    #region Dependency Properties
    097. 
    098.    public static readonly DependencyProperty InertiaDecelerationProperty = DependencyProperty.Register(
    099.      "InertiaDeceleration", typeof (double), typeof (PanAndZoomImage), new PropertyMetadata( default( double ) ) );
    100. 
    101.    public double InertiaDeceleration
    102.    {
    103.      get { return (double) GetValue( InertiaDecelerationProperty ); }
    104.      set { SetValue( InertiaDecelerationProperty, value ); }
    105.    }
    106. 
    107.    #endregion
    108. 
    109. 
    110.    #region Overrides of PanAndZoomImage
    111. 
    112.    public override void OnApplyTemplate()
    113.    {
    114.      base.OnApplyTemplate();
    115. 
    116.      var indicator = ElementTreeHelper.FindVisualDescendant<RadBusyIndicator>( this );
    117.      if ( indicator != null )
    118.      {
    119.        indicator.Foreground = Theme.AccentBrush;
    120.      }
    121.    }
    122. 
    123.    protected override void OnDoubleTap( GestureEventArgs e )
    124.    {
    125.      RaiseAlternateDoubleTap( e );
    126. 
    127.      if ( Zoom > 1 )
    128.      {
    129.        Pan = new Point( 0, 0 );
    130.        base.OnDoubleTap( e );
    131.        return;
    132.      }
    133. 
    134.      // decide whether to zoom horizontally or vertically
    135.      var zoomX = RenderSize.Width / _image.RenderSize.Width;
    136.      var zoomY = RenderSize.Height / _image.RenderSize.Height;
    137.      var zoom = Math.Abs( Math.Round( zoomX, 0 ) - 1 ) < double.Epsilon
    138.        ? (Math.Abs( zoomY - 1 ) < double.Epsilon ? zoomX : zoomY)
    139.        : zoomX;
    140.      if ( double.IsNaN( zoom ) || double.IsInfinity( zoom ) )
    141.        return;
    142. 
    143.      // get pan range.
    144.      double panRange = (zoom * RenderSize.Height) - RenderSize.Height;
    145.      _maxPanUp = panRange / 2;
    146.      _maxPanDown = -1 * _maxPanUp;
    147. 
    148.      // calculate final pan relative to the recent touch point.
    149.      Point touch = e.GetPosition( _image );
    150. 
    151.      double halfHeight = RenderSize.Height / 2;
    152.      bool isPanUp = touch.Y <= halfHeight;
    153.      double touchY = touch.Y - (isPanUp ? 0 : halfHeight);
    154.      double offset = touchY / halfHeight;
    155.      double panY = isPanUp ? _maxPanUp - offset * _maxPanUp : offset * _maxPanDown;
    156. 
    157. 
    158.      _panAnimation.From = new Point( 0, 0 );
    159.      _panAnimation.To = new Point( 0, panY );
    160.      _zoomAnimation.To = zoom;
    161. 
    162.      _panAndZoom.Begin();
    163.    }
    164. 
    165.    #endregion
    166. 
    167. 
    168.    #region Event Handler
    169. 
    170.    private void DoFlick( object sender, ManipulationCompletedEventArgs e )
    171.    {
    172.      if ( Math.Abs( Pan.Y - _maxPanUp ) < double.Epsilon ||
    173.           Math.Abs( Pan.Y - _maxPanDown ) < double.Epsilon ) return;
    174. 
    175.      if ( Math.Abs( Zoom - 1 ) < double.Epsilon ) return;
    176. 
    177.      if ( Math.Abs( e.TotalManipulation.Scale.X ) > double.Epsilon ||
    178.           Math.Abs( e.TotalManipulation.Scale.Y ) > double.Epsilon ) return;
    179. 
    180.      // stop flick on tap
    181.      if ( e.IsTapGesture() )
    182.      {
    183.        _flickAnimation.To = Pan;
    184.        _flick.SkipToFill();
    185.        return;
    186.      }
    187. 
    188.      if ( !e.IsInertial ) return;
    189. 
    190.      Point start = Pan;
    191.      Size size = _image.RenderSize;
    192.      double height = size.Height * Zoom;
    193.      double width = size.Width * Zoom;
    194.      Point velocity = e.FinalVelocities.LinearVelocity;
    195.       
    196.      double dx = velocity.X * Math.Min( InertiaDeceleration, Zoom );
    197.      double dy = velocity.Y * Math.Min( InertiaDeceleration, Zoom );
    198. 
    199.      double sx = Math.Sign( dx );
    200.      double sy = Math.Sign( dy );
    201. 
    202.      dx = sx * Math.Min( Math.Abs( dx ), width / 3 );
    203.      dy = sy * Math.Min( Math.Abs( dy ), height / 3 );
    204. 
    205.      double endX = start.X + dx;
    206.      double endY = start.Y + dy;
    207.       
    208.      _flickAnimation.From = start;
    209.      _flickAnimation.To = new Point( endX, endY );
    210.      _flick.Begin();
    211.    }
    212. 
    213.    #endregion
    214.  }
    215.}

    And the according XAML:
    01.<Style x:Key="PanAndZoomImageStyle" TargetType="controls:PanAndZoomImage">
    02.    <Setter Property="UseOptimizedManipulationRouting" Value="False"/>
    03.    <Setter Property="CacheMode" Value="BitmapCache"/>
    04.    <Setter Property="Template">
    05.        <Setter.Value>
    06.            <ControlTemplate TargetType="controls:PanAndZoomImage">
    07.                <Border Background="#00FFFFFF">
    08.                    <Grid>
    09.                        <Image x:Name="image"
    10.                                CacheMode="{TemplateBinding CacheMode}"
    11.                                HorizontalAlignment="{TemplateBinding ImageHorizontalAlignment}"
    12.                                RenderTransformOrigin="0.5, 0.5"
    13.                                Source="{TemplateBinding Source}"
    14.                                Stretch="{TemplateBinding Stretch}"
    15.                                VerticalAlignment="{TemplateBinding ImageVerticalAlignment}" />
    16.                        <telerikPrimitives:RadBusyIndicator x:Name="busyIndicator"
    17.                                                            Style="{TemplateBinding BusyIndicatorStyle}"
    18.                                                            Foreground="{TemplateBinding Tag}" />
    19.                    </Grid>
    20.                </Border>
    21.            </ControlTemplate>
    22.        </Setter.Value>
    23.    </Setter>
    24.    <Setter Property="BusyIndicatorStyle">
    25.        <Setter.Value>
    26.            <Style TargetType="telerikPrimitives:RadBusyIndicator">
    27.                <Setter Property="InitialDelay" Value="00:00:0.3"/>
    28.                <Setter Property="AnimationStyle" Value="AnimationStyle7"/>
    29.            </Style>
    30.        </Setter.Value>
    31.    </Setter>
    32.</Style>


    1.<controls:PanAndZoomImage x:Name="PanAndZoomImage"
    2.                          ZoomMode="Free"
    3.                          MaximumZoom="25"
    4.                          InertiaDeceleration="5"
    5.                          ImageHorizontalAlignment="Stretch"
    6.                          Style="{StaticResource PanAndZoomImageStyle}"
    7.                          Source="..." />

    If you need a "live preview" have a look at 9GAG Plus.

    Best regards,
    Sven
  7. Lance | Tech Support Engineer, Sr.
    Admin
    Lance | Tech Support Engineer, Sr. avatar
    135 posts

    Posted 25 Jun 2014 Link to this post

    Hi Sven,

    Thank you for sharing with the Telerik developer community, it is appreciated. As Tsvyatko stated, we are seriously considering including this functionality into a future release.

    If you have any further suggestions, please do not hesitate to add them to this new forum thread dedicated solely for feature and control suggestions for the upcoming UI for Universal Windows Apps controls. We evaluate every suggestion with zeal and use your feedback to make the Telerik controls better.

    Thank you for contacting Support and thank you for choosing Telerik.

    Regards,
    Lance | Senior Support Specialist
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top
DevCraft banner