Android实现九宫格解锁

相信大家都有使用九宫格解锁,比如在设置手机安全项目中,可以使用九宫格解锁,提高安全性,以及在使用支付功能的时候,为了提高安全使用九宫锁,今天就为大家介绍Android实现九宫格的方法,分享给大家供大家参考。具体如下:
运行效果截图如下:

具体代码如下:

布局文件如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 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=".MainActivity" >

 <com.xuliugen.jiugongge.SudokuView
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="@string/hello_world" />

</RelativeLayout>

从布局文件中可以看出需要自定义一个View用于绘制九宫格图案:
SudokuView.java

package com.xuliugen.jiugongge;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class SudokuView extends View {

 private static final int DEFALUT_CELL_WIDTH = 60; //默认的cell宽度
 private static final int DEFALUT_CELL_STROKE_WIDTH = 2;
 private static final int DEFALUT_SPACE = DEFALUT_CELL_WIDTH >> 1;

 private Cell mCells[] = new Cell[9]; // 九宫格:定义用于存放九个数组

 private int mCellWidth;
 private int mCellRadius;
 private int mCellStrokeWidth;
 private int mSpace;

 private Paint mPaintNormal;
 private Paint mPaintSelected;
 private int mWidth;
 private int mHeight;

 private float mCurrentX;
 private float mCurrentY;
 private boolean mFinish = false;

 private StringBuffer mSbSelected = new StringBuffer(20);

 /**
  * 下边是三个构造方法:每一个构造方法中有一个初始化操作
  */
 public SudokuView(Context context) {
  super(context);
  init();
 }

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

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

 /**
  * 初始化操作
  */
 private void init() {
  mCellWidth = DensityUtil.dip2px(getContext(), DEFALUT_CELL_WIDTH);
  mCellRadius = DensityUtil.dip2px(getContext(), DEFALUT_CELL_WIDTH >> 1);
  mCellStrokeWidth = DensityUtil.dip2px(getContext(),
    DEFALUT_CELL_STROKE_WIDTH);
  mSpace = DensityUtil.dip2px(getContext(), DEFALUT_SPACE);

  mPaintNormal = new Paint();
  mPaintNormal.setColor(Color.WHITE);
  mPaintNormal.setStrokeWidth(mCellStrokeWidth);
  mPaintNormal.setStyle(Paint.Style.STROKE);
  mPaintNormal.setAntiAlias(true);

  mPaintSelected = new Paint();
  mPaintSelected.setColor(Color.CYAN);
  mPaintSelected.setStrokeWidth(mCellStrokeWidth);
  mPaintSelected.setStyle(Paint.Style.STROKE);
  mPaintSelected.setAntiAlias(true);

  Cell cell;
  float x;
  float y;

  for (int i = 0; i < 9; i++) {
   x = mSpace * (i % 3 + 1) + mCellRadius + mCellWidth * (i % 3);
   y = mSpace * (i / 3 + 1) + mCellRadius + mCellWidth * (i / 3);

   cell = new Cell(x, y);
   mCells[i] = cell;
  }
 }

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  drawCell(canvas);
  drawLine(canvas);
 }

 private void drawCell(Canvas canvas) {
  for (int i = 0; i < 9; i++) {
   canvas.drawCircle(mCells[i].getCenterX(), mCells[i].getCenterY(),
     mCellRadius, mCells[i].isSelected() ? mPaintSelected
       : mPaintNormal);
  }
 }

 private void drawLine(Canvas canvas) {
  if ("".equals(mSbSelected.toString())) {
   return;
  }

  String[] selectedIndexs = mSbSelected.toString().split(",");
  Cell cell = mCells[Integer.valueOf(selectedIndexs[0])];
  Cell nextCell;
  if (selectedIndexs.length > 1) {
   for (int i = 1; i < selectedIndexs.length; i++) {
    nextCell = mCells[Integer.valueOf(selectedIndexs[i])];
    canvas.drawLine(cell.getCenterX(), cell.getCenterY(),
      nextCell.getCenterX(), nextCell.getCenterY(),
      mPaintSelected);

    cell = nextCell;
   }
  }

  if (!mFinish) {
   canvas.drawLine(cell.getCenterX(), cell.getCenterY(), mCurrentX,
     mCurrentY, mPaintSelected);
  }
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  mWidth = getRealSize(widthMeasureSpec);
  mHeight = getRealSize(heightMeasureSpec);

  setMeasuredDimension(mWidth, mWidth);
 }

 private int getRealSize(int measureSpc) {
  int result;
  int mode = MeasureSpec.getMode(measureSpc);
  int size = MeasureSpec.getSize(measureSpc);

  if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.UNSPECIFIED) {
   result = mCellWidth * 3 + mSpace * 4;
  } else {
   result = size;
  }

  return result;
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {

  switch (event.getAction()) {
  case MotionEvent.ACTION_DOWN:
   if (mFinish) {
    for (int i = 0; i < 9; i++) {
     mCells[i].setSelected(false);
    }
    mFinish = false;
    mSbSelected.delete(0, mSbSelected.length());
    invalidate();
    return false;
   }
   handleDownEvent(event);
   break;
  case MotionEvent.ACTION_UP:
   mFinish = true;
   Toast.makeText(getContext(), mSbSelected.toString(),
     Toast.LENGTH_SHORT).show();
   break;
  case MotionEvent.ACTION_MOVE:
   handleMoveEvent(event);
   break;
  }

  return true;
 }

 private void handleMoveEvent(MotionEvent event) {
  int index = findCellIndex(event.getX(), event.getY());
  if (index != -1) {
   mCells[index].setSelected(true);
   mSbSelected.append(index).append(",");
  }
  invalidate();

  mCurrentX = event.getX();
  mCurrentY = event.getY();
 }

 private void handleDownEvent(MotionEvent event) {
  int index = findCellIndex(event.getX(), event.getY());
  if (index != -1) {
   mCells[index].setSelected(true);
   mSbSelected.append(index).append(",");
   invalidate();
  }

  mCurrentX = event.getX();
  mCurrentY = event.getY();
 }

 private int findCellIndex(float x, float y) {
  float cellX;
  float cellY;
  int result = -1;

  for (int i = 0; i < 9; i++) {
   if (mCells[i].isSelected()) {
    continue;
   }

   cellX = mCells[i].getCenterX();
   cellY = mCells[i].getCenterY();

   float tempX = cellX - x;
   float tempY = cellY - y;

   float distance = (float) Math.sqrt(tempX * tempX + tempY * tempY);

   if (distance < mCellRadius) {
    result = i;
    break;
   }
  }

  return result;
 }
}

