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

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

}

}

}