上一篇(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軸位移
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軸每次縮放的比例值。