天天看點

Android實作手勢解鎖

自己實作過一個手勢解鎖, 覺得有一點用, 是以貼出來便于以後使用.

Android實作手勢解鎖
Android實作手勢解鎖

需求

     9宮格解鎖, 連接配接節點後, 節點之間會繪制連線. 節點被連接配接後會變色.

     當手指繼續繪制手勢時, 最後一個節點會延伸出一條連線跟随手指.

     當手指離開螢幕時開始判斷解鎖手勢是否正确, 若解鎖失敗, 連線變為紅色, 維持1秒(或者手指再次觸碰解鎖控件) 消失

思路

     按照需求, 可以得知需要根據連線狀态來繪制節點以及繪制連線, 并記錄連線狀态.

     手勢連線, 需要根據手指的坐标判定哪個節點被連接配接, 這裡通過計算手指點與節點距離來判定是否激活節點.

     手勢執行完畢後, 根據節點連線順序編号, 調用回調接口, 将手勢值傳回調用者.

繪制圖形     

     這裡需要繪制的圖形有三類:

            1. 節點.

            2. 節點間連線.

            3. 手指與節點的連線.

     正常的方案

         将以上三類圖形狀态儲存到資料結構, 每次移動手指便進行全盤的重繪. 網上很多的手勢解鎖實作就是用到這樣一個方案.

         這樣并不會引起效率問題, 隻是會讓程式員冤枉多寫一些代碼. 需要維護三種圖形的資料結構變化, 也要注意圖層的覆寫順序問題, 寫起來也稍微麻煩. 覺得這樣寫比較笨, 了解起來也難, 是以并未采用該方案.

     優化的方案

         使用FrameLayout, 建立三個圖層, 分别将 節點, 節點間連線, 手指與節點的連線, 這三塊需要維護的圖形放入不同的圖層, 這樣一來就簡單許多, 并且讓android幫程式員處理了圖層覆寫順序問題.

         1. 節點繪制:  建立一個GridLayout, 在GridLayout内放入9個ImageView來代表節點, 響應連線狀态時改變ImageView圖示.

         2. 節點間連線: 同理, 在連線狀态響應時根據節點的變化狀态, 根據坐标在該圖層繪制連線.

         3. 手指與節點的連線: 随着手指的移動, 将手指劃過的最後一個節點的坐标與手指目前坐标進行連線, 

判定節點激活

     這裡的判定方式無非是根據手指坐标以及節點中心坐标使用勾股定理計算距離來判定節點是否激活

     正常的方案

            循環所有節點, 計算各節點與手指間距離. 這裡計算距離公式為 sqrt( (x-xn)^2 + (y-yn)^2  )  這裡 x,y 為手指坐标,  xn, yn為第n個節點坐标.

            當距離小于門檻值(這裡通常為節點半徑), 激活節點.

     優化的方案

            1. 這裡9宮格為n*n個正方形組成的大正方形, 可以很友善的根據手指橫縱坐标計算出手指落點距離哪個9宮格節點最近, 然後隻需要計算和這個最近的9宮格的距離是否小于門檻值即可判定是否觸發, 減少循環次數. 這裡也需要考慮到手指落在9宮格外的情況.

            2. 節點激活距離門檻值預先平方, 避免比較距離時需要開平方, 減少計算量.

使用

    極其簡單, 無第三方庫依賴, 隻有幾個檔案, 很容易加到項目中

    使用方法如下:

GestureLockView gestureLockView = (GestureLockView) findViewById(R.id.gestureView); //在xml中添加手勢控件
gestureLockView.setGestureListener(new GestureLockView.GestureListener() {  //添加回調監聽器
    @Override
    public boolean getGesture(String gestureCode) { //gestureCode 是傳回的手勢值
        if (0 == gestureCode.length()) return true;  //空手勢
        if (gestureCode.equals("1478")) {  //判斷手勢值
            Toast.makeText(MainActivity.this, "Right!!", Toast.LENGTH_SHORT).show();
            return true;
        }
        Toast.makeText(MainActivity.this, gestureCode + "!=1478", Toast.LENGTH_SHORT).show();
        return false;
    }
});      

例子都在工程裡面, 使用Android Studio導入即可

  下載下傳連結