310 likes | 454 Views
Touch Input. Charles Petzold www.charlespetzold.com. Agenda. Mouse events Frame.TouchReported events Manipulation events GestureListener events. Mouse Events. Primary touch events promoted to mouse events MouseLeftButtonDown , MouseLeftButtonUp , MouseMove , MouseEnter , MouseLeave
E N D
Touch Input Charles Petzold www.charlespetzold.com
Agenda • Mouse events • Frame.TouchReported events • Manipulation events • GestureListener events
Mouse Events • Primary touch events promoted to mouse events • MouseLeftButtonDown, MouseLeftButtonUp, MouseMove, MouseEnter, MouseLeave • "Primary" means first finger down • Build touch interfaces using mouse logic only • Same code works in Silverlight desktop apps • Single-touch only!
Responding to Touch // XAML <Rectangle Width="300" Height="200" Fill="Red" MouseLeftButtonDown="OnRectangleClicked" /> // C# void OnRectangleClicked(object sender, RoutedEventArgse) { (sender as Rectangle).Fill = new SolidColorBrush(Colors.Blue); }
Touch.FrameReported Events • Low-level touch events fired by Silverlight • Up to four fingers at a time • Fired at application level, not by individual objects • Information regarding individual fingers conveyed in TouchPoint objects revealing: • Whether finger went down, moved, or lifted up • Finger position relative to specified UI element • Contact area size • Topmost element underneath finger and finger ID • Primary touch points promoted to mouse events
Handling Touch.FrameReported Touch.FrameReported+= OnFrameReported; . . . void OnFrameReported(object sender, TouchFrameEventArgs e) { // TODO: Act on touch input }
Responding to Touch // XAML <Rectangle x:Name="Rect" Width="300" Height="200" Fill="Red" /> // C# Touch.FrameReported+= OnFrameReported; ... void OnFrameReported(object sender, TouchFrameEventArgs e) { // Single touch only TouchPoint point = e.GetPrimaryTouchPoint(null); if (point.Action == TouchAction.Down&& point.TouchDevice.DirectlyOver== Rect) { Rect.Fill = new SolidColorBrush(Colors.Blue); } }
Responding to Multi-Touch // XAML <Rectangle x:Name="Rect" Width="300" Height="200" Fill="Red" /> // C# Touch.FrameReported+= OnFrameReported; ... void OnFrameReported(object sender, TouchFrameEventArgs e) { TouchPointCollection points = e.GetTouchPoints(null); foreach (TouchPoint point in points) { if (point.Action== TouchAction.Down&& point.TouchDevice.DirectlyOver== Rect) Rect.Fill= new SolidColorBrush(Colors.Blue); } }
Manipulation Events • High-level touch events fired by UI elements • Do not support simultaneous manipulation • Perform implicit capture when element is moved • Built-in inertia support • Velocity info in ManipulationCompleted events • You provide logic to use the velocity info • Consolidate interaction of two fingers into X and Y scaling factors for pinch-zooming
Moving a UI Element // XAML <Rectangle ... Fill="Red" ManipulationDelta="OnManipulationDelta"> <Rectangle.RenderTransform> <TranslateTransform /> </Rectangle.RenderTransform> </Rectangle> // C# private void OnManipulationDelta(object sender, ManipulationDeltaEventArgse) { Rectangle rect = sender as Rectangle; TranslateTransform transform = rect.RenderTransform as TranslateTransform; transform.TranslateX+= e.DeltaManipulation.Translation.X; transform.TranslateY+= e.DeltaManipulation.Translation.Y; }
Scaling a UI Element // XAML <Rectangle ... Fill="Red" ManipulationDelta="OnManipulationDelta"> <Rectangle.RenderTransform> <ScaleTransform /> </Rectangle.RenderTransform> </Rectangle> // C# private void OnManipulationDelta(object sender, ManipulationDeltaEventArgse) { if (e.DeltaManipulation.Scale.X > 0.0 && e.DeltaManipulation.Scale.Y > 0.0) { Rectangle rect = sender as Rectangle; ScaleTransform transform = rect.RenderTransform as ScaleTransform; transform.ScaleX *= e.DeltaManipulation.Scale.X; transform.ScaleY *= e.DeltaManipulation.Scale.Y; } }
Inertia • ManipulationCompletedEventArgs properties expose velocity information • IsInertial – True if finger was moving when it left the screen, false if not • FinalVelocities.LinearVelocity.X • FinalVelocities.LinearVelocity.Y • FinalVelocities.ExpansionVelocity.X • FinalVelocities.ExpansionVelocity.Y • Use these properties to simulate inertia • e.g., start animation to continue motion
Simulating Horizontal Inertia private void OnManipulationCompleted(object sender, ManipulationCompletedEventArgse) { if (e.IsInertial) { Rectangle rect = sender as Rectangle; TranslateTransform transform = rect.RenderTransform as TranslateTransform; InertiaAnimation.To= transform.X + e.FinalVelocities.LinearVelocity.X/ 10.0; InertiaStoryboard.Begin(); } }
Gestures • Three ways to support gestures • Roll your own using Touch.FrameReported events • Use the XNA Framework's TouchPanel class • Use the Silverlight for Windows Phone Toolkit's GestureListener class • GestureListener makes it easy • Event-based API recognizes six basic gestures • No simultaneous manipulation of UI elements • Microsoft.Phone.Controls.Toolkit assembly
Gesture Types • GestureListener supports six gestures • Tap • Double tap • Tap and hold • Drag or pan • Flick • Pinch • Pinch gestures can be used for scaling, rotation, or both
Responding to Taps // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerTap="OnTap" /> </toolkit:GestureService.GestureListener> </Rectangle> // C# private void OnTap(object sender, GestureEventArgs e) { (sender as Rectangle).Fill = new SolidColorBrush(Colors.Blue); } GestureBegin Tap GestureCompleted
Responding to Double Taps // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerDoubleTap="OnDoubleTap" /> </toolkit:GestureService.GestureListener> </Rectangle> // C# private void OnDoubleTap(object sender, GestureEventArgs e) { (sender as Rectangle).Fill = new SolidColorBrush(Colors.Blue); } GestureBegin Tap GestureCompleted GestureBegin DoubleTap GestureCompleted
Responding to Holds // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerHold="OnHold" /> </toolkit:GestureService.GestureListener> </Rectangle> // C# private void OnHold(object sender, GestureEventArgs e) { (sender as Rectangle).Fill = new SolidColorBrush(Colors.Blue); } GestureBegin Hold GestureCompleted
Moving a UI Element // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerDragDelta="OnDragDelta" /> </toolkit:GestureService.GestureListener> <Rectangle.RenderTransform> <TranslateTransform /> </Rectangle.RenderTransform> </Rectangle> // C# private void OnDragDelta(object sender, DragDeltaGestureEventArgse) { Rectangle rect = sender as Rectangle; TranslateTransform transform = rect.RenderTransform as TranslateTransform; transform.X += e.HorizontalChange; transform.Y += e.VerticalChange; } GestureBegin DragStarted DragDelta DragDelta ... DragDelta DragDelta DragCompleted GestureCompleted
Responding to Flicks // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerFlick="OnFlick" /> </toolkit:GestureService.GestureListener> <Rectangle.RenderTransform> <TranslateTransform /> </Rectangle.RenderTransform> </Rectangle> // C# private void OnFlick(object sender, FlickEventArgse) { Rectangle rect = sender as Rectangle; TranslateTransform transform = rect.RenderTransform as TranslateTransform; InertiaAnimation.To = transform.X+ e.HorizontalVelocity/ 10.0; InertiaStoryboard.Begin(); } GestureBegin DragStarted DragDelta DragDelta ... Flick DragCompleted GestureCompleted
Scaling a UI Element // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerPinchDelta="OnPinchDelta" /> </toolkit:GestureService.GestureListener> <Rectangle.RenderTransform> <ScaleTransform/> </Rectangle.RenderTransform> </Rectangle> // C# private void PinchDelta(object sender, PinchGestureEventArgs e) { Rectangle rect = sender as Rectangle; ScaleTransform transform = rect.RenderTransform as ScaleTransform; transform.ScaleX = _cx * e.DistanceRatio; transform.ScaleY = _cy * e.DistanceRatio; } GestureBegin PinchStarted PinchDelta PinchDelta ... PinchDelta PinchDelta PinchCompleted GestureCompleted
Rotating a UI Element // XAML <Rectangle Width="300" Height="200" Fill="Red"> <toolkit:GestureService.GestureListener> <toolkit:GestureListenerPinchDelta="OnPinchDelta" /> </toolkit:GestureService.GestureListener> <Rectangle.RenderTransform> <RotateTransform/> </Rectangle.RenderTransform> </Rectangle> // C# private void PinchDelta(object sender, PinchGestureEventArgs e) { Rectangle rect = sender as Rectangle; RotateTransform transform = rect.RenderTransform as RotateTransform; transform.Rotation = e.TotalAngleDelta; } GestureBegin PinchStarted PinchDelta PinchDelta ... PinchDelta PinchDelta PinchCompleted GestureCompleted
Questions? Charles Petzold www.charlespetzold.com