Android实现九宫格解锁
作者:徐刘根
根据最近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实现九宫格解锁的方法,希望本文所述对大家学习有所帮助。