亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Android實現(xiàn)九宮格解鎖的實例代碼

 更新時間:2017年07月26日 11:00:23   作者:Mr_SSY  
本篇文章主要介紹了Android九宮格解鎖的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

當(dāng)年感覺九宮格解鎖很是高大上,一臉懵逼,今天正好要做解鎖這一塊業(yè)務(wù),回頭來看九宮格,這特么簡單啊

首先理清一下邏輯,我們要做NxN的九宮格 下圖是3x3的簡單圖例

// -(--)-(--)-(--)-
// -(--)-(--)-(--)-
// -(--)-(--)-(--)-

我們就把九宮格分解成

外圓 、內(nèi)圓、連線三部分

外圓半徑Radius,內(nèi)圓半徑dp(5)

建立一個集合來放置 外圓的圓心( 內(nèi)圓的圓心也一樣)

 private ArrayList<Point> mListCircle;//外圓的圓心

 for (int i = 0; i < mCount; i++) {
      for (int j = 0; j < mCount; j++) {
        Point point = new Point((3 * i + 2) * (int) mRadius, (3 * j + 2) * (int) mRadius);
        mListCircle.add(point);
      }
    }

這樣我們就初始化好了內(nèi)外圓的位置point集合

我們draw一下看一下效果

void drawAll_Cicle(Canvas canvas) {
    for (int i = 0; i < mListCircle.size(); i++) {
      Point point = mListCircle.get(i);
        canvas.drawCircle(point.x, point.y, mRadius, mPaint);
        canvas.drawCircle(point.x, point.y, mMinRadius, miniPaint);
    }

效果圖就是上圖了 (哈哈一樣的)

主結(jié)構(gòu)已經(jīng)畫完了,接下來就是如何繪制點與點之間的連線了,有人會覺得沒思路,其實很簡單了,以3X3 為例子哈
我們可以給這九個棋子編號1--9號,把他存入LinkedHashSet中,著重介紹這個LinkedHashSet有順序不重復(fù)這個真的在合適不過了。

這樣就不會有重復(fù)的事情了。這個和解鎖時候的密碼也很契合。所以選對了存儲方式會事半功倍。

還有一個問題,就是點擊邊界問題,這個好解決,我們把每一個棋子都花矩形,通過圓來控制邊界,(其實也可以通過矩形來控制邊界,這個也很簡單,原理是差不多的,有興趣的同學(xué)可以下去試試)

同樣也是用集合。和上邊的圓是一樣一樣的。

ArrayList<RectF> mListRectFs;
for (int i = 0; i < mCount; i++) {
      for (int j = 0; j < mCount; j++) {
        RectF rectF = new RectF((3 * i + 1) * mRadius, (3 * j + 1) * mRadius, (3 * i + 3) * mRadius, (3 * j + 3) * mRadius);
        mListRectFs.add(rectF);
      }
    }

好邊界也有了,我們來計算邊界返回編號

/**
   * 點和圓形碰撞檢測
   *
   * @param x1   手指接觸點
   * @param y1   手指接觸點
   * @param x2   外圓
   * @param y2   外圓
   * @param radius 半徑
   * @return
   */
  private boolean isCollision(float x1, float y1, float x2, float y2, float radius) {
    if (Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) <= radius) {
      // 如果點和圓心距離小于或等于半徑則認為發(fā)生碰撞
      return true;
    }
    return false;
  }


/**
   * 判斷觸摸點在哪個item上
   *
   * @param x
   * @param y
   * @return
   */
  private int touchIndex(float x, float y) {
    for (int i = 0; i < mListCircle.size(); i++) {
      Point p = mListCircle.get(i);
      if (isCollision(x, y, p.x, p.y, mRadius)) {
        return i;
      }
    }

    return -1;
  }

幾個關(guān)鍵點都寫到了接下來就是具體的細節(jié)了。我把代碼都貼上來,注釋的很詳細。當(dāng)然加入了一個手指觸控點,更加好看一些。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;

/**
 * Created by ld on 2017/7/25.
 */

