中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android自定義控件實現九宮格解鎖功能

發布時間:2020-09-14 12:16:55 來源:腳本之家 閱讀:165 作者:一生中所愛 欄目:移動開發

最終Android九宮格解鎖效果如下

Android自定義控件實現九宮格解鎖功能

1.進行定義實體point點

public class Point {
 private float x;
 private float y;
 //正常模式
 public static final int NORMAL_MODE = 1;
 //按下模式
 public static final int PRESSED_MODE = 2;
 //錯誤模式
 public static final int ERROR_MODE = 3;

 private int state = NORMAL_MODE;
 private String mark;

 public Point(float x, float y, String mark) {
  this.x = x;
  this.y = y;
  this.mark = mark;
 }

 public float getX() {
  return x;
 }

 public void setX(float x) {
  this.x = x;
 }

 public float getY() {
  return y;
 }

 public void setY(float y) {
  this.y = y;
 }

 public int getState() {
  return state;
 }

 public void setState(int state) {
  this.state = state;
 }

 public String getMark() {
  return mark;
 }

 public void setMark(String mark) {
  this.mark = mark;
 }
}

2.自定義ScreenLockView

public class ScreenLockView extends View {
 private static final String TAG = "ScreenLockView";

 // 錯誤格子的圖片
 private Bitmap errorBitmap;
 // 正常格子的圖片
 private Bitmap normalBitmap;
 // 手指按下時格子的圖片
 private Bitmap pressedBitmap;
 // 錯誤時連線的圖片
 private Bitmap lineErrorBitmap;
 // 手指按住時連線的圖片
 private Bitmap linePressedBitmap;
 // 偏移量,使九宮格在屏幕中央
 private int offset;
 // 九宮格的九個格子是否已經初始化
 private boolean init;
 // 格子的半徑
 private int radius;
 // 密碼
 private String password = "123456";
 // 九個格子
 private Point[][] points = new Point[3][3];
 private int width;
 private int height;
 private Matrix matrix = new Matrix();
 private float moveX = -1;
 private float moveY = -1;
 // 是否手指在移動
 private boolean isMove;
 // 是否可以觸摸,當用戶抬起手指,劃出九宮格的密碼不正確時為不可觸摸
 private boolean isTouch = true;
 // 用來存儲記錄被按下的點
 private List<Point> pressedPoint = new ArrayList<>();
 // 屏幕解鎖監聽器
 private OnScreenLockListener listener;

 public ScreenLockView(Context context) {
  super(context);
  init();
 }


 public ScreenLockView(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public ScreenLockView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  init();
 }

