欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    iamondTouch是一種多用戶觸摸技術(shù),適用于桌面環(huán)境和前投顯示器。它可以實現(xiàn)多個用戶同時在同一個觸摸表面上進(jìn)行操作,而彼此之間不會相互干擾,也不會受到異物的影響。此外,DiamondTouch還能夠識別哪個用戶正在觸摸表面的哪個位置。

    有人構(gòu)建了一個協(xié)作工作空間,多個用戶可以在其中共同使用數(shù)據(jù)集。該環(huán)境包括一個安裝在天花板上的視頻投影儀,將內(nèi)容顯示在一張白色桌子上,用戶可以坐下操作。每個用戶還配備了一個無線鼠標(biāo)作為輸入設(shè)備。

    通過讓用戶獨立地同時與桌面進(jìn)行互動,并考慮使用多只鼠標(biāo),可以改善協(xié)作效果。然而,在協(xié)作環(huán)境中使用多只鼠標(biāo)存在一些問題。用戶可能會面臨跟蹤指針在大型表面上的挑戰(zhàn)。跟蹤多只鼠標(biāo)幾乎是不可能的,這使得用戶無法準(zhǔn)確地告知其他用戶他們所指向的位置。

    此外,依賴于單一的物理設(shè)備也無法充分利用人類的自然傾向,例如伸手、觸摸和抓握動作。使用大型觸摸屏作為桌面解決方案看起來是一個答案,但現(xiàn)有的觸摸技術(shù)還不足以滿足需求,大多數(shù)只允許單點觸摸且無法識別用戶。

    而DiamondTouch技術(shù)具有多點觸摸、用戶識別、抗干擾、耐用性、無需額外設(shè)備和低成本制造的特點可以解決上述問題。

    多用戶觸摸技術(shù)原理

    DiamondTouch是一種通過傳輸不同的電信號來工作的技術(shù)。它向桌面的每個部分發(fā)出獨特的信號以進(jìn)行確認(rèn)。當(dāng)用戶觸摸桌子時,信號從觸摸點正下方進(jìn)行電容耦合,并通過用戶進(jìn)入與該用戶相關(guān)聯(lián)的接收器單元。

    然后,接收器可以確定用戶正在觸摸桌面的哪些部分。這種方式可以實現(xiàn)多點觸控,使系統(tǒng)能夠檢測和跟蹤多個用戶在桌面上的觸摸位置和動作。桌面是使用一組嵌入式天線構(gòu)建的,可以具有任意形狀和大小。

    這些天線是由導(dǎo)電材料制成的薄片,并且彼此之間被絕緣隔離。由于向用戶發(fā)送的信號是電容耦合的,天線也與用戶絕緣,整個桌面覆蓋著一層絕緣保護(hù)材料,如圖1所示。每個天線延伸到一個特定區(qū)域,以明確標(biāo)識出其位置。

    圖1

    系統(tǒng)無法區(qū)分用戶觸摸天線的具體位置,即用戶觸摸的天線。發(fā)射器單元通過驅(qū)動每個天線發(fā)送自己的信號,可以通過信號的特征來區(qū)分每個天線。用戶通過他們的椅子與天線發(fā)生電容耦合,并且接收器通過共享的電氣接地參考返回到發(fā)射器。

    當(dāng)用戶觸摸桌子時,電容耦合電路就會完成連接。該電路從發(fā)射器開始,通過桌面上的觸摸點傳輸,然后通過用戶到達(dá)用戶的接收器,并返回到發(fā)射器。

    通過適當(dāng)?shù)脑O(shè)計,人體的電容耦合可以非常可靠地實現(xiàn)。首先要考慮的是使用"近場"即電容耦合進(jìn)行操作。通過限制發(fā)射頻率,使得整個系統(tǒng)的尺寸相比波長非常小,輻射的能量非常少。

    這減少了射頻干擾和不需要的天線之間的耦合問題。對于適當(dāng)大小的桌子,頻率應(yīng)在亞兆赫范圍內(nèi)。由于用戶可能同時觸摸多個天線,因此接收器的能力來區(qū)分和區(qū)分天線是非常重要的,以識別輸入信號的任何混合。

    為了實現(xiàn)這一點,使用了一種信號處理術(shù)語中稱為"可分離的"或"相互正交的"的信號。有多種方法可以生成這樣的信號。

    例如,可以使用不同頻率的正弦波來驅(qū)動每個天線。通過檢查接收信號的頻譜,耦合到多個天線的接收器可以確定它們來自哪些天線。然而,生成大型陣列所需的許多頻率是復(fù)雜且相對昂貴的。

    時分復(fù)用是另一種選擇。在這種情況下,每個天線被逐個驅(qū)動,而其他天線則不被驅(qū)動。接收器根據(jù)接收時間信號來確定哪些天線與之相連。盡管這種系統(tǒng)的實施非常簡單,但它可能不適用于較大的陣列。

    這是由于各種制約因素的相互作用。為了提供良好的響應(yīng)時間,整個陣列必須以每秒10到100次的速率進(jìn)行掃描。然而,實際可用的調(diào)制頻率受限于亞兆赫范圍,這導(dǎo)致每個天線的調(diào)制周期非常短,使得接收機設(shè)計變得非常困難,特別是在面對其他干擾噪聲源時。

    另一種構(gòu)建一組正交信號的方法是碼分復(fù)用,這是一種擴頻技術(shù)。事實上,對于大型陣列來說,這是一種特別優(yōu)雅的方法,因為可以使用非常簡單的硬件操作(如移位、XOR等)來生成擴展碼序列。

    簡單的硬件甚至可以級聯(lián),以實現(xiàn)更大規(guī)模的觸摸設(shè)備。擴頻方法實際上提供了大型陣列的顯著信噪比增益。

    正如之前提到的,嵌入在桌面上的天線可以具有任意形狀和大小。設(shè)計師可以選擇實現(xiàn)幾個大的"按鈕"或者更復(fù)雜的天線陣列。然而,一個通用且可配置的解決方案比特定設(shè)計的硬件更可取。

    最通用的解決方案是使用"全矩陣"模式,其中大量的天線被排列成一個矩形網(wǎng)格。

    這樣,通過單獨驅(qū)動每個天線的矩陣"像素",可以明確地確定多個觸摸位置,即使對于單個用戶也是如此。然而,這種模式也是制造最困難的,因為它需要大量的連接和相應(yīng)的支持電路。實際上,并不是每個應(yīng)用程序都需要矩陣模式。

    雖然同步和多用戶功能是必不可少的,但對于大多數(shù)應(yīng)用程序,每個用戶最多指示一個觸摸點或邊界框已足夠。這種功能可以通過簡單的行/列模式實現(xiàn),大大減少了所需的天線數(shù)量。

    行和列通常位于不同的層上。由于屏蔽效應(yīng),創(chuàng)建良好的行/列天線方向圖有一些微妙之處。簡單的上層矩形列圖案會覆蓋和重疊太多的較低等效行集層。這將減小通過的面積,使行無法很好地電容耦合信號,從而削弱其靈敏度。

    良好的天線方向圖將最小化行和列的重疊區(qū)域,同時最大化它們的總面積,連接成菱形圖案(如圖2所示)是一個不錯的選擇。這個圖案具有行導(dǎo)線和列導(dǎo)線相同的有趣特性,只是旋轉(zhuǎn)了90度。使用相同的導(dǎo)線圖案來驅(qū)動行和列,從而節(jié)省了制造時間和成本。

    圖2

    在使用中,觸摸很可能會跨越多行和具有不同的列耦合度。接收到的信號強度可用于估計觸摸的質(zhì)心,從而獲得比行和列更精細(xì)的定位。然而,使用這些信息的另一種方法是為觸摸事件呈現(xiàn)一個邊界框,由最外層具有顯著耦合的行和列定義。

    這導(dǎo)致了有趣的使用方式-單個用戶可以觸摸兩個點來定義邊界框。這是一種非常自然的選擇矩形區(qū)域的方式。

    當(dāng)耦合區(qū)域較小時,假設(shè)用戶表示一個點;當(dāng)它跨越較大區(qū)域時,假設(shè)用戶試圖指定一個邊界框。最終結(jié)果是,即使是這種簡化的行/列設(shè)計,也可以實現(xiàn)一些單個用戶的多點觸控功能。

    多用戶觸摸技術(shù)原型

    測試了一個小型的DiamondTouch原型的概念(如圖3所示)。該原型具有一個約20厘米x20厘米的活動區(qū)域,包含了80個排列的天線,分為40行和40列。天線陣列被設(shè)計成印刷在0.5毫米厚的雙面電路板上,具體取決于其旋轉(zhuǎn)方向。

    圖3

    為了將天線陣列夾在一起,電路板被夾在堆疊的行板和列板之間,中間有一個非常薄的絕緣體,使其與表面幾乎沒有區(qū)別,只是厚度不同。

    天線陣列由發(fā)射器板(如圖4所示)驅(qū)動。實現(xiàn)了時分復(fù)用,即每個天線依次用10kHz方波驅(qū)動10個周期。盡管該板可以以60伏的振幅驅(qū)動天線,但5伏的電壓就足夠了。使用更高的電壓可以產(chǎn)生更好的信噪比,這在電磁噪聲環(huán)境中非常有用。

    圖4

    接收器通過屏蔽電纜連接到軟墊,軟墊被用作將用戶與接收器耦合的金屬椅。幾乎任何導(dǎo)電的椅子都可以用于這個應(yīng)用,只要在乘員和接收器電纜之間有足夠的電容耦合。

    如果使用非導(dǎo)電的椅子,可以使用導(dǎo)電的"緩沖墊"(一層金屬箔,也可以用于舒適填充)來將用戶與接收器耦合。

    (圖5)顯示了其中一個原型接收器。為了獲得最大的抗噪性,接收器使用同步解調(diào),因此需要適當(dāng)?shù)耐叫盘杹碜园l(fā)射器板。接收器將結(jié)果數(shù)字化,并以原始形式通過快速RS-232串行傳輸?shù)竭B接的計算機。

    圖5

    每個用戶都有一個獨立的接收器板。整個表每秒掃描75次,計算機接收每一行和每一列的每個用戶的耦合值。75Hz的更新速率和可忽略的延遲使得原型非常敏感。

    當(dāng)接收到足夠高的信號時,表面被認(rèn)為被"觸摸"。理論上,可以使用一個簡單的閾值來確定這一點。然而,考慮到組件漂移、用戶變化和不同的噪聲水平,采用基于閾值的方法更為實用,即基于當(dāng)前對最小耦合和噪聲水平的估計。

    這種方法效果令人滿意,但更復(fù)雜的方法可能會產(chǎn)生更好的結(jié)果,特別是在靜電噪聲較大的情況下,如橡膠腳椅子拖過地毯時。

    發(fā)送器和接收器板都使用了PIC微控制器和其他廉價的現(xiàn)成電子元件。最昂貴的部件是印刷在桌子上的電路板,這在批量生產(chǎn)的產(chǎn)品中會更便宜。

    編寫的測試軟件,可以為每一行和每一列以及每一位生成耦合級別的條形圖,并用不同顏色表示每個用戶。計算得出的觸摸點以圖形方式顯示,小觸摸區(qū)域顯示為十字光標(biāo),較大的觸摸區(qū)域顯示為邊界框。

    盡管普通物體不會對桌子產(chǎn)生影響,但可以設(shè)計特殊的物體來影響桌子,這對于使用有形和可抓取的應(yīng)用程序來說非常有用,這些應(yīng)用程序?qū)⑦@些特殊物體作為其用戶界面的一部分。

    由于天線陣列和用戶之間存在絕緣層,用戶不需要具備任何特殊特性,因此可以使用多種材料來制造桌子,使其在不同的環(huán)境條件下都能保持堅固。

    例如,玻璃或塑料可用于使桌子抗液體和化學(xué)品泄漏。原型是使用一種名為GML1000的玻璃纖維層壓板制造的,其熱性能關(guān)系允許在臨時操作桌子時(而且沒有損壞),表面被酒精覆蓋。

    多用戶觸摸技術(shù)總結(jié)

    電阻式和電容式觸摸屏已經(jīng)銷售幾十年了,但它們?nèi)菀资艿蕉啻斡|摸的干擾。對于對壓力敏感的應(yīng)用而言,無法容忍任何殘留物在其上。

    超聲波系統(tǒng)最近在創(chuàng)建電子白板方面變得流行。然而,它們需要主動筆筒,一般不支持多點觸控。此外,較大的碎片對象可能會造成陰影,降低性能。

    Wacom Intuos圖形輸入板是一種支持多點觸控和識別所用工具的系統(tǒng)。它具有名為"雙軌"的功能,允許同時使用兩個工具(如手寫筆或鼠標(biāo))。不幸的是,Intuos更小更貴,且僅限于兩點觸控。

    其他無法識別用戶的多點觸控系統(tǒng)包括FingerWorks FingerBoard和Tactex smart織物技術(shù)。盡管FingerBoard尚未發(fā)行,但似乎使用了二維數(shù)組電容傳感器來獲取放置在其上的物體的二維圖像。Tactex技術(shù)則通過感應(yīng)壓力對材料光學(xué)特性的變化進(jìn)行檢測。

    已經(jīng)設(shè)計了一些基于光學(xué)的輸入系統(tǒng),用于跟蹤手或其他物體周圍的二維區(qū)域。全息墻使用相機和紅外線照明來尋找附近的物體,而Strickon和Paradiso使用掃描激光測距儀在自由空間中進(jìn)行類似的工作。

    這兩種系統(tǒng)都可以感知多個觸摸,但無法輕松區(qū)分不同的用戶。

    近場電場(電容)傳感器已經(jīng)用于簡單應(yīng)用,例如觸摸開關(guān),幾十年了。最近幾年,用戶界面社區(qū)引入了更精細(xì)制作的電容感應(yīng)形式。這些系統(tǒng)試圖檢測手或其他物體與電極之間的距離,然后使用場強來確定位置。

    DiamondTouch與其他技術(shù)的不同之處在于,它要求被感應(yīng)的物體非常接近(毫米或更小)的電極,但使用大量的電極來感知位置。

    DiamondTouch多用戶觸摸技術(shù)可以檢測多個點同時觸摸,并能識別哪個用戶觸摸了每個點。它的設(shè)計主要考慮了表面上留下的物體對其性能的影響,并且非常耐用。整個系統(tǒng)的制造成本也相對較低,而且沒有手寫筆容易丟失的問題。

    參考文獻(xiàn):Dietz, Paul H. and Darren Leigh. “DiamondTouch: a multi-user touch technology.” ACM Symposium on User Interface Software and Technology (2001).


    對于Android自定義控件開發(fā),多點觸控是一個必須要懂的知識點。因為在正常的情況下操作正常的控件,使用多指操作時,基本上都會出現(xiàn)問題。當(dāng)需要對多指操作進(jìn)行兼容時,就需要這方面的知識了。

    本文選自《Android自定義控件高級進(jìn)階與精彩實例》一書,帶你了解多點觸控的基本知識。


    —— 正文 ——

    假如,我們做了這么一個功能,圖像跟隨手指移動。

    在單指操作下,圖像的移動非常流暢、正確,而如果我們使用兩根手指的話,就會出現(xiàn)下面這種情況。

    從效果圖可以看出,在第2根手指放下,而第1根手指抬起時,圖像會出現(xiàn)跳躍,直接從第1根手指的位置移動到了第2根手指的位置,這明顯是不對的。這只是一個簡單的例子,一般使用單指操作的控件改到多指操作的時候,都會出現(xiàn)問題。

    這便是本文講解多點觸控的初衷。既然多點觸控會造成這么多問題,那么下面就來詳細(xì)了解它吧。

    單點觸控與多點觸控


    1
    單點觸控

    單點觸控與多點觸控是相對的,單點觸控的意思是,我們只考慮一根手指的情況,而且僅處理一根手指的觸摸事件,而多點觸控是處理多根手指的觸摸事件。

    一般我們處理MotionEvent事件,通過MotionEvent.getAction來獲取事件類型,這就是單點觸控。在單點觸控中,會涉及對下面幾個消息的處理。

    除了消息外,我們也經(jīng)常用下面這幾個函數(shù)來獲取手指的位置等信息,這些函數(shù)都沒有參數(shù),也都只有在單點觸控時才能使用。

    對于這幾個函數(shù)的使用方法,這里就不再贅述了。可以看到,我們平常所處理的MotionEvent事件,以及常用的MotionEvent函數(shù)都只是針對單點觸控的,那么哪些才是多點觸控的事件和函數(shù)呢?

    2
    多點觸控

    首先,多點觸控的消息類型只能通過getActionMasked來獲取。因此,判斷當(dāng)前代碼處理的是單點觸控還是多點觸控,單從獲取消息類型的函數(shù)就可以看出。

    說明:單點觸控是通過getAction來獲取當(dāng)前事件類型的,而多點觸控是通過getActionMasked來獲取的。

    多點觸控涉及的消息類型與單點觸控的不一樣,它的消息類型如下。

    比如以下圖中的手指按下順序,我們來看看其中的事件觸發(fā)順序。

    在效果圖中,先后有3根手指按下,按下順序是1、2、3,抬起順序是1、3、2,而事件觸發(fā)順序如下表。

    這里需要注意,

    第1根手指按下時,收到的消息是ACTION_DOWN;

    隨后的手指再按下時,收到的是ACTION_POINTER_DOWN

    當(dāng)有手指抬起時,收到的是ACTION_POINTER_UP;

    當(dāng)最后一根手指抬起時,收到的是ACTION_UP。

    對多點觸控消息進(jìn)行處理的代碼如下:

     1String TAG = "qijian";
     2@Override
     3public boolean onTouchEvent(MotionEvent event) {
     4    switch (event.getActionMasked()) {
     5    case MotionEvent.ACTION_DOWN:
     6        Log.e(TAG,"第1根手指按下");
     7        break;
     8    case MotionEvent.ACTION_UP:
     9        Log.e(TAG,"最后一根手指抬起");
    10        break;
    11    case MotionEvent.ACTION_POINTER_DOWN:
    12        Log.e(TAG,"又一根手指按下");
    13        break;
    14    case MotionEvent.ACTION_POINTER_UP:
    15        Log.e(TAG,"又一根手指抬起");
    16        break;
    17    }
    18    return true;
    19}
    20...
    21    }

    這里僅列出了手指按下和手指抬起所觸發(fā)的消息類型,而在手指移動時,無論是單點觸控還是多點觸控,所觸發(fā)的消息都是MotionEvent.ACTION_MOVE

    在多點觸控時,我們可以通過代碼來獲取當(dāng)前移動的是哪根手指。


    多點觸控


    1
    識別按下的手指

    上面講解了在什么情況下會觸發(fā)什么消息,但我們怎么來識別當(dāng)前按下的是哪根手指呢?

    在MotionEvent中有一個Pointer的概念:

    一個Pointer就代表一個觸摸點,每個Pointer都有自己的消息類型,也有自己的X坐標(biāo)值。一個MotionEvent對象中可能會存儲多個Pointer的相關(guān)信息,每個Pointer都有自己的PointerIndex和PointerId。在多點觸控中,就是用PointerIndex和PointerId來標(biāo)識用戶手指的。

    • PointerIndex表示當(dāng)前手指的索引,PointerId是手指按下時分配的唯一id,用來標(biāo)識這根手指。
    • 每根手指從按下、移動到離開屏幕,PointerId是不變的,而PointerIndex則不是固定的。

    通過下面這個例子,我們來了解一下PointerIndex與PointerId的區(qū)別。

    可見同一根手指的id是不變的,而PointerIndex是會變化的,但總是以0、1或者0、1、2這樣的形式出現(xiàn),而不可能出現(xiàn)0、2這樣間隔了一個數(shù)或者1、2這種沒有0索引值的形式。

    針對PointerIndex與PointerId,在MotionEvent類中經(jīng)常使用下面這幾個函數(shù)。

    • public final int getActionIndex:

    用于獲取當(dāng)前活動手指的PointerIndex值。

    • public final int getPointerId(int pointerIndex):

    用于根據(jù)PointerIndex值獲取手指的PointerId,其中pointerIndex表示手指的PointerIndex值。

    • public final int getPointerCount:

    用于獲取用戶按下的手指個數(shù),一般我們用它來遍歷屏幕上的所有手指,遍歷手指的代碼如下:

    1for (int i = 0; i < event.getPointerCount(); i++) {
    2    int pointerId = event.getPointerId(i);
    3}

    前面講過,PointerIndex是從0開始的,表示當(dāng)前所有手指的索引,值從0到getPointerCount() ? 1,不會出現(xiàn)不連續(xù)的數(shù)。因此,我們通過event.getPointerCount可以得到當(dāng)前屏幕上的手指個數(shù)。然后從0開始遍歷PointerIndex,同時我們還能通過int pointerId = event.getPointerId(i)來得到每根手指PointerIndex所對應(yīng)的PointerId。

    • public final int findPointerIndex(int pointerId):

    用于根據(jù)PointerId反向找到手指的PointerIndex值。

    由此,我們就知道了PointerIndex與PointerId的關(guān)系,以及它們相互之間的換算方法。下面再來看看通過PointerIndex和PointerId能得到什么。

    2
    獲取手指位置信息

    通過PointerIndex與PointerId,可以使用以下函數(shù)獲得手指的位置信息。

    • public final float getX(int pointerIndex):

    根據(jù)PointerIndex得到對應(yīng)手指的X坐標(biāo)值,該函數(shù)的意義與單點觸控里的getX函數(shù)相同。

    • public final float getY(int pointerIndex):

    同樣地,根據(jù)PointerIndex得到對應(yīng)手指的Y坐標(biāo)值,該函數(shù)的意義與單點觸控里的getY函數(shù)相同。


    實例:追蹤第2根手指


    現(xiàn)在,我們將通過一個實例來學(xué)習(xí)上面講到的函數(shù)。

    這里實現(xiàn)的效果是:當(dāng)用戶按下第2根手指時,就開始追蹤這根手指,無論其他手指是否抬起,只要這根手指沒有抬起,就一直顯示這根手指的位置,如下如。

    從效果圖可以看出,先后總共按下了3根手指,分別在左(第1根手指)、中(第2根手指)、右(第3根手指)。

    抬起手指時,先抬起左側(cè)第1根手指,然后抬起右側(cè)第3根手指。可以看到,第2根手指的觸摸點,我們使用白色圓圈顯示,無論第3根手指是否按下,還是其他手指是否抬起,白色圓圈總是跟著第2根手指的移動來顯示。這就實現(xiàn)了跟蹤第2根手指軌跡的效果。

    下面我們來看看這個效果是怎么實現(xiàn)的吧。

    1
    自定義View并初始化

    布局很簡單,就是一個全屏View,為了在View上畫圓圈,我們必須自定義View,其中的初始化代碼如下:

     1public class MultiTouchView extends View {
     2    // 用于判斷第2根手指是否存在
     3    private boolean haveSecondPoint = false;
     4    // 記錄第2根手指的位置
     5    private PointF point = new PointF(0, 0);
     6    private Paint mDefaultPaint = new Paint();
     7
     8    public MultiTouchView(Context context) {
     9        super(context);
    10        init();
    11    }
    12
    13    public MultiTouchView(Context context, @Nullable AttributeSet attrs) {
    14        super(context, attrs);
    15        init();
    16    }
    17
    18    public MultiTouchView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    19        super(context, attrs, defStyleAttr);
    20        init();
    21    }
    22
    23    private void init() {
    24        mDefaultPaint.setColor(Color.WHITE);
    25        mDefaultPaint.setAntiAlias(true);
    26        mDefaultPaint.setTextAlign(Paint.Align.CENTER);
    27        mDefaultPaint.setTextSize(30);
    28    }
    29}

    這樣我們就自定義了一個View,很明顯它內(nèi)部不會再包裹其他的View控件,所以繼承自View類即可。

    我們定義了3個變量,其中:

    • haveSecondPoint用于判斷第2根手指是否按下。
    • point用于記錄第2根手指的位置。
    • mDefaultPaint是畫筆變量,用于畫第2根手指位置處的白色圓圈。

    2
    onTouchEvent

    然后,在用戶按下手指時,需要加以判斷,當(dāng)前是第幾根手指,然后獲取第2根手指的位置,下面列出完整代碼:

     1public boolean onTouchEvent(MotionEvent event) {
     2    int index = event.getActionIndex();
     3
     4    switch (event.getActionMasked()) {
     5    case MotionEvent.ACTION_POINTER_DOWN:
     6        if (event.getPointerId(index) == 1) {
     7            haveSecondPoint = true;
     8            point.set(event.getX(), event.getY());
     9        }
    10        break;
    11    case MotionEvent.ACTION_MOVE:
    12        try {
    13            if (haveSecondPoint) {
    14                int pointerIndex = event.findPointerIndex(1);
    15                point.set(event.getX(pointerIndex), event.getY(pointerIndex));
    16            }
    17        } catch (Exception e) {
    18            haveSecondPoint = false;
    19        }
    20        break;
    21    case MotionEvent.ACTION_POINTER_UP:
    22        if (event.getPointerId(index) == 1) {
    23            haveSecondPoint = false;
    24        }
    25        break;
    26    case MotionEvent.ACTION_UP:
    27        haveSecondPoint = false;
    28        break;
    29    }
    30
    31    invalidate();
    32    return true;
    33}

    獲取當(dāng)前活動手指的PointerIndex值:

    1int index = event.getActionIndex();
    

    我們知道,當(dāng)?shù)?根手指按下的時候觸發(fā)的是ACTION_DOWN消息,隨后的手指按下的時候觸發(fā)的都是ACTION_POINTER_DOWN消息。因為我們要跟蹤第2根手指,所以這里只需要識別ACTION_POINTER_DOWN消息即可:

    1case MotionEvent.ACTION_POINTER_DOWN:
    2    if (event.getPointerId(index) == 1) {
    3        haveSecondPoint = true;
    4        point.set(event.getX(), event.getY());
    5    }
    6    break;
    

    我們也知道PointerIndex是變化的,而PointerId是不變的,PointerId根據(jù)手指按下的順序從0到1逐漸增加。因此,第2根手指的PointerId就是1。當(dāng)(event.getPointerId(index) == 1時,就表示當(dāng)前按下的是第2根手指,將haveSecondPoint設(shè)為true,并將得到的第2根手指的位置設(shè)置到point中。

    到這里,大家可能會產(chǎn)生疑問,上面提到的多點觸控獲取手指位置都用的是event.getX(pointerIndex),而這里怎么直接用event.getX了呢?其實這里使用event.getX (pointerIndex)也是可以的,大家可以先記下這個問題,后面我們再詳細(xì)講解。

    當(dāng)手指移動時,會觸發(fā)ACTION_MOVE消息:

     1case MotionEvent.ACTION_MOVE:
     2    try {
     3        if (haveSecondPoint) {
     4            int pointerIndex = event.findPointerIndex(1);
     5            point.set(event.getX(pointerIndex), event.getY(pointerIndex));
     6        }
     7    } catch (Exception e) {
     8        haveSecondPoint = false;
     9    }
    10    break;

    需要注意,因為這里使用event.findPointerIndex(1)來強制獲取PointerId為1的手指PointerIndex,在異常情況下可能出現(xiàn)越界,所以使用try…catch…來進(jìn)行保護(hù)。

    在這里,我們使用event.getX(pointerIndex)來獲取指定手指的位置信息。同樣地,這個問題也放在后面講解。

    當(dāng)手指抬起時,會觸發(fā)ACTION_POINTER_UP消息:

    1case MotionEvent.ACTION_POINTER_UP:
    2    if (event.getPointerId(index) == 1) {
    3        haveSecondPoint = false;
    4    }
    5    break;

    同樣地,使用event.getPointerId(index)來獲取當(dāng)前抬起手指的PointerId,如果是1,那就說明是第2根手指抬起了,這時就把haveSecondPoint設(shè)為false。

    當(dāng)全部手指抬起時,會觸發(fā)ACTION_UP消息:

    1case MotionEvent.ACTION_UP:
    2    haveSecondPoint = false;
    3    break;

    在最后一根手指抬起時,把haveSecondPoint設(shè)為false,白色圓圈從屏幕上消失。

    最后,調(diào)用invalidate();來重繪界面。

    3
    onDraw

    在重繪界面時,主要是在point中存儲的第2根手指的位置處畫一個白色圓圈:

     1protected void onDraw(Canvas canvas) {
     2
     3    canvas.drawColor(Color.GREEN);
     4    if (haveSecondPoint) {
     5        canvas.drawCircle(point.x, point.y, 50, mDefaultPaint);
     6    }
     7
     8    canvas.save();
     9    canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
    10    canvas.drawText("追蹤第2個按下手指的位置", 0, 0, mDefaultPaint);
    11    canvas.restore();
    12}
    

    首先,為整個屏幕繪一層綠色,把上一屏的內(nèi)容清掉:

    1canvas.drawColor(Color.GREEN);

    然后,如果第2根手指按下了,則在它的位置處畫一個圓圈:

    1if (haveSecondPoint) {
    2    canvas.drawCircle(point.x, point.y, 50, mDefaultPaint);
    3}
    

    最后,在布局的中間位置寫上提示文字:

    1canvas.save();
    2canvas.translate(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
    3canvas.drawText("追蹤第2個按下手指的位置", 0, 0, mDefaultPaint);
    4canvas.restore();
    

    有關(guān)Canvas的操作及寫字的操作,在《Android自定義控件開發(fā)入門與實戰(zhàn)》一書中有詳細(xì)章節(jié)講述,這里就不再贅述了。

    在寫好控件以后,直接利用XML引入布局即可,這里不再展示,效果就是我們想要的樣子。

    關(guān)于作者

    啟艦

    本名張恩偉,Android研發(fā)專家、CSDN博客專家、CSDN博客之星,《Android自定義控件入門與實戰(zhàn)》《Android自定義控件高級進(jìn)階與精彩實例》作者,電子工業(yè)出版社博文視點優(yōu)秀作者,曾就職于阿里巴巴,現(xiàn)就職于vivo。


    圖書推薦

    ▊《Android自定義控件高級進(jìn)階與精彩實例》

    啟艦 著

    • 專注于介紹Android自定義控件進(jìn)階知識
    • 通過精彩的案例對各種繪制、動畫技術(shù)進(jìn)行了糅合講解

    本書主要內(nèi)容有3D特效的實現(xiàn)、高級矩陣知識、消息處理機制、派生類型的選擇方法、多點觸控及輔助類、RecyclerView的使用方法及3D卡片的實現(xiàn)、動畫框架Lottie的講解與實戰(zhàn)等。

    讀者可以通過本書從宏觀層面、源碼層面對Android自定義控件建立完整的認(rèn)識。

網(wǎng)站首頁   |    關(guān)于我們   |    公司新聞   |    產(chǎn)品方案   |    用戶案例   |    售后服務(wù)   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區(qū)    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權(quán)所有