public class NineGridLockView extends View {
  private Context context;
  int index_point = 0;
  private float mDensity;
  private int mCount = 3;
  private ArrayList<RectF> mListRectFs;//圓的外形矩形
  private ArrayList<Point> mListCircle;//外圓的圓心
  private LinkedHashSet<Integer> mSetPoints;//記錄需要連線的外圓圓心點在mListCircle中的索引值,LinkedHashSet線性不可重復(fù) 集合,F(xiàn)IFO
  private Paint mPaint, miniPaint;//畫筆
  private float mRadius;//外圓半徑
  private float mMinRadius;//內(nèi)圓半徑
  private float mStrokeWidth = 10; //繪制時的畫筆寬度
  private Point mMovePoint; //記錄手指移動時的點

  public NineGridLockView(Context context) {
    this(context, null);
  }

  public NineGridLockView(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    mDensity = getContext().getResources().getDisplayMetrics().density;
    mListRectFs = new ArrayList<>();
    mListCircle = new ArrayList<>();
    mPaint = new Paint();
    mPaint.setStrokeWidth(5);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.BLUE);

    miniPaint = new Paint();
    miniPaint.setColor(Color.BLACK);
    miniPaint.setAntiAlias(true);
    miniPaint.setStyle(Paint.Style.STROKE);
    miniPaint.setStrokeWidth(5);
    mMinRadius = dp(5);
    mSetPoints = new LinkedHashSet<>();
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    drawAll_Cicle(canvas);
    draw_line(canvas);
  }

  private int dp(int dp) {
    return (int) (dp * mDensity + 0.5f);
  }

  //繪制 連接線
  void draw_line(Canvas canvas) {
    Point p1 = null;
    Point p2 = null;
    //從結(jié)合中獲取 move過的點
    for (int index : mSetPoints) {
      //當(dāng)?shù)谝粋€點為null的時候 給第一個點賦值
      if (p1 == null) {
        p1 = mListCircle.get(index);
        //然后 給第二個點賦值 兩點一條線
      } else if (p2 == null) {
        p2 = mListCircle.get(index);
        canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaint);
        //p1 挪到p2
        p1 = p2;
        //接下來就是第三個點了 乃至更多點
      } else {
        //p2重新賦值 兩點一條線
        p2 = mListCircle.get(index);
        canvas.drawLine(p1.x, p1.y, p2.x, p2.y, mPaint);
        //p1 挪到p2
        p1 = p2;
      }

    }

    //繪制實時連線
    if (mMovePoint != null && p1 != null) {
      canvas.drawLine(p1.x, p1.y, mMovePoint.x, mMovePoint.y, mPaint);
    }
  }

  //繪制 外圓 內(nèi)圓
  void drawAll_Cicle(Canvas canvas) {
    for (int i = 0; i < mListRectFs.size(); i++) {
      Point point = mListCircle.get(i);
      //如果move過的 就換顏色
      if (mSetPoints.contains(i)) {
        canvas.drawCircle(point.x, point.y, mRadius, miniPaint);
        canvas.drawCircle(point.x, point.y, mMinRadius, mPaint);

      } else {

        canvas.drawCircle(point.x, point.y, mRadius, mPaint);
        canvas.drawCircle(point.x, point.y, mMinRadius, miniPaint);
      }

    }

  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    float w = Math.min(getMeasuredWidth(), getMeasuredHeight());
    //   -(--)-(--)-(--)-
    //   -(--)-(--)-(--)-
    //   -(--)-(--)-(--)-
    mRadius = getMeasuredWidth() * 1.00f / (mCount * 3 + 1);

    float rectWH = mRadius * 2;
    mListRectFs.clear();
    mListCircle.clear();
    for (int i = 0; i < mCount; i++) {
      for (int j = 0; j < mCount; j++) {
        RectF rectF = new RectF((3 * i + 1) * mRadius, (3 * j + 1) * mRadius, (3 * i + 3) * mRadius, (3 * j + 3) * mRadius);
        mListRectFs.add(rectF);
        Point point = new Point((3 * i + 2) * (int) mRadius, (3 * j + 2) * (int) mRadius);


        mListCircle.add(point);
      }
    }

  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float point_x = event.getX();
    float point_y = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:


        break;
      case MotionEvent.ACTION_UP:
        mMovePoint = null;
        mSetPoints.clear();
        invalidate();
        break;
      case MotionEvent.ACTION_MOVE:

        int index = touchIndex(point_x, point_y);
        if (mMovePoint == null) {
          mMovePoint = new Point((int) point_x, (int) point_y);
        } else {
          mMovePoint.set((int) point_x, (int) point_y);
        }

        if (index != -1) {
          mSetPoints.add(index);
          if (index_point != mSetPoints.size()) {
            index_point = mSetPoints.size();
            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
          }
        }
        invalidate();
        break;
    }

    return true;
  }


  /**
   * 判斷觸摸點在哪個item上
   *
   * @param x
   * @param y
   * @return
   */
  private int touchIndex(float x, float y) {
    for (int i = 0; i < mListCircle.size(); i++) {
      Point p = mListCircle.get(i);
      if (isCollision(x, y, p.x, p.y, mRadius)) {
        return i;
      }
    }

    return -1;
  }

  /**
   * 點和圓形碰撞檢測
   *
   * @param x1   手指接觸點
   * @param y1   手指接觸點
   * @param x2   外圓
   * @param y2   外圓
   * @param radius 半徑
   * @return
   */
  private boolean isCollision(float x1, float y1, float x2, float y2, float radius) {
    if (Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) <= radius) {
      // 如果點和圓心距離小于或等于半徑則認為發(fā)生碰撞
      return true;
    }
    return false;
  }
}

