1. 程式人生 > >WPF觸控程序開發(二)——整理的一些問題

WPF觸控程序開發(二)——整理的一些問題

不錯 mat 如何判斷 href tar 全局 acc lean font

原文:WPF觸控程序開發(二)——整理的一些問題

  上一篇(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對我來說只是一個黑盒,我能模仿,甚至超越。

WPF觸控程序開發(二)——整理的一些問題