 private void init() {
  errorBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_error);
  normalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_normal);
  pressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmap_pressed);
  lineErrorBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.line_error);
  linePressedBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.line_pressed);
  radius = normalBitmap.getWidth() / 2;
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  int widthSize = MeasureSpec.getSize(widthMeasureSpec);
  int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  int heightSize = MeasureSpec.getSize(heightMeasureSpec);
  int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  if (widthSize > heightSize) {
   offset = (widthSize - heightSize) / 2;
  } else {
   offset = (heightSize - widthSize) / 2;
  }
  setMeasuredDimension(widthSize, heightSize);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  if (!init) {
   width = getWidth();
   height = getHeight();
   initPoint();
   init = true;
  }
  drawPoint(canvas);
  if (moveX != -1 && moveY != -1) {
   drawLine(canvas);
  }
 }

 // 畫直線
 private void drawLine(Canvas canvas) {

  // 將pressedPoint中的所有格子依次遍歷,互相連線
  for (int i = 0; i < pressedPoint.size() - 1; i++) {
   // 得到當前格子
   Point point = pressedPoint.get(i);
   // 得到下一個格子
   Point nextPoint = pressedPoint.get(i + 1);
   // 旋轉畫布
   canvas.rotate(RotateDegrees.getDegrees(point, nextPoint), point.getX(), point.getY());

   matrix.reset();
   // 根據距離設置拉伸的長度
   matrix.setScale(getDistance(point, nextPoint) / linePressedBitmap.getWidth(), 1f);
   // 進行平移
   matrix.postTranslate(point.getX(), point.getY() - linePressedBitmap.getWidth() / 2);


   if (point.getState() == Point.PRESSED_MODE) {
    canvas.drawBitmap(linePressedBitmap, matrix, null);
   } else {
    canvas.drawBitmap(lineErrorBitmap, matrix, null);
   }
   // 把畫布旋轉回來
   canvas.rotate(-RotateDegrees.getDegrees(point, nextPoint), point.getX(), point.getY());
  }

  // 如果是手指在移動的情況
  if (isMove) {
   Point lastPoint = pressedPoint.get(pressedPoint.size() - 1);
   canvas.rotate(RotateDegrees.getDegrees(lastPoint, moveX, moveY), lastPoint.getX(), lastPoint.getY());

   matrix.reset();
   Log.i(TAG, "the distance : " + getDistance(lastPoint, moveX, moveY) / linePressedBitmap.getWidth());
   matrix.setScale(getDistance(lastPoint, moveX, moveY) / linePressedBitmap.getWidth(), 1f);
   matrix.postTranslate(lastPoint.getX(), lastPoint.getY() - linePressedBitmap.getWidth() / 2);
   canvas.drawBitmap(linePressedBitmap, matrix, null);

   canvas.rotate(-RotateDegrees.getDegrees(lastPoint, moveX, moveY), lastPoint.getX(), lastPoint.getY());
  }
 }

 // 根據point和坐標點計算出之間的距離
 private float getDistance(Point point, float moveX, float moveY) {
  Point b = new Point(moveX,moveY,null);
  return getDistance(point,b);
 }

 // 根據兩個point計算出之間的距離
 private float getDistance(Point point, Point nextPoint) {
  return (float) Math.sqrt(Math.pow(nextPoint.getX() - point.getX(), 2f) + Math.pow(nextPoint.getY() - point.getY(), 2f));
 }
 private void drawPoint(Canvas canvas) {
  for (int i = 0; i < points.length; i++) {
   for (int j = 0; j < points[i].length; j++) {
    int state = points[i][j].getState();
    if (state == Point.NORMAL_MODE) {
     canvas.drawBitmap(normalBitmap, points[i][j].getX() - radius, points[i][j].getY() - radius, null);
    } else if (state == Point.PRESSED_MODE) {
     canvas.drawBitmap(pressedBitmap, points[i][j].getX() - radius, points[i][j].getY() - radius, null);
    } else {
     canvas.drawBitmap(errorBitmap, points[i][j].getX() - radius, points[i][j].getY() - radius, null);
    }
   }
  }
 }

 //初始化九宮格的點
 private void initPoint() {
  points[0][0] = new Point(width / 4, offset + width / 4, "0");
  points[0][1] = new Point(width / 2, offset + width / 4, "1");
  points[0][2] = new Point(width * 3 / 4, offset + width / 4, "2");

  points[1][0] = new Point(width / 4, offset + width / 2, "3");
  points[1][1] = new Point(width / 2, offset + width / 2, "4");
  points[1][2] = new Point(width * 3 / 4, offset + width / 2, "5");

  points[2][0] = new Point(width / 4, offset + width * 3 / 4, "6");
  points[2][1] = new Point(width / 2, offset + width * 3 / 4, "7");
  points[2][2] = new Point(width * 3 / 4, offset + width * 3 / 4, "8");

 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
  if (isTouch) {
   float x = event.getX();
   float y = event.getY();
   Point point;
   switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
     // 判斷用戶觸摸的點是否在九宮格的任意一個格子之內
     point = isPoint(x, y);
     if (point != null) {
      point.setState(Point.PRESSED_MODE); // 切換為按下模式
      pressedPoint.add(point);
     }
     break;
    case MotionEvent.ACTION_MOVE:
     if (pressedPoint.size() > 0) {
      point = isPoint(x, y);
      if (point != null) {
       if (!crossPoint(point)) {
        point.setState(Point.PRESSED_MODE);
        pressedPoint.add(point);
       }
      }
      moveX = x;
      moveY = y;
      isMove = true;
     }
     break;
    case MotionEvent.ACTION_UP:
     isMove = false;
     String tempPwd = "";
     for (Point p : pressedPoint) {
      tempPwd += p.getMark();
     }
     if (listener != null) {
      listener.getStringPassword(tempPwd);
     }

     if (tempPwd.equals(password)) {
      if (listener != null) {
       listener.isPassword(true);
       this.postDelayed(runnable, 1000);
      }

     } else {
      for (Point p : pressedPoint) {
       p.setState(Point.ERROR_MODE);
      }
      isTouch = false;
      this.postDelayed(runnable, 1000);
      if (listener != null) {
       listener.isPassword(false);
      }
     }
     break;
   }
   invalidate();
  }
  return true;
 }

 private boolean crossPoint(Point point) {
  if (pressedPoint.contains(point)) {
   return true;
  }
  return false;
 }

 public interface OnScreenLockListener {
  public void getStringPassword(String password);

  public void isPassword(boolean flag);
 }

 public void setOnScreenLockListener(OnScreenLockListener listener) {
  this.listener = listener;
 }

 private Point isPoint(float x, float y) {
  Point point;
  for(int i = 0; i<points.length;i++){
   for (int j = 0; j < points[i].length; j++) {
    point = points[i][j];
    if (isContain(point, x, y)) {
     return point;
    }
   }
  }
  return null;
 }

 private boolean isContain(Point point, float x, float y) {
  return Math.sqrt(Math.pow(x - point.getX(), 2f) + Math.pow(y - point.getY(), 2f)) <= radius;
 }
 private Runnable runnable = new Runnable() {
  @Override
  public void run() {
   isTouch = true;
   reset();
   invalidate();
  }
 };

 // 重置格子
 private void reset(){
  for (int i = 0; i < points.length; i++) {
   for (int j = 0; j < points[i].length; j++) {
    points[i][j].setState(Point.NORMAL_MODE);
   }
  }
  pressedPoint.clear();
 }
}