MainActivity.java如下:

package com.xuliugen.jiugongge;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;

public class MainActivity extends ActionBarActivity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.menu_main, menu);
  return true;
 }

 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
  int id = item.getItemId();

  if (id == R.id.action_settings) {
   return true;
  }
  return super.onOptionsItemSelected(item);
 }
}

另外还需要一个存放圆圈的Javabean

package com.xuliugen.jiugongge;

/**
 * 代表每一个九宫格圆圈的Javabean
 * @author xuliugenpc
 */
public class Cell {
 private float centerX;
 private float centerY;
 private boolean selected;

 public Cell(float x, float y) {
  centerX = x;
  centerY = y;
 }

 public float getCenterX() {
  return centerX;
 }

 public void setCenterX(float centerX) {
  this.centerX = centerX;
 }

 public float getCenterY() {
  return centerY;
 }

 public void setCenterY(float centerY) {
  this.centerY = centerY;
 }

 public boolean isSelected() {
  return selected;
 }

 public void setSelected(boolean selected) {
  this.selected = selected;
 }
}

像素转换的工具类:

package com.xuliugen.jiugongge;

import android.content.Context;
/**
 * 手机屏幕px转dp和dp转px工具类
 * @author xuliugenpc
 */
public class DensityUtil {

 private static float scale;

 /**
  * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  */
 public static int dip2px(Context context, float dpValue) {
  if (scale == 0) {
   scale = context.getResources().getDisplayMetrics().density;
  }
  return (int) (dpValue * scale + 0.5f);
 }

 /**
  * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
  */
 public static int px2dip(Context context, float pxValue) {
  if (scale == 0) {
   scale = context.getResources().getDisplayMetrics().density;
  }
  return (int) (pxValue / scale + 0.5f);
 }
}

以上就是Android实现九宫格解锁的方法,希望本文所述对大家学习有所帮助。

(0)

