欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2023-12-02 20:07:22
效果图由于网站占时不能上传,以后补上。 ninepointlineview.java 复制代码 代码如下: package org.demo.custon_view; im...
效果图由于网站占时不能上传,以后补上。
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;
import android.graphics.color;
import android.graphics.paint;
import android.graphics.paint.cap;
import android.graphics.typeface;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
public class ninepointlineview extends view {
paint linepaint = new paint();
paint whitelinepaint = new paint();
paint textpaint = new paint();
// 由于两个图片都是正方形,所以获取一个长度就行了
bitmap defaultbitmap = bitmapfactory.decoderesource(getresources(),
r.drawable.lock);
int defaultbitmapradius = defaultbitmap.getwidth() / 2;
// 初始化被选中图片的直径、半径
bitmap selectedbitmap = bitmapfactory.decoderesource(getresources(),
r.drawable.indicator_lock_area);
int selectedbitmapdiameter = selectedbitmap.getwidth();
int selectedbitmapradius = selectedbitmapdiameter / 2;
// 定义好9个点的数组
pointinfo[] points = new pointinfo[9];
// 相应action_down的那个点
pointinfo startpoint = null;
// 屏幕的宽高
int width, height;
// 当action_move时获取的x,y坐标
int movex, movey;
// 是否发生action_up
boolean isup = false;
// 最终生成的用户锁序列
stringbuffer lockstring = new stringbuffer();
public ninepointlineview(context context) {
super(context);
this.setbackgroundcolor(color.white);
initpaint();
}
public ninepointlineview(context context, attributeset attrs) {
super(context, attrs);
this.setbackgroundcolor(color.white);
initpaint();
}
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
mlog.i("onmeasure");
// 初始化屏幕大小
width = getwidth();
height = getheight();
if (width != 0 && height != 0) {
initpoints(points);
}
mlog.i("width、height = " + width + "、" + height);
super.onmeasure(widthmeasurespec, heightmeasurespec);
}
@override
protected void onlayout(boolean changed, int left, int top, int right,
int bottom) {
mlog.i("onlayout");
super.onlayout(changed, left, top, right, bottom);
}
private int startx = 0, starty = 0;
@override
protected void ondraw(canvas canvas) {
canvas.drawtext("用户的滑动顺序:" + lockstring, 0, 40, textpaint);
if (movex != 0 && movey != 0 && startx != 0 && starty != 0) {
// 绘制当前活动的线段
drawline(canvas, startx, starty, movex, movey);
}
drawninepoint(canvas);
super.ondraw(canvas);
}
// 记住,这个down和move、up是成对的,如果没从up释放,就不会再获得down;
// 而获得down时,一定要确认消费该事件,否则move和up不会被这个view的ontouchevent接收
@override
public boolean ontouchevent(motionevent event) {
boolean flag = true;
if (isup) {// 如果已滑完,重置每个点的属性和lockstring
finishdraw();
// 当up后,要返回false,把事件释放给系统,否则无法获得down事件
flag = false;
} else {// 没滑完,则继续绘制
handlingevent(event);
// 这里要返回true,代表该view消耗此事件,否则不会收到move和up事件
flag = true;
}
return flag;
}
private void handlingevent(motionevent event) {
switch (event.getaction()) {
case motionevent.action_move:
movex = (int) event.getx();
movey = (int) event.gety();
mlog.i("onmove:" + movex + "、" + movey);
for (pointinfo temp : points) {
if (temp.isinmyplace(movex, movey) && temp.isnotselected()) {
temp.setselected(true);
startx = temp.getcenterx();
starty = temp.getcentery();
int len = lockstring.length();
if (len != 0) {
int preid = lockstring.charat(len - 1) - 48;
points[preid].setnextid(temp.getid());
}
lockstring.append(temp.getid());
break;
}
}
invalidate(0, height - width, width, height);
break;
case motionevent.action_down:
int downx = (int) event.getx();
int downy = (int) event.gety();
mlog.i("ondown:" + downx + "、" + downy);
for (pointinfo temp : points) {
if (temp.isinmyplace(downx, downy)) {
temp.setselected(true);
startpoint = temp;
startx = temp.getcenterx();
starty = temp.getcentery();
lockstring.append(temp.getid());
break;
}
}
invalidate(0, height - width, width, height);
break;
case motionevent.action_up:
mlog.i("onup");
startx = starty = movex = movey = 0;
isup = true;
invalidate();
break;
default:
mlog.i("收到其他事件!!");
break;
}
}
private void finishdraw() {
for (pointinfo temp : points) {
temp.setselected(false);
temp.setnextid(temp.getid());
}
lockstring.delete(0, lockstring.length());
isup = false;
invalidate();
}
private void initpoints(pointinfo[] points) {
int len = points.length;
int seletedspacing = (width - selectedbitmapdiameter * 3) / 4;
// 被选择时显示图片的左上角坐标
int seletedx = seletedspacing;
int seletedy = height - width + seletedspacing;
// 没被选时图片的左上角坐标
int defaultx = seletedx + selectedbitmapradius - defaultbitmapradius;
int defaulty = seletedy + selectedbitmapradius - defaultbitmapradius;
// 绘制好每个点
for (int i = 0; i < len; i++) {
if (i == 3 || i == 6) {
seletedx = seletedspacing;
seletedy += selectedbitmapdiameter + seletedspacing;
defaultx = seletedx + selectedbitmapradius
- defaultbitmapradius;
defaulty += selectedbitmapdiameter + seletedspacing;
}
points[i] = new pointinfo(i, defaultx, defaulty, seletedx, seletedy);
seletedx += selectedbitmapdiameter + seletedspacing;
defaultx += selectedbitmapdiameter + seletedspacing;
}
}
private void initpaint() {
initlinepaint(linepaint);
inittextpaint(textpaint);
initwhitelinepaint(whitelinepaint);
}
/**
* 初始化文本画笔
* @param paint
*/
private void inittextpaint(paint paint) {
textpaint.settextsize(30);
textpaint.setantialias(true);
textpaint.settypeface(typeface.monospace);
}
/**
* 初始化黑线画笔
*
* @param paint
*/
private void initlinepaint(paint paint) {
paint.setcolor(color.gray);
paint.setstrokewidth(defaultbitmap.getwidth());
paint.setantialias(true);
paint.setstrokecap(cap.round);
}
/**
* 初始化白线画笔
*
* @param paint
*/
private void initwhitelinepaint(paint paint) {
paint.setcolor(color.white);
paint.setstrokewidth(defaultbitmap.getwidth() - 5);
paint.setantialias(true);
paint.setstrokecap(cap.round);
}
/**
* 绘制已完成的部分
*
* @param canvas
*/
private void drawninepoint(canvas canvas) {
if (startpoint != null) {
draweachline(canvas, startpoint);
}
// 绘制每个点的图片
for (pointinfo pointinfo : points) {
if (pointinfo.isselected()) {// 绘制大圈
canvas.drawbitmap(selectedbitmap, pointinfo.getseletedx(),
pointinfo.getseletedy(), null);
}
// 绘制点
canvas.drawbitmap(defaultbitmap, pointinfo.getdefaultx(),
pointinfo.getdefaulty(), null);
}
}
/**
* 递归绘制每两个点之间的线段
*
* @param canvas
* @param point
*/
private void draweachline(canvas canvas, pointinfo point) {
if (point.hasnextid()) {
int n = point.getnextid();
drawline(canvas, point.getcenterx(), point.getcentery(),
points[n].getcenterx(), points[n].getcentery());
// 递归
draweachline(canvas, points[n]);
}
}
/**
* 先绘制黑线,再在上面绘制白线,达到黑边白线的效果
*
* @param canvas
* @param startx
* @param starty
* @param stopx
* @param stopy
*/
private void drawline(canvas canvas, float startx, float starty,
float stopx, float stopy) {
canvas.drawline(startx, starty, stopx, stopy, linepaint);
canvas.drawline(startx, starty, stopx, stopy, whitelinepaint);
}
/**
* 用来表示一个点
*
* @author zkwlx
*
*/
private class pointinfo {
// 一个点的id
private int id;
// 当前点所指向的下一个点的id,当没有时为自己id
private int nextid;
// 是否被选中
private boolean selected;
// 默认时图片的左上角x坐标
private int defaultx;
// 默认时图片的左上角y坐标
private int defaulty;
// 被选中时图片的左上角x坐标
private int seletedx;
// 被选中时图片的左上角y坐标
private int seletedy;
public pointinfo(int id, int defaultx, int defaulty, int seletedx,
int seletedy) {
this.id = id;
this.nextid = id;
this.defaultx = defaultx;
this.defaulty = defaulty;
this.seletedx = seletedx;
this.seletedy = seletedy;
}
public boolean isselected() {
return selected;
}
public boolean isnotselected() {
return !isselected();
}
public void setselected(boolean selected) {
this.selected = selected;
}
public int getid() {
return id;
}
public int getdefaultx() {
return defaultx;
}
public int getdefaulty() {
return defaulty;
}
public int getseletedx() {
return seletedx;
}
public int getseletedy() {
return seletedy;
}
public int getcenterx() {
return seletedx + selectedbitmapradius;
}
public int getcentery() {
return seletedy + selectedbitmapradius;
}
public boolean hasnextid() {
return nextid != id;
}
public int getnextid() {
return nextid;
}
public void setnextid(int nextid) {
this.nextid = nextid;
}
/**
* 坐标(x,y)是否在当前点的范围内
*
* @param x
* @param y
* @return
*/
public boolean isinmyplace(int x, int y) {
boolean inx = x > seletedx
&& x < (seletedx + selectedbitmapdiameter);
boolean iny = y > seletedy
&& y < (seletedy + selectedbitmapdiameter);
return (inx && iny);
}
}
}

