標籤:
這是我們在實際項目中經常要面臨的問題,因為你很可能會出現這種需求:單手操作與雙手操作的行為不同,在手勢開始之時就需要知道到底是單手還是雙手。
方案一:
瞭解了這個需求之後,我迅速憑藉經驗,感覺在ManipulationStarting或者ManipulationStarted事件傳入的參數中應該類似於e.GetPointers()類似的方法,用於獲得當前有多少個手指在螢幕上。感覺三年的Windows 開發經驗終於有了點小用,節省了我好多效率不免心生有預感。。。但是當尋找了半天之後,胸中頓時有幾萬隻草泥馬奔騰而過,不是說的是底層事件嗎?底層事件連最簡單的判斷有幾個手指頭都不行麼?TouchFrame才叫底層事件好嗎???
public class ManipulationStartedRoutedEventArgs : RoutedEventArgs, IManipulationStartedRoutedEventArgs { public ManipulationStartedRoutedEventArgs(); public UIElement Container { get; } public ManipulationDelta Cumulative { get; } public System.Boolean Handled { get; set; } public PointerDeviceType PointerDeviceType { get; } public Point Position { get; } public void Complete(); }
各位請看,我不會冤枉好人的,根本就沒有一個集合性的東西,這個Point倒是手指在螢幕上的接觸點,但是這都是Started事件了好嗎?我要的是在Started之前就知道有幾個手指頭跟螢幕接觸好嗎?
方案二:
抱著”微軟虐我千百遍,我待微軟如初戀"的心態,我繼續尋找方案二。心想:如果我能獲得這個容器,甚至我擷取這個App所在的Frame,應該有暴露方法判斷有多少個手指吧。具體的過程我就不說了,神馬UIElement,Control,Frame,都沒有啊,都沒有。
方案三:
抱著“人在屋簷下,不得不低頭”的心態,我繼續尋找方案三,(畢竟技術是你微軟的,項目是我的,還得繼續啊,一萬隻草泥馬又呼嘯而來。。。),去MSDN上面扒了扒跟輸入相關的知識點,終於發現了一個東西,並且是一個比較熟悉的東西:PointerPressed,中級事件,這個事件我們上篇已經做過實驗了,它會在ManipulationStarting之前觸發,就是說,如果我在這個事件觸發之時,能擷取手指的個數,那我就能解決這個問題了!(https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj150606.aspx, 這篇文章詳細介紹了Pointer相關的知識,有興趣的朋友可以去看看,草泥馬統統不見了,前途一片光明啊,哈哈哈)
可以這麼說,每一次點擊都會觸發一次PointerPressed事件,並且這個事件帶來的參數能夠獲得接觸點的資訊,這個資訊包含了PointerID,就是說,每一次點擊,系統會標識這個接觸點,鬆開後系統回收這個標記,那麼我們本地可以實現一個字典,以PointerID為key,對應的Pointer為Value,那麼在OnManipulationStarting事件中我就能判斷是幾個手指啦,說幹就幹
private Dictionary<uint, Point?> _contacts; //與螢幕接觸的點的集合 /// <summary> /// 手指按下 /// </summary> /// <param name="e"></param> protected override void OnPointerPressed(PointerRoutedEventArgs e) { //if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse) //{ _contacts[e.Pointer.PointerId] = e.GetCurrentPoint(this).Position; //} e.Handled = true; } /// <summary> /// 手指離開 /// </summary> /// <param name="e"></param> protected override void OnPointerReleased(PointerRoutedEventArgs e) { //if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse) //{ if (_contacts.ContainsKey(e.Pointer.PointerId)) { _contacts[e.Pointer.PointerId] = null; _contacts.Remove(e.Pointer.PointerId); } //} e.Handled = true; } /// <summary> /// 手指放上只會出發starting事件,要移動才開始觸發started事件 /// </summary> /// <param name="e"></param> protected override void OnManipulationStarted(ManipulationStartedRoutedEventArgs e) { int count = _contacts.Count; if (count == 1) {// 如果這時手指只有一根,則認為在對比模式 _viewController.OnManipulationStarted(e); } else if (count > 1) {// 如果手指超過一根,則認為在縮放模式下 e.Handled = true; } }
哇哈哈哈哈,到了這個時候,功能做完了,是時候回過頭來看看,為什麼ManipulationStarting不能提供GetPoints()的方法。從實驗的結果來看,ManipulationStarting應該還是只針對單次操作來說的,又或者說,ManipulationStarting只是一個“預備”的動作,並不能做很多事情。但是ManipulationDelta又可以判斷雙手操作中的:Scale,額,這個要在以後慢慢琢磨了。
如果你也遇到了在操作之前判斷手指的情況,這篇文章對你應該會有協助。
手勢部分就到此,因為我在項目中也僅僅遇到了這些問題,不排除後續還有更複雜的情況出現,或者又擴充了很多其他問題。
Windows 10 開發日記(三)-- 如何在手勢開始之前判斷手指數量