热卡

迷上一个人,迷上一件事。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  上一篇(WPF触控程序开发)介绍了几个比较不错的资源,比较基础。等到自己真正使用它们时,问题就来了,现把我遇到的几个问题罗列下,大家如有遇到其他问题或者有什么好的方法还望赐教。

  问题1.如何获取触控点的个数

  当你要在单指触屏和多指触屏时分别做不同的处理时就要用到。如何获取,刚开始我是弄个List,在TouchDown时存储输入点,然后TouchUp时移除输入点,这样我要判断输入点的个数时只要获取这个List的Count就行了,这是原始的做法,而且有的时候会不准(原因可能是down和up的事件抛出时机导致的,具体原因没作研究),有个比较简单的做法是在开头引用一下 

using System.Linq ;

ManipulationStarting或者ManipulationDelta里可以使用

int deviceCount = e.Manipulators.Count();

来获取即可。

  问题2.如何判断触控点是否位移

  这个问题也常遇到,情景是在单点抬起和单点移动再抬起做不同的处理,如单点抬起就弹窗,单点移动后抬起做翻页,如何判断呢?其实我上篇也略微提到了,就是定义一个TouchPoint类型的变量

TouchPoint touchPointOld;

TouchDown的时候

touchPointOld  = e.GetTouchPoint(this);

然后在TouchUp的时候获取新点

TouchPoint touchPointNew = e.GetTouchPoint(this);

最后即可判断X轴的位移

double offsetX = touchPointNew.Bounds.Left - touchPointOld.Bounds.Left ;//判断X轴位移
  当然也可以判断Y轴的位移。在这里多说一句,当我们在用鼠标模拟触控测试时,是可以很精准地落下抬起,现实当中的手指落下抬起,虽然用户主观上没有动,实际上可能会有5个像素左右的位移(手指是肉团,没有鼠标那么精细),这时代码就要判定超过5个像素的移动才算手指位移了。
 
  问题3.如何做精准的翻页效果

  WPF的ScrollViewer已经支持触屏了,设置PanningMode属性即可滑动,但是这样滑动是利用了惯性,想要控制精准翻页比较困难。想做到像iphone相册那样的翻页效果,即不管使用多大力气,滑一次只翻一屏,这显然不适用。目前我能想到的是用动画来处理,大致思路是把罗列的对象放置于Canvas里(必须是Canvas,原因后面再说),然后使用DoubleAnimation作用于这个Canvas的TranslateTransform.XProperty,为避免生硬地滑动,可以设置DoubleAnimation的AccelerationRatio和DecelerationRatio,这样能有加速和减速的效果。每次手指放下记录点,抬起后判断位移趋势是左移还是右移,然后执行相应的动画,当然,每次滑动多少就要自己计算了。

  上面说到了一定要使用Canvas,当然你也可以用Gird、StackPanel等等、不过你会发现,只要执行移动动画,整个容器就会从你的视线消失。这可能与容器的特性有关,当你设置容器的宽度后(假设是水平滑动),执行动画,改变TranslateTransform.XProperty,容器好像不是按照你的原来意思来滑动,而是把初始化的时候显示的部分整体移动了,不管你设的宽度为多少,而Canvas则会像一张很长的画布一样慢慢展开。这个现象很容易重现,在blend里随意试一下,设置容器转换的X值(其实就是TranslateTransform.XProperty),你会很清晰得看到全过程。

  问题4.如何做图片的平移、缩放、旋转

  我认为这可以算触控开发的进阶了。因为这个涉及到操作一个原始的结构体——UI的Matrix。当然你想简单做做的话直接用Blend自带的TranslateZoomRotateBehavior就行,不过使用这个的话就相当于完全托管了,你能控制的东西很少。所以还是要直接操作Matrix。关于Matrix的介绍这里有个资源可以参考一下:WPF中的MatrixTransform

  不必研究很深入,你只需要知道Matrix有6个值,分别是M11,M12,M21,M22,OffsetX,OffsetY,其中M11和M22分别管的X轴和Y轴的缩放,OffsetX对应X轴位移,OffsetY对应Y轴位移,还有ScaleAt方法(缩放),Translate方法(平移),RotateAt方法(旋转),看他们的传入参数,基本都可以从e获取,如ScaleAt方法需要四个参数:

public void ScaleAt (double scaleX, double scaleY , double centerX , double centerY );

一般做平移、旋转、缩放的时候是写在ManipulationDelta里面,前面两个参数就可以从e的DeltaManipulation属性获得,为Scale.X和Scale.Y,后面两个参数就更简单了,是操作的中心点,也可以从e获得,ManipulationOrigin属性即为中心点,直接把他的X和Y传入就行。

  还要多说一句,这里的Matrix改变后,并不影响UI的Width或者ActualWidth,如果想要获取这类的值,需要计算。有这样的情景,我需要在缩放到某个尺寸后就不让继续缩放了,这时候你去获取UI的Width或者ActualWidth根本没用,因为这些值一直没变过。我的做法是定义全局变量,每次ManipulationDelta里改变的时候,就计算缩放后的新值,以此来记录当前缩放状态。其中ManipulationDelta的Scale.X就是X轴每次缩放的比例值。

  懂了这些,我认为已经算入门了。不过我也研究过iphone相册的效果,它好像不是我这样的思路。首先,它的滑动是实时跟随的,当然我也可以做到那样的效果;其次它的黑边处理,是等宽填充,即不管相片多宽多高,宽度是始终充满屏幕的,当你滑动时,不仅当前图片跟随移动,紧挨着的图片也会受影响,而我的只是处理当前的对象,并未去影响其他的。这也可能是操作系统的区别吧,IOS没研究过,说不定它是一个封好的控件,任何对象放进去就会有这样的效果。我看了新浪、QQ的IOS客户端,里面的图片展示都是这样的效果,看起来好容易。不过我相信,任何的效果都是代码实现的,看起来越简单,其实实现过程并不是那么简单。IOS对我来说只是一个黑盒,我能模仿,甚至超越。
posted on 2014-04-17 14:40  热卡  阅读(3850)  评论(3编辑  收藏  举报