Windows Phone 7 学习流程攻略(三)

今天介绍触摸屏点击

从硬件设计上说Windows Phone 7至少可以接收4个手指的触摸事件。

 

一、在XNA上的Low-Level触摸事件

可以利用全局的TouchPanel class来的到输入事件。

-----------------------------

Tips:

1. 调用静态的TouchPanel.GetCapabilities()方法返回TouchPanelCapabilities的可以的到系统的输入能力。

    TouchPanelCapabilities对象中:

           IsConnected表示触摸是否可用。

           MaximumTouchCount表示最多可响应几个触点。

2. 在Update()函数中,调用TouchPanel.GetState()方法来的到TouchCollection对象来的到当前的按键情况。

3. 得到的TouchCollection对象中有0到多个TouchLocation对象,包含单个触点对象的信息。

    TouchLocation对象中:

          TouchLocationState State:Pressed, Moved, Released

          Vector2 Position:表示触点针对左上角的位置

          int id:表示在一次触摸过程中的唯一标识(从按下开始分配这个ID,在抬起事件结束前这个ID不会变)

          bool TryGetPreviousLocation(out TouchLocation)方法,可以得到上一次刷新的触点对象。(可以用来算位移差值,没有上一个位置的话函数会返回false)

    注意:在Pressed事件过后,就算手指没有移动也会接收到Moved事件,直到手指抬起触发Released事件。

            如果点击得特别快在两次刷新之间完成了按下和抬起,是收不到Moved事件的。

            手指这个东东比较粗,有可能你按一下下会产生多个Pressed事件,处理的时候还要考虑按键区域的问题。不要重复计算多个区域的好。

------------------------------

 

二、XNA下的手势接口

这个比刚才那个高级了。

直接利用TouchPanel.EnabledGestures设置你需要监听的手势,然后在Update()中,通过查询属性TouchPanel.IsGestureAvailable,得到当前是否有需要的手势状态并做处理。

------------------------------

Tips:

1. TouchPanel.EnabledGestures可以设置的动作有Tap, DoubleTap, Flick, Hold, Pinch, PinchComplete, FreeDrag, HorizontalDrag, VerticalDrag 和 DragComplete,他们之间可以用与运算连接同时设置多个动作。

2. 在Update()中读取手势的方法:

protected override void Update(GameTime gameTime)
{

    …

    while(TouchPanel.IsGestureAvailable)

    {

          //得到一个动作取样

          GestureSample gestureSample = TouchPanel.ReadGesture();

          if (gestureSample.GestureType == GestureType.Tap)

          {

                //…………………………

          }

          else if (gestureSample.GestureType == ……….)

          {

               //…………………………

          }

    }

}

    注意:手势事件是在确实触发了这种事件后才执行的,因此Tap是在手指离开屏幕才处理的。

            有些手势会有前置动作,GestureSample中的Position2和Delta2就起了作用。

----------------------------

 

三、在Silverlight上的Low-Level触摸事件

在Silverlight上,可以通过静态事件Touch.FrameReported回调事件响应函数。

--------------------------

Tips:

1. 将回调函数添加到事件中。

         Touch.FrameReported += OnTouchFrameReported;
    回调函数的实现类似于:

          void OnTouchFrameReported(object sender, TouchFrameEventArgs args) {
            …

          }

     TouchFrameEventArgs对象中包含:

             GetTouchPoints(refElement) 返回一个 TouchPointCollection(也就是一组TouchPoint,参数传null的话,返回从左上角开始的所有触点内容)
             GetPrimaryTouchPoint(refElement) 返回一个 TouchPoint(第一个触摸事件)
             SuspendMousePromotionUntilTouchUp()禁止该事件被提升为鼠标事件,这个函数可有渊源等下详细介绍。

     GetTouchPoints和GetPrimaryTouchPoint返回的都是和TouchPoint相关的。

     那就先说说TouchPoint对象:

              TouchAction Action:Down, Move, 和 Up.

              Point Position:这个就是针对左上角的坐标了。

              Size Size:触摸的区域大小(在WP7上没啥用)

              TouchDeivce TouchDeivce:这个是个对象里面包含:int Id,从触点按下到抬起的唯一标识。UIElement DirectlyOver,按键底下的控件,也就是谁不幸被点了。

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

void OnTouchFrameReported(object sender, TouchFrameEventArgs args)


     TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);

     //第一个触点,并且是按下事件
     if (primaryTouchPoint != null && primaryTouchPoint.Action == TouchAction.Down) 
     { 
         args.SuspendMousePromotionUntilTouchUp(); 
     }  
     …

}

-----------------------------

 

四、操作事件(The Manipulation Events)

Silverlight的高级操作接口。由三个事件组成ManipulationStart、ManipulationDelta、MannipulationCompleted。

-----------------------------

Tips:

1. 在xaml中,这三个事件可以作为控件的属性添加到控件中。

2. 三个方法ManipulationStart、ManipulationDelta、ManipulationCompleted,分别对应触摸操作的按下,移动,抬起三个事件。并且在出发ManipulationStart事件到ManipulationCompleted结束之间,就算有其他触摸,事件也不会被响应。

3. 在回调中调用args.Complete()方法,会在执行完当前回调后立即触发ManipulationCompleted这个事件。

4. 继承PhoneApplicationPage的窗口可以重载ManipulationStart、ManipulationDelta、ManipulationCompleted这三个方法。注意到在参数对象ManipulationStartedEventArgs args中,args.OriginalSource标志的是页面上触摸的控件。

----------------------------

 

五、操作事件的执行路径

现在,控件上可以有三个操作的回调,页面上可以有三个操作的重载。他们的执行路径会是什么样的呢?

场景:

在Page上有一个TextBlock,现在用户在TextBlock点了一下。

以ManipulationStart事件为例:Silverlight框架会先执行TextBlock上的回调,然后执行Page重载的方法。

但是当执行TextBlock上的回调时,设置了args.Handled为true,这样消息就不会传递给上层Page了。

延伸:

有个比较有意思的事情,TextBlock上的ManipulationStart执行时执行了args.Complete(),并且设置了args.Handled为true,同时不对ManipulationComplete中的args做操作。上层Page收不到OnManipulationStart的事件了,可是可以执行OnManipulationComplete重载。结论是这三个事件之间是并行没有关联的。

其实也好理解,分别实现三个事件比三个事件关联容易多了,框架也更整齐。写Silverlight的人也是参考了一些游戏框架的消息处理机制的。

posted @ 2011-03-19 22:44  摇滚诗人  阅读(474)  评论(0编辑  收藏  举报