下一篇會把把應(yīng)用鎖和這個結(jié)合起來,就是appLock功能了。敬請期待···

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android中Intent傳遞對象的3種方式詳解

    Android中Intent傳遞對象的3種方式詳解

    這篇文章給大家介紹了Android中Intent傳遞對象的3種方式,分別是Serializable 方式、Parcelable 方式以及JSON 方式,有需要的朋友們可以一起參考借鑒,下面來一起看看吧。
    2016-09-09
  • Android自定義ViewGroup實現(xiàn)側(cè)滑菜單

    Android自定義ViewGroup實現(xiàn)側(cè)滑菜單

    這篇文章主要為大家詳細介紹了Android如何通過自定義ViewGroup實現(xiàn)側(cè)滑菜單,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2023-01-01
  • Android中不同狀態(tài)頁面管理優(yōu)化技巧詳解

    Android中不同狀態(tài)頁面管理優(yōu)化技巧詳解

    在Android中,不管是activity或者fragment,在加載視圖的時候都有可能會出現(xiàn)多種不同的狀態(tài)頁面View,所以本文就來聊聊Android中不同狀態(tài)頁面管理優(yōu)化吧
    2024-04-04
  • Android使用ViewFlipper實現(xiàn)圖片上下自動輪播的示例代碼

    Android使用ViewFlipper實現(xiàn)圖片上下自動輪播的示例代碼

    這篇文章主要介紹了Android使用ViewFlipper實現(xiàn)圖片上下自動輪播的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • Android Handler實現(xiàn)閃屏頁倒計時代碼

    Android Handler實現(xiàn)閃屏頁倒計時代碼

    這篇文章主要介紹了Android Handler實現(xiàn)閃屏頁倒計時代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 快速掌握Android屏幕的知識點

    快速掌握Android屏幕的知識點

    相信不少設(shè)計師和工程師都被安卓設(shè)備紛繁的屏幕搞得暈頭轉(zhuǎn)向,我既做UI設(shè)計,也做過一點安卓界面布局,剛好對這塊內(nèi)容比較熟悉,所以在此我將此部分知識重新梳理出來分享給大家!有需要的朋友們可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-11-11
  • Android自定義View實現(xiàn)拖動自動吸邊效果

    Android自定義View實現(xiàn)拖動自動吸邊效果

    這篇文章主要為大家詳細介紹了Android自定義View實現(xiàn)拖動自動吸邊效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • 使用Glide實現(xiàn)高斯模糊效果

    使用Glide實現(xiàn)高斯模糊效果

    這篇文章主要為大家詳細介紹了使用Glide實現(xiàn)高斯模糊效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 基于Flutter實現(xiàn)手勢密碼加密與解鎖功能

    基于Flutter實現(xiàn)手勢密碼加密與解鎖功能

    這篇文章主要介紹了如何利用Flutter實現(xiàn)手勢密碼的加密與解鎖,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • android中開啟actionbar的兩種方法

    android中開啟actionbar的兩種方法

    這篇文章主要介紹了android中開啟actionbar的兩種方法,本文給出了靜態(tài)開啟和動態(tài)開啟2種方法,需要的朋友可以參考下
    2015-06-06

最新評論