• WP7开发—Silverlight多点触摸事件详解【含Demo代码】


        最近在学习WP7的Silverlight编程,就把学习到知识点整理为日志,方便自己理解深刻点,也作为笔记和备忘,如有不合理或者错误之处,还恳请指正。

        WP7的支持多点触摸,有两种不同的编程模式: 1、低级别使用Touch.FrameReported事件 2、高级别的使用UIElement类中定义三个事件:ManipulationStarted,ManipulationDelta和ManipulationCompleted。下面就对不同的事件进行说明和写Demo。

     

    1.低级别触摸事件:Touch.FrameReported

           多点触控事件不与其他 Silverlight 输入事件(如 MouseLeftButtonDown)使用相同的事件模型。多点触控输入事件是在应用程序级别处理的单一事件,而不是公开为可能通过 UI 的对象树路由的特定于元素的事件。然后通过事件,使用 TouchFrameEventArgs 并调用 GetPrimaryTouchPoint 和特定 UI 元素及其边界。这将确定应用程序 UI 布局中的特定触控点参考框架。
     

     Touch类:提供应用程序级服务,用以处理来自操作系统的多点触控输入并引发FrameReported事件。

      使用Touch.FrameReported事件处理程序:

    Touch.FrameReported += OnTouchFrameReported;

      OnTouchFrameReported 方法格式如下:

      void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
      {
        //
      }

        FrameReported事件:当输入系统为 Silverlight 提升 Windows 7 多点触控消息时发生,可以通过对事件进行处理并调用TouchFrameEventArgs事件数据中的GetTouchPoints或其他 API 查看详情。

        TouchFrameEventArgs为 FrameReported 事件提供数据。其主要有三个方法:

       • GetTouchPoints(refElement) :返回一个TouchPointCollection 获取多个接触点的集合,当传递null的时候,GetTouchPoints得到Position属性相对于应用程序的左上角。

       • GetPrimaryTouchPoint(refElement):返回一个TouchPoint 获取第一个手指接触点。

       • SuspendMousePromotionUntilTouchUp(): 禁止该时间被提升为鼠标事件。这个方法来自桌面的Silverlight,很多桌面程序只有鼠标按键,现在有触摸屏了,点一下触摸屏,一小下,就不好区分,这个事件是鼠标点的还是触控事件呢?这个函数就是在处理触控的时候防止同时触发鼠标的点击事件.因此,这个函数只能在,只有在处理第一个触摸事件,并且是在处理按下事件的时候才能调用.否则会抛出异常. 详细解析点击这里查看CSDN一位同学解析。
     

     TouchPoint类:一个TouchPoint的实例代表一个特定的手指触摸屏幕。可通过TouchFrameEventArgs的GetTouchPoints(refElement)或GetPrimaryTouchPoint(refElement)获得。

      TouchPoint的四个属性:

      • Action:动作类型,枚举TouchAction有Down, Move和Up三个值表示手指的按下、移动和离开。

      • Position:位置类型,Point的位置,以左上角为参考点。

      • Size:大小类型,支持接触面积(手指的压力大小),但Windows 7不会返回电话有用的值。

      • TouchDevice: 接触设备的类型TouchDevice。TouchDevice对象有两个得到只读属性:

        1. ID: int类型,用来区分手指,一个特定的手指有一个唯一测ID来触发所有的上下移动的事件。

        2. DirectlyOver: UIElement的类型,你手指的最顶层元素。
     

    实例代码:

    在xaml页加入一个TextBlock标签,显示TouchPoint属性:

    <TextBlock Name="tbTouchPoint" Text=""  />

    在后台cs构造函数加入以下代码:

            public MainPage()
    {
    InitializeComponent();

    //FrameReported事件
    Touch.FrameReported += OnTouchFrameReported;
    }

    void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
    {
               //取得第一个接触点
    TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);

    tbTouchPoint.Text = string.Format(@"
    Action: {0};
    Position: X={1}, Y={2};
    Size: Width={3}, Height={4};
    TouchDevice: Id={5};
    ",
    primaryTouchPoint.Action,
    primaryTouchPoint.Position.X,
    primaryTouchPoint.Position.Y,
    primaryTouchPoint.Size.Width,
    primaryTouchPoint.Size.Height,
    primaryTouchPoint.TouchDevice.Id);


    //SuspendMousePromotionUntilTouchUp()的用法
    if (primaryTouchPoint != null && primaryTouchPoint.Action == TouchAction.Down)
    {
    args.SuspendMousePromotionUntilTouchUp();
    }

    }

    模拟器效果图如下:

    图片效果




    2.高级别的使用UIElement类中定义三个事件:ManipulationStarted,ManipulationDelta和ManipulationCompleted
     

         这3个事件并不是单独来处理每个手指的触控信息的,它们将所有手指的平移和缩放操作进行了整合。由于这3个事件都是在UIElement类中定义的,都是基于具体的元素的,而非应用程序级别的事件,由于任何UI控件都继承于UIElement(如:TextBlock控件集成于FrameworkElement类,而FrameworkElement又继承于UIElement,如下代码),因此我们可以为任何UI元素添加对这些事件的处理,比如ListBox,Canvas,Rectangle等等。

    TextBlok继承
        // Summary:
    // Provides a lightweight control for displaying small amounts of text..
    [ContentProperty("Inlines", true)]
    public sealed class TextBlock : FrameworkElement
    {
    //省略...
    }




    // Summary:
    // Provides a framework of common APIs for objects that participate in Silverlight
    // layout. System.Windows.FrameworkElement also defines APIs related to data
    // binding, object tree, and object lifetime feature areas in Silverlight.
    public abstract class FrameworkElement : UIElement
    {
    //省略...
    }



    •   ManipulationStarted事件:当手指按下触摸屏时发生,可以通过事件并调用ManipulationStartedEventArgs的相关方法进行处理。

                ManipulationStartedEventArgs为 ManipulationStarted事件提供数据,其属性和方法如下:

    ManipulationStartedEventArgs的属性和方法
        public sealed class ManipulationStartedEventArgs : RoutedEventArgs
    {
    // Summary:
    // Initializes a new instance of the System.Windows.Input.ManipulationStartedEventArgs
    // class.
    public ManipulationStartedEventArgs();

    // Summary:
    // Gets or sets a value that marks the routed event as handled. Setting to true
    // prevents most handlers along the event route from handling the same event
    // again.
    //
    // Returns:
    // true to mark the routed event handled; false to leave the routed event unhandled,
    // which permits the event to potentially route further. The default is false.
    public bool Handled { get; set; }
    //
    // Summary:
    // Gets the container that defines the coordinates for the manipulation.
    //
    // Returns:
    // The container element.
    public UIElement ManipulationContainer { get; set; }
    //
    // Summary:
    // Gets the point from which the manipulation originated.
    //
    // Returns:
    // The point from which the manipulation originated.
    public Point ManipulationOrigin { get; }

    // Summary:
    // Completes the manipulation without inertia.
    public void Complete();
    }

                Handled属性:bool类型,默认为false获取或设置一个值,标记为已处理路由事件(后面做详细说明)如果设置为true处理相同的事件防止事件沿线大部分处理程序一次。

                ManipulationContainer属性:UIElement类型,获取操作位置所相对的元素。

                ManipulationOrigin属性:Point类型,获取操作的原点。

                Complete()方法:表示事件完成,直接触发ManipulationCompleted()事件,不会触发ManipulationDelta()事件,一般使用其来取消该操作。

     

    •  Manipulationdelta事件:当手指在触摸屏移动时发生,可以通过事件并调用ManipulationDeltaEventArgs的相关方法进行处理。

               ManipulationDeltaEventArgs为 Manipulationdelta事件提供数据,其属性和方法如下:

    ManipulationDeltaEventArgs 属性和方法
        // Summary:
    // Provides data for the System.Windows.UIElement.ManipulationDelta event.
    public sealed class ManipulationDeltaEventArgs : RoutedEventArgs
    {
    // Summary:
    // Initializes a new instance of the System.Windows.Input.ManipulationDeltaEventArgs
    // class.
    public ManipulationDeltaEventArgs();

    // Summary:
    // Gets the accumulated changes of the current manipulation, as a System.Windows.Input.ManipulationDelta.
    //
    // Returns:
    // The accumulated changes of the current manipulation.
    public ManipulationDelta CumulativeManipulation { get; }
    //
    // Summary:
    // Gets the most recent changes of the current manipulation, as a System.Windows.Input.ManipulationDelta.
    //
    // Returns:
    // The most recent changes of the current manipulation.
    public ManipulationDelta DeltaManipulation { get; }
    //
    // Summary:
    // Gets or sets a value that marks the routed event as handled. Setting to true
    // prevents most handlers along the event route from handling the same event
    // again.
    //
    // Returns:
    // true to mark the routed event handled; false to leave the routed event unhandled,
    // which permits the event to potentially route further. The default is false.
    public bool Handled { get; set; }
    //
    // Summary:
    // Gets whether the System.Windows.UIElement.ManipulationDelta event occurs
    // during inertia.
    //
    // Returns:
    // true if the System.Windows.UIElement.ManipulationDelta event occurs during
    // inertia; false if the event occurs while the user's input device has contact
    // with the element.
    public bool IsInertial { get; }
    //
    // Summary:
    // Gets the container that defines the coordinates for the manipulation.
    //
    // Returns:
    // The container element.
    public UIElement ManipulationContainer { get; }
    //
    // Summary:
    // Gets the point from which the manipulation originated.
    //
    // Returns:
    // The point from which the manipulation originated.
    public Point ManipulationOrigin { get; }
    //
    // Summary:
    // Gets the rates of the most recent changes to the manipulation.
    //
    // Returns:
    // The rates of the most recent changes to the manipulation.
    public ManipulationVelocities Velocities { get; }

    // Summary:
    // Completes the manipulation without inertia.
    public void Complete();
    }

               其属性除了与ManipulationStartedEventArgs相同属性和方法之外,还多了以下几个属性:

               CumulativeManipulation属性:ManipulationDelta类型,返回当前操作累积变化

               DeltaManipulation属性:ManipulationDelta类型,返回当前操纵近期变化

               IsInertial属性:Bool类型,返回事件是否发生惯性如果为true如果事件发生在惯性(即连续性);如果false,则与用户的输入设备联系。

               Velocities属性:ManipulationVelocities类型,操纵近期变化率。


    •  ManipulationCompleted事件:当手指释放触摸屏时发生,可以通过事件并调用ManipulationCompletedEventArgs的相关方法进行处理。
    ManipulationCompletedEventArgs属性
        // Summary:
    // Provides data for the System.Windows.UIElement.ManipulationCompleted event.
    public sealed class ManipulationCompletedEventArgs : RoutedEventArgs
    {
    // Summary:
    // Initializes a new instance of the System.Windows.Input.ManipulationCompletedEventArgs
    // class.
    public ManipulationCompletedEventArgs();

    // Summary:
    // Gets the velocities that are used for the manipulation.
    //
    // Returns:
    // The velocities that are used for the manipulation.
    public ManipulationVelocities FinalVelocities { get; }
    //
    // Summary:
    // Gets or sets a value that marks the routed event as handled. Setting to true
    // prevents most handlers along the event route from handling the same event
    // again.
    //
    // Returns:
    // true to mark the routed event handled; false to leave the routed event unhandled,
    // which permits the event to potentially route further. The default is false.
    public bool Handled { get; set; }
    //
    // Summary:
    // Gets whether the System.Windows.UIElement.ManipulationCompleted event occurs
    // during inertia.
    //
    // Returns:
    // true if the System.Windows.UIElement.ManipulationCompleted event occurs during
    // inertia; false if the event occurs while the user's input device has contact
    // with the element.
    public bool IsInertial { get; }
    //
    // Summary:
    // Gets the container that defines the coordinates for the manipulation.
    //
    // Returns:
    // The container element.
    public UIElement ManipulationContainer { get; }
    //
    // Summary:
    // Gets the point from which the manipulation originated.
    //
    // Returns:
    // The point from which the manipulation originated.
    public Point ManipulationOrigin { get; }
    //
    // Summary:
    // Gets the total transformation that occurs during the current manipulation.
    //
    // Returns:
    // The total transformation that occurs during the current manipulation.
    public ManipulationDelta TotalManipulation { get; }
    }

            ManipulationCompletedEventArgs的属性在前面已经出现,在此不在重复说明。


     

    路由事件:

           所谓的路由事件是指UI层里面,这个事件会一层层从由里向外传播。例如:

    UI代码:

    <phone:PhoneApplicationPage>
    <Grid x:Name="ContentPanel" ManipulationStarted="ContentPanel_ManipulationStarted">
    <TextBox Name="tbShow" ManipulationCompleted="tbShow_ManipulationCompleted>
    </TextBox>
    </Grid>
    </phone:PhoneApplicationPage>

    后台代码:

            private void tbShow_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
    //记录事件触发,调试是Output窗口可以看到打印信息,
    //如果没有打开Output窗口,在VS顶部菜单Deubug/Windows/Output可以打开。
    System.Diagnostics.Debug.WriteLine(DateTime.Now + " tbShow_ManipulationStarted \r\n");
    }

    /// <summary>
    /// TextBlock外层Grid的ManipulationStarted事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ContentPanel_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
    {
    System.Diagnostics.Debug.WriteLine(DateTime.Now + " ContentPanel_ManipulationStarted \r\n"); //记录事件触发
    }

    /// <summary>
    /// 重写Page的OnManipulationStarted事件
    /// </summary>
    /// <param name="e"></param>
    protected override void OnManipulationStarted(ManipulationStartedEventArgs e)
    {
    System.Diagnostics.Debug.WriteLine(DateTime.Now + " OnManipulationStarted \r\n"); //记录事件触发
    }

    运行结果如下:

    10/15/2011 5:25:53 PM tbShow_ManipulationStarted 

    10/15/2011 5:25:53 PM ContentPanel_ManipulationStarted

    10/15/2011 5:25:53 PM OnManipulationStarted

    由上面结果可以看出,ManipulationStarted是从里向外传播,如果要防止传播,只要设置Handled=true即可

    ————————————————————————————

    具体Demo代码如下点击这里进行下载



     


  • 相关阅读:
    第一章 重构
    Android View的事件分发
    java.lang.NoSuchMethodError: android.view.View.setBackground
    handler消息机制
    魅族手机Listview下拉出现hold字样的奇葩问题解决方案
    数据结构--树,二叉树
    数据结构之栈和队列
    设计模式--六大原则
    ListView上下线添加
    Python 入门(七)函数
  • 原文地址:https://www.cnblogs.com/foolin/p/WindowsPhone7_TouchAndManipulation.html
Copyright © 2020-2023  润新知