Android 九宮格鎖屏(已更新嘱蛋,添加了用戶操作記錄密碼修陡,更加完善邀桑,更新的在下面)
此demo的重點(diǎn)就在于九宮點(diǎn)的繪制,與用戶操作手勢(shì)的監(jiān)聽(tīng)交互
實(shí)現(xiàn)思路1(點(diǎn)的繪制)
- 在繪制之前首先確定繪制九點(diǎn)整體的位置工窍,這里將九點(diǎn)確定在居中
- 要想將九點(diǎn)分別按順序繪制在屏幕中割卖,要知道屏幕的寬高
- 因?yàn)榫劈c(diǎn)為三行三列所以我們可以講中間繪制九點(diǎn)的區(qū)域給一個(gè)正方形,將正方形在分為4 × 4的小正方形
- 接下來(lái)根據(jù)屏幕的寬高確定手機(jī)此時(shí)的橫豎屏狀態(tài)分別設(shè)置不同的偏移量和space(space為4×4小方格之一的邊長(zhǎng))的值
此圖為繪制九點(diǎn)之前的思路(豎屏狀態(tài))
下面我們先新建一個(gè)類 SudokuLockViewextends
(繼承)View
患雏,實(shí)現(xiàn)繼承的方法
重寫(xiě)onDraw
方法鹏溯,在onDraw
方法中首先判斷要繪制的九點(diǎn)的位置是否初始化,如果沒(méi)有則實(shí)現(xiàn)九點(diǎn)初始化的方法
private void initView() {
/**
* 屏幕寬高
*/
int pHigth = metrics.heightPixels;
int pWidth = metrics.widthPixels;
/**
* X淹仑,Y的偏移量
*/
float offsetX;
float offsetY;
float space; //小方格邊長(zhǎng)
/**
* 判斷橫豎屏設(shè)置對(duì)應(yīng)的值
*/
if (pHigth > pWidth){
offsetX = 0;
offsetY = (pHigth - pWidth)/2;
space = pWidth/4;
}else {
offsetX = (pWidth - pHigth)/2;
offsetY = 0;
space = pHigth/4;
}
//以下可以用雙層for循環(huán)更簡(jiǎn)便
/**one lines**/
myPoint[0][0] = new MyPoint(offsetX+space,offsetY+space);
myPoint[0][1] = new MyPoint(offsetX+space*2,offsetY+space);
myPoint[0][2] = new MyPoint(offsetX+space*3,offsetY+space);
/**two lines**/
myPoint[1][0] = new MyPoint(offsetX+space,offsetY+space*2);
myPoint[1][1] = new MyPoint(offsetX+space*2,offsetY+space*2);
myPoint[1][2] = new MyPoint(offsetX+space*3,offsetY+space*2);
/**three lines**/
myPoint[2][0] = new MyPoint(offsetX+space,offsetY+space*3);
myPoint[2][1] = new MyPoint(offsetX+space*2,offsetY+space*3);
myPoint[2][2] = new MyPoint(offsetX+space*3,offsetY+space*3);
}
初始化點(diǎn)的位置之后就可以開(kāi)始繪制點(diǎn)了(此處的九點(diǎn)可以通過(guò)Paint
繪制圓形的圖標(biāo)丙挽,也可以直接定義一個(gè)圖片資源,直接將圖片資源繪制出來(lái))匀借,此處用的第二種方法颜阐,同樣在初始的方法中添加資源圖標(biāo)的初始
/**添加點(diǎn)的圖片資源**/
nBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.onetests);
sBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.twotests);
eBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.threetests);
之后就可以直接繪制出
private void drawPoint(Canvas canvas) {
for (int i = 0;i<myPoint.length;i++){
for (int j = 0;j<myPoint[i].length;j++){
/**
* 當(dāng)然,此處可以判斷九點(diǎn)的不同的狀態(tài)吓肋,在繪制(正常的凳怨、選中的,錯(cuò)誤的)
*
* @bitR 為圖片資源的半徑是鬼,因?yàn)楫?huà)筆所繪制的不會(huì)是從中心電繪制肤舞,而是從左上角開(kāi)始繪制,在這里x均蜜,y各減去半徑萨赁,就會(huì)以圖標(biāo)中心的位置開(kāi)始繪制
*/
canvas.drawBitmap(sBitmap,myPoint[i][j].x-bitR,myPoint[i][j].y-bitR,paint);
}
}
}
好了,現(xiàn)在在XML文件中把我們自定義的這個(gè)View添加一下兆龙,運(yùn)行看看,九點(diǎn)的效果就出來(lái)了
實(shí)現(xiàn)思路2(用戶操作)
- 在用戶手勢(shì)監(jiān)聽(tīng)的方法
onTouchEvent
中分別有三種狀態(tài)(Down
·Move
·Up
) - 首先在用戶手指點(diǎn)下的時(shí)候,就要以x紫皇,y生成一個(gè)點(diǎn)慰安,并且將點(diǎn)返回,判斷點(diǎn)的位置是否為九點(diǎn)中任一點(diǎn)的位置聪铺,如果是添加選中的點(diǎn)化焕,并改變點(diǎn)的狀態(tài)
- 當(dāng)用戶手指移動(dòng)時(shí),同上铃剔,先判斷是否選擇的是九點(diǎn)中任意點(diǎn)撒桨,如果是,在此處再次判斷键兜,次點(diǎn)是否已經(jīng)包含在選中點(diǎn)的集合中凤类,如果沒(méi)有包含,改變點(diǎn)的狀態(tài)并添加
- 在用戶手指抬起的時(shí)候普气,先判斷所繪制的點(diǎn)的總數(shù)是否大于規(guī)定的最小數(shù)量谜疤,分別以點(diǎn)的不同狀態(tài)顯示所選最小數(shù)是否滿足,最后在判斷现诀,當(dāng)用戶操作屏幕后夷磕,并且選中點(diǎn)的數(shù)量大于0,那么就關(guān)閉繪制狀態(tài)
下面為當(dāng)用戶手指點(diǎn)下并且滑動(dòng)的時(shí)候生成的點(diǎn)仔沿,并且返回為選中的九點(diǎn)的任一點(diǎn)坐桩,沒(méi)選中的返回為null
/**
* 返回是否選擇的是點(diǎn)
*/
private int[] getSelectPoint() {
//MyPoint自定義的點(diǎn)的類 ,用戶手指按下時(shí)以x封锉,y生成的點(diǎn)
MyPoint begainSelectPoint = new MyPoint(moveX,moveY);
for (int i = 0;i<myPoint.length;i++){
for (int j = 0;j<myPoint[i].length;j++){
//判斷距離將選擇的點(diǎn)的位置否和一定條件時(shí)绵跷,為選中
if (myPoint[i][j].distance(begainSelectPoint) < bitR){
//定義長(zhǎng)度為2的數(shù)組,返回選中點(diǎn)的X烘浦,Y
int[] result = new int[2];
result[0] = i;
result[1] = j;
return result;
}
}
}
return null;//選中的不是九點(diǎn)的任一點(diǎn)時(shí)
}
下面上一下onTouchEvent
的方法(在此方法中在用戶沒(méi)操作的時(shí)候都要顯示選中點(diǎn)的狀態(tài)抖坪,所以要及時(shí)更新View,可以用this.postInvalidate();
方法闷叉,及時(shí)更新)
@Override
public boolean onTouchEvent(MotionEvent event) {
moveX = event.getX();
moveY = event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
if (isDrawing){
getSelect = getSelectPoint();//用int[]的類型接收
if (getSelect != null){
x = getSelect[0];//x
y = getSelect[1];//y
myPoint[x][y].start = MyPoint.SELECT;//設(shè)置點(diǎn)的狀態(tài)
allPoint.add(myPoint[x][y]);//添加點(diǎn)到選擇點(diǎn)的集合
}
}
break;
case MotionEvent.ACTION_MOVE:
if (isDrawing){
getSelect = getSelectPoint();
if (getSelect != null){
x = getSelect[0];
y = getSelect[1];
if (!allPoint.contains(myPoint[x][y])){//判斷是否已經(jīng)包含此點(diǎn)
myPoint[x][y].start = MyPoint.SELECT;
allPoint.add(myPoint[x][y]);
}
}
}
break;
case MotionEvent.ACTION_UP:
if (isDrawing){
if (allPoint.size() <= 3 && allPoint.size()>0){
Toast.makeText(getContext(),"至少不少于四點(diǎn)",Toast.LENGTH_SHORT).show();
for (int i = 0;i<allPoint.size();i++){
allPoint.get(i).start = MyPoint.ERROR;
}
}
}
if (allPoint.size() > 0){
isDrawing = false;
}
break;
}
this.postInvalidate();//及時(shí)更新
return true;
}
在onTouchEvent
方法之后就可以繪制線了擦俐,線的繪制是以兩點(diǎn)劃線,并且握侧,每次講第二次選擇的線賦值為初始點(diǎn)蚯瞧,下面給下選中九點(diǎn)的任一點(diǎn),和沒(méi)選中是線的繪制
private void drawPointLines(Canvas canvas) {
if (allPoint.size() > 0){
MyPoint A = allPoint.get(0);
for (int a = 1;a<allPoint.size();a++){
MyPoint B = allPoint.get(a);
drawLines(canvas,A,B);//此為選中九點(diǎn)時(shí)的劃線的方法
A = B;
}
if (isDrawing){
drawLines(canvas,A,new MyPoint(moveX,moveY));//當(dāng)處于繪制狀態(tài)時(shí)品擎,沒(méi)有選中時(shí)埋合,劃線就是一手指移動(dòng)而繪制
}
}
}
繪制線的方法,判斷選擇的點(diǎn)的個(gè)數(shù)萄传,繪制不同狀態(tài)的線
/**
* 通過(guò)兩點(diǎn)繪制線
* @param canvas
* @param a
* @param b
*/
private void drawLines(Canvas canvas, MyPoint a, MyPoint b) {
if (a.start == MyPoint.ERROR){
canvas.drawLine(a.x,a.y,b.x,b.y,epaint);
}else {
canvas.drawLine(a.x,a.y,b.x,b.y,paint);
}
}
用戶操作密碼記錄
- 上面我們?cè)谟脩舨僮鞯姆椒?code>onTouchEvent中用三種狀態(tài)甚颂,我們只需在用戶按下和移動(dòng)的狀態(tài)中添加判斷的方法,判斷用戶選擇的是當(dāng)前的哪一個(gè)點(diǎn),我們?cè)诮o每一個(gè)點(diǎn)設(shè)置不同的標(biāo)志值振诬,當(dāng)用戶保存時(shí)蹭睡,我們可以將用戶的選擇點(diǎn)的標(biāo)志保存起來(lái)即可(下面上下代碼)
private void setPassWord(int x, int y) {
if (myPoint[x][y] == myPoint[0][0]){
list.add("1");
}else if (myPoint[x][y] == myPoint[0][1]){
list.add("2");
}else if (myPoint[x][y] == myPoint[0][2]){
list.add("3");
}else if (myPoint[x][y] == myPoint[1][0]){
list.add("4");
}else if (myPoint[x][y] == myPoint[1][1]){
list.add("5");
}else if (myPoint[x][y] == myPoint[1][2]){
list.add("6");
}else if (myPoint[x][y] == myPoint[2][0]){
list.add("7");
}else if (myPoint[x][y] == myPoint[2][1]){
list.add("8");
}else if (myPoint[x][y] == myPoint[2][2]){
list.add("9");
}
}
上面的代碼我們可以生成一個(gè)方法,在用戶按下和移動(dòng)的操作中調(diào)用即可
好了赶么,九宮鎖到此結(jié)束肩豁,有更好思路的請(qǐng)告知,以上文章如有錯(cuò)誤辫呻,請(qǐng)熱情指正