Effective and Easy Logic For Touch Control and Slow Finishing Action After Touch Leaves

Introduction

While analyzing some controls used for touch devices I found this effective and easy logic for touch control and slow finishing action after touch leaves. Normally in touch devices we like to have control of an application with very smooth touch interaction. We also expect some slow finish of the action, like if we tap and wipe a control then it will move some distance and stay. So I found this logic to do that in an effective manner.

Platform support this approach

  • WPF
  • Windows Stores (WinRT)
  • Windows Phones 8 

Concept behind the approach

In my logic I have handled the manipulation of the data to the control. Using the manipulation of the data, I reset the matrix value of the control as desired. For slow finishing, I used a timer that enables the control for slower and smooth finishing actions after touch leaves.

XAML Code snippet behind the approach

<Button x:Class="TouchApplication.SmoothestTouchControl"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="300">

  <Grid>

  </Grid>

</Button>

<Window x:Class="TouchApplication.MainWindow"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="MainWindow" Height="350" Width="525"

xmlns:local="clr-namespace:WpfApplication8">

  <Grid >

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" />

 

    <local:SmoothestTouchControl IsManipulationEnabled="True"

    RenderTransform="0.9 0 0 0.9 100 100" /

  </Grid>

</Window>

C# code snippet behind the approach
 

// Use required name space  using System;

using System.Linq;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Input;

using System.Windows.Media;

 

namespace TouchApplication

{

    /// Interaction logic for SmoothestTouchControl.xaml

 

    public partial class SmoothestTouchControl : Button

    {

        int i = 0; // Iteration count for slower animation to end

        UIElement uiElement = null; // contains current control

        MatrixTransform matrixTransform = null; // contains Matrix transform

        Matrix uiElementMatrix = new Matrix(); // contains Matrix of the UIElement

        ManipulationDelta manipulationDelta = null; // contains data of Manipulation

        Point centerPoint = new Point(); // contains center point of the element

        System.Windows.Forms.Timer smoother = new System.Windows.Forms.Timer(); // Animater that slow down the action after touch leave

        public SmoothestTouchControl()

        {

            smoother.Interval = 1; // Inverval for animater

            smoother.Tick += smoother_Tick; // hook event to animation

        }

        // override manupulation starting to reset the Z order to get the current touched UI element a top element

        protected override void OnManipulationStarting(ManipulationStartingEventArgs args)

        {

            args.ManipulationContainer = App.Current.MainWindow; // Get the parent window

 

            var frameworkElement = args.Source as FrameworkElement; // Get the current touched element

 

            var panel = frameworkElement.Parent as Panel; // Get parent element to have the children collection

 

            for (int i = 0; i < panel.Children.Count; i++) // Iterate the children collection to reset the Z order

            {

                Panel.SetZIndex(panel.Children[i], panel.Children[i] == frameworkElement ? panel.Children.Count : i);

            }

            args.Handled = true; // Get handled true

 

            base.OnManipulationStarting(args); // Call base for original action

        }

        // override manipulation delta for transform actions

        protected override void OnManipulationDelta(ManipulationDeltaEventArgs args)

        {

            uiElement = args.Source as UIElement; // Get the current touched element

            matrixTransform = uiElement.RenderTransform as MatrixTransform; // Get MatrixTransform of the element

            uiElementMatrix = matrixTransform.Matrix; // Get Matrix of the element

            manipulationDelta = args.DeltaManipulation; // Get delta manipulation of the touch action

            centerPoint = args.ManipulationOrigin; // Get center point of the manipulation

 

            uiElementMatrix.RotateAt(manipulationDelta.Rotation, centerPoint.X, centerPoint.Y); // Rotate the ccontrol acccording to manipulation

            uiElementMatrix.ScaleAt(manipulationDelta.Scale.X, manipulationDelta.Scale.Y, centerPoint.X, centerPoint.Y); // Scale the ccontrol acccording to manipulation

            uiElementMatrix.Translate(manipulationDelta.Translation.X, manipulationDelta.Translation.Y); // Move the ccontrol acccording to manipulation

 

            matrixTransform.Matrix = uiElementMatrix; // Reset the updated matrix to the element matrix

            args.Handled = true; // Get handled true

            base.OnManipulationDelta(args); // Call base for original action

        }

        // override manipulation completed to start slower finish of the touch action

        protected override void OnManipulationCompleted(ManipulationCompletedEventArgs e)

        {

            base.OnManipulationCompleted(e); // Call base for original action

            smoother.Interval = 1; // reset the interval of the slower finish action

            i = 10; // Reset the iterator of the slower finish

            smoother.Start(); // Start animation for slower finish

        }

 

        // slowe finish animater logic

        void smoother_Tick(object sender, EventArgs e)

        {

            i--; // for slow finish action

 

            smoother.Interval = smoother.Interval + 2; // increase interval for integrated slow finish

 

            if (smoother.Interval > 25) // Check for dezire interval

                smoother.Stop(); // Stop the animation


            if (manipulationDelta.Rotation != 0) // Check if the control atually in rotation

            {

                uiElementMatrix.RotateAt(manipulationDelta.Rotation - (i > 0 ? i : 1), centerPoint.X, centerPoint.Y); // keep rotation using iterated value

            }

            uiElementMatrix.Translate(manipulationDelta.Translation.X - (i > 0 ? i : 0), manipulationDelta.Translation.Y - (i > 0 ? i : 0)); // keep moving using iterated value

            matrixTransform.Matrix = uiElementMatrix; // reset the updated matrix to the element matrix  

        } 

    }

}


Recommended Free Ebook
Similar Articles