ninepointview.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;
import android.graphics.color;
import android.graphics.matrix;
import android.graphics.paint;
import android.graphics.paint.cap;
import android.graphics.path;
import android.graphics.typeface;
import android.util.attributeset;
import android.view.motionevent;
import android.view.view;
public class ninepointview extends view {
paint linepaint = new paint();
paint textpaint = new paint();
path path = new path();
// 由于两个图片都是正方形,所以获取一个长度就行了
bitmap defaultbitmap = bitmapfactory.decoderesource(getresources(),
r.drawable.lock);
int defaultbitmapradius = defaultbitmap.getwidth() / 2;
// 初始化被选中图片的直径、半径
bitmap selectedbitmap = bitmapfactory.decoderesource(getresources(),
r.drawable.indicator_lock_area);
int selectedbitmapdiameter = selectedbitmap.getwidth();
int selectedbitmapradius = selectedbitmapdiameter / 2;
// 初始化指示器的图片
bitmap indicatebitmap = bitmapfactory.decoderesource(getresources(),
r.drawable.indicator_lock_area_next);
bitmap tempbitmap = null;
// 定义好9个点的数组
pointinfo[] points = new pointinfo[9];
// 屏幕的宽高
int width, height;
// 当action_move时获取的x,y坐标
int movex, movey;
// 是否发生action_up
boolean isup = false;
// 最终生成的用户锁序列
stringbuffer lockstring = new stringbuffer();
matrix matrix = new matrix();
public ninepointview(context context) {
super(context);
this.setbackgroundcolor(color.white);
initlinepaint(linepaint);
inittextpaint(textpaint);
}
public ninepointview(context context, attributeset attrs) {
super(context, attrs);
this.setbackgroundcolor(color.white);
initlinepaint(linepaint);
inittextpaint(textpaint);
}
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
mlog.i("onmeasure");
width = getwidth();
height = getheight();
if (width != 0 && height != 0) {
initpoints(points);
}
mlog.i("width、height = " + width + "、" + height);
super.onmeasure(widthmeasurespec, heightmeasurespec);
}
@override
protected void onlayout(boolean changed, int left, int top, int right,
int bottom) {
mlog.i("onlayout");
super.onlayout(changed, left, top, right, bottom);
}
private int startx = 0, starty = 0;
@override
protected void ondraw(canvas canvas) {
canvas.drawtext("用户的滑动顺序:" + lockstring, 0, 40, textpaint);
if (movex != 0 && movey != 0 && startx != 0 && starty != 0) {
// 绘制当前活动的线段
canvas.drawline(startx, starty, movex, movey, linepaint);
}
drawninepoint(canvas, linepaint);
super.ondraw(canvas);
}
// 记住,这个down和move、up是成对的,如果没从up释放,就不会再获得down;
// 而获得down时,一定要确认消费该事件,否则move和up不会被这个view的ontouchevent接收
@override
public boolean ontouchevent(motionevent event) {
boolean flag = true;
if (isup) {// 如果已滑完,则把整个canvas重置
finishdraw();
// 当up后,要返回false,把事件释放给系统,否则无法获得down事件
flag = false;
} else {// 没滑完,则继续绘制
handlingevent(event);
// 这里要返回true,否则代表该view不消耗此事件,交给系统处理,则不会再收到move和up事件
flag = true;
}
return flag;
}
private void handlingevent(motionevent event) {
switch (event.getaction()) {
case motionevent.action_move:
movex = (int) event.getx();
movey = (int) event.gety();
mlog.i("onmove:" + movex + "、" + movey);
for (pointinfo temp : points) {
if (temp.isinmyplace(movex, movey) && temp.isnotselected()) {
temp.setselected(true);
startx = temp.getcenterx();
starty = temp.getcentery();
int len = lockstring.length();
if (len != 0) {
int preid = lockstring.charat(len - 1) - 48;
points[preid].setnextid(temp.getid());
}
lockstring.append(temp.getid());
break;
}
}
invalidate(0, height - width, width, height);
break;
case motionevent.action_down:
int downx = (int) event.getx();
int downy = (int) event.gety();
mlog.i("ondown:" + downx + "、" + downy);
for (pointinfo temp : points) {
if (temp.isinmyplace(downx, downy)) {
temp.setselected(true);
startx = temp.getcenterx();
starty = temp.getcentery();
lockstring.append(temp.getid());
break;
}
}
invalidate(0, height - width, width, height);
break;
case motionevent.action_up:
mlog.i("onup");
startx = starty = movex = movey = 0;
isup = true;
invalidate();
break;
default:
mlog.i("收到其他事件!!");
break;
}
}
private void finishdraw() {
for (pointinfo temp : points) {
temp.setselected(false);
temp.setnextid(temp.getid());
}
lockstring.delete(0, lockstring.length());
isup = false;
invalidate();
}
private void initpoints(pointinfo[] points) {
int len = points.length;
int seletedspacing = (width - selectedbitmapdiameter * 3) / 4;
// 被选择时显示图片的左上角坐标
int seletedx = seletedspacing;
int seletedy = height - width + seletedspacing;
// 没被选时图片的左上角坐标
int defaultx = seletedx + selectedbitmapradius - defaultbitmapradius;
int defaulty = seletedy + selectedbitmapradius - defaultbitmapradius;
for (int i = 0; i < len; i++) {
if (i == 3 || i == 6) {
seletedx = seletedspacing;
seletedy += selectedbitmapdiameter + seletedspacing;
defaultx = seletedx + selectedbitmapradius
- defaultbitmapradius;
defaulty += selectedbitmapdiameter + seletedspacing;
}
points[i] = new pointinfo(i, defaultx, defaulty, seletedx, seletedy);
seletedx += selectedbitmapdiameter + seletedspacing;
defaultx += selectedbitmapdiameter + seletedspacing;
}
}
private void inittextpaint(paint paint) {
textpaint.settextsize(30);
textpaint.setantialias(true);
textpaint.settypeface(typeface.monospace);
}
/**
* 初始化线画笔
*
* @param paint
*/
private void initlinepaint(paint paint) {
paint.setcolor(color.gray);
paint.setstrokewidth(defaultbitmap.getwidth());
paint.setantialias(true);
paint.setstrokecap(cap.round);
}
/**
* 绘制已完成的部分
*
* @param canvas
*/
private void drawninepoint(canvas canvas, paint paint) {
// 先把用户画出的线绘制好
for (pointinfo pointinfo : points) {
if (pointinfo.hasnextid()) {
int n = pointinfo.getnextid();
canvas.drawline(pointinfo.getcenterx(), pointinfo.getcentery(),
points[n].getcenterx(), points[n].getcentery(), paint);
}
}
// 绘制每个点的图片
for (pointinfo pointinfo : points) {
if (pointinfo.isselected()) {
if (pointinfo.hasnextid()) {
matrix.reset();
int i = (int) math.abs(math.random() * 1000 - 640);
mlog.i("随机到的角度:" + i);
matrix.setrotate(i);
tempbitmap = bitmap.createbitmap(indicatebitmap, 0, 0,
indicatebitmap.getwidth(),
indicatebitmap.getheight(), matrix, false);
canvas.drawbitmap(tempbitmap, pointinfo.getseletedx(),
pointinfo.getseletedy(), paint);
} else {
canvas.drawbitmap(selectedbitmap, pointinfo.getseletedx(),
pointinfo.getseletedy(), paint);
}
}
canvas.drawbitmap(defaultbitmap, pointinfo.getdefaultx(),
pointinfo.getdefaulty(), paint);
}
}
private class pointinfo {
// 一个点的id
private int id;
// 当前点所指向的下一个点的id,当没有时为自己id
private int nextid;
// 是否被选中
private boolean selected;
// 默认时图片的左上角x坐标
private int defaultx;
// 默认时图片的左上角y坐标
private int defaulty;
// 被选中时图片的左上角x坐标
private int seletedx;
// 被选中时图片的左上角y坐标
private int seletedy;
public pointinfo(int id, int defaultx, int defaulty, int seletedx,
int seletedy) {
this.id = id;
this.nextid = id;
this.defaultx = defaultx;
this.defaulty = defaulty;
this.seletedx = seletedx;
this.seletedy = seletedy;
}
public boolean isselected() {
return selected;
}
public boolean isnotselected() {
return !isselected();
}
public void setselected(boolean selected) {
this.selected = selected;
}
public int getid() {
return id;
}
public int getdefaultx() {
return defaultx;
}
public int getdefaulty() {
return defaulty;
}
public int getseletedx() {
return seletedx;
}
public int getseletedy() {
return seletedy;
}
public int getcenterx() {
return seletedx + selectedbitmapradius;
}
public int getcentery() {
return seletedy + selectedbitmapradius;
}
public boolean hasnextid() {
return nextid != id;
}
public int getnextid() {
return nextid;
}
public void setnextid(int nextid) {
this.nextid = nextid;
}
/**
* 坐标(x,y)是否在当前点的范围内
*
* @param x
* @param y
* @return
*/
public boolean isinmyplace(int x, int y) {
boolean inx = x > seletedx
&& x < (seletedx + selectedbitmapdiameter);
boolean iny = y > seletedy
&& y < (seletedy + selectedbitmapdiameter);
if (inx && iny) {
return true;
} else {
return false;
}
}
}
}