相关推荐

  • Android自制九宫格解锁控件

    本文实例为大家分享了Android自制九宫格解锁控件的具体代码,供大家参考,具体内容如下 前两天从网上学习了下如何自定义一个九宫格解锁的控件,于是自己根据逻辑写了一遍,自定义控件的代码如下: public class LockedView extends View {       private boolean isFirst = true;//设置第一次加载时为true,后面重新画图不再执行     private int width, height;//获取控件的宽度和高度     priv

  • 使用Android自定义控件实现滑动解锁九宫格

    本文概述:  滑动解锁九宫格的分析: 1.需要自定义控件: 2.需要重写事件onTouchEvent(); 3.需要给九个点设置序号和坐标,这里用Map类就行: 4.需要判断是否到滑到过九点之一,并存储滑到过的点的序号,而且需要一个方法可以返回它们,这里用List类就行: 滑动解锁当前还是比较流行的,今天写了个简单的滑动解锁九宫格的例程,分享出来让初学者看看. 我的是这样的: Demo 首先,自定义一个View /** * 九宫格 */ public class NineGridView ext

  • 轻松实现安卓(Android)九宫格解锁

    效果图 思路 首先我们来分析一下实现九宫格解锁的思路:当用户的手指触摸到某一个点时,先判断该点是否在九宫格的某一格范围之内,若在范围内,则该格变成选中的状态:之后用户手指滑动的时候,以该格的圆心为中心,用户手指为终点,两点连线.最后当用户手指抬起时,判断划过的九宫格密码是否和原先的密码匹配. 大致的思路流程就是上面这样的了,下面我们可以来实践一下. Point 类 我们先来创建一个 Point 类,用来表示九宫格锁的九个格子.除了坐标 x ,y 之外,还有三种模式:正常模式.按下模式和错误模式.

  • android 九宫格滑动解锁开机实例源码学习

    效果图由于网站占时不能上传,以后补上. NinePointLineView.java 复制代码 代码如下: package org.demo.custon_view; import org.demo.utils.MLog; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; imp

  • Android实现九宫格手势解锁

    本文为大家分享了Android九宫格手势解锁的具体代码,供大家参考,具体内容如下 这里是使用的开源库GestureLibray 里面有关于这个东西的介绍和接入方式,这里就不累赘了,我只是说下里面没有的. 关于这个库的使用: protected void initViews() { //设置模式 LockMode lockMode = (LockMode) getIntent().getSerializableExtra(Config.INTENT_SECONDACTIVITY_KEY); //是

  • 轻松实现Android自定义九宫格图案解锁

    Android实现九宫格图案解锁,自带将图案转化成数字密码的功能,代码如下: LockPatternView.java package com.jackie.lockpattern; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.text.TextUtils; i

  • Android实现九宫格解锁的实例代码

    当年感觉九宫格解锁很是高大上,一脸懵逼,今天正好要做解锁这一块业务,回头来看九宫格,这特么简单啊 首先理清一下逻辑,我们要做NxN的九宫格 下图是3x3的简单图例 // -(--)-(--)-(--)- // -(--)-(--)-(--)- // -(--)-(--)-(--)- 我们就把九宫格分解成 外圆 .内圆.连线三部分 外圆半径Radius,内圆半径dp(5) 建立一个集合来放置 外圆的圆心( 内圆的圆心也一样) private ArrayList<Point> mListCircl

  • Android 仿小米锁屏实现九宫格解锁功能(无需图片资源)

    最近公司要求做个九宫格解锁,本人用的是小米手机,看着他那个设置锁屏九宫格很好看,就做了该组件,不使用图片资源,纯代码实现. 尊重每个辛苦的博主,在http://blog.csdn.net/mu399/article/details/38734449的基础上进行修改 效果图: 关键代码类: MathUtil.Java /** * @author SoBan * @create 2016/12/5 15:52. */ public class MathUtil { public static dou

  • Android自定义View九宫格手势密码解锁

    由于公司新的项目需要用到九宫格手势密码解锁的功能,于是觉得自己写一个.废话不多说,直接上效果图: 首选我们来分析下实现的思路: 1. 绘制出相对于这个View的居中的九个点,作为默认状态的点 2. 点击屏幕的时候是否点击在这九个点上 3. 在屏幕上滑动的时候,绘制两个点之间的线条,以及选中状态的点 4. 手指离开屏幕的时候判断手势密码是否正确,如若错误这把错误状态下的点和线绘制出来. 具体实现: 首先我们得绘制出默认正常状态下的九个点: /** * 点的bean * Created by Adm

  • 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

随机推荐