3.RotateDegress類

public class RotateDegrees {
 public static float getDegrees(Point a, Point b){
  float degrees = 0 ;
  float aX = a.getX();
  float aY = a.getY();
  float bX = b.getX();
  float bY = b.getY();
  if(aX == bX){
   if(aY<bY){
    degrees = 90;
   }else{
    degrees = 270;
   }
  }else if(bY == aY){
   if(aX<bX){
    degrees = 0 ;
   }else{
    degrees = 180;
   }

  }else{
   if(aX>bX){
    if(aY>bY){
     degrees = 180 + (float)(Math.atan2(aY-bY,aX-bX)*180/Math.PI);
    }else{
     degrees = 180 - (float)(Math.atan2(bY -aY,aX - bX)*180/Math.PI);
    }

   }else{
    if(aY>bY){
     degrees = 360 -(float)(Math.atan2(aY - bY,bX-aX)*180/Math.PI);
    }else{
     degrees = (float)(Math.atan2(bY - aY,bX - aX)*180/Math.PI);
    }
   }
  }
  return degrees;
 }

 public static float getDegrees(Point a, float bX,float bY){
  Point b = new Point(bX,bY,null);
  return getDegrees(a,b);
 }
}

用到的圖片資源

Android自定義控件實現九宮格解鎖功能Android自定義控件實現九宮格解鎖功能Android自定義控件實現九宮格解鎖功能

4.MainActivity中使用

public class MainActivity extends AppCompatActivity {

 private ScreenLockView screenLockView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  screenLockView = (ScreenLockView) findViewById(R.id.slv);
  screenLockView.setOnScreenLockListener(new ScreenLockView.OnScreenLockListener() {
   @Override
   public void getStringPassword(String password) {

   }

   @Override
   public void isPassword(boolean flag) {
    String content;
    if (flag) {
     content = "密碼正確";

    } else {
     content = "密碼錯誤";
    }
    Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();

   }
  });
 }
}

5.布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 tools:context="com.example.admin.ninegridunlock.MainActivity">

 <com.example.admin.ninegridunlock.ScreenLockView
  android:id="@+id/slv"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />
</RelativeLayout>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

辉县市| 白朗县| 修武县| 渑池县| 赤峰市| 定结县| 邵阳县| 贵南县| 惠州市| 长阳| 淮南市| 南郑县| 南陵县| 尼玛县| 峨山| 通辽市| 玉山县| 乳山市| 宁阳县| 西峡县| 会同县| 博罗县| 辉南县| 拜泉县| 阿拉尔市| 永年县| 河津市| 乐亭县| 彰化县| 哈巴河县| 都江堰市| 衡阳市| 六安市| 卢龙县| 呼和浩特市| 罗山县| 石嘴山市| 峨眉山市| 洮南市| 汉中市| 桦甸市|