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;

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;

}

}

}

}

时间: 2024-09-21 06:47:31

android 九宫格滑动解锁开机实例源码学习的相关文章

android 九宫格滑动解锁开机实例源码学习_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管理与操作Wifi简单实例源码_Android

因为需要一直在弄网络的问题,今天看了一下Wifi的操作,经过整理,做出来了一个类,可能不全,但是个人感觉已经完全能够满足需要了,当然,里面的方法也有可能是错误的或者是不全的,这个类我没有进行完整的测试,只测试了其中的一些方法. 其实操作Wifi也是很简单的,主要使用以下几个对象或变量: private WifiManager wifiManager;// 声明管理对象OpenWifi private WifiInfo wifiInfo;// Wifi信息 private List<ScanRes

Android管理与操作Wifi简单实例源码

因为需要一直在弄网络的问题,今天看了一下Wifi的操作,经过整理,做出来了一个类,可能不全,但是个人感觉已经完全能够满足需要了,当然,里面的方法也有可能是错误的或者是不全的,这个类我没有进行完整的测试,只测试了其中的一些方法. 其实操作Wifi也是很简单的,主要使用以下几个对象或变量: private WifiManager wifiManager;// 声明管理对象OpenWifi private WifiInfo wifiInfo;// Wifi信息 private List<ScanRes

Android通过访问网页查看网页源码实例详解

Android通过访问网页查看网页源码 1.添加网络权限 <!--访问网络的权限--> <uses-permission android:name="android.permission.INTERNET"/> 2.获取网络中网页的数据 /** * 获取网页HTML源代码 * @param path 网页路径 */ public static String getHtml(String path) throws Exception { URL url=new U

Android入门之使用eclipse进行源码开发的方法_Android

本文实例讲述了Android入门之使用eclipse进行源码开发的方法.分享给大家供大家参考,具体如下: 一.版本说明: 1. eclipse for javaEE 3.5.2 2. jdk1.6 3. adt12.0 4. linux/Ubuntu10.04 或者 linux/ubuntu10.10 二.准备工作: 1. 下载 Android2.3.7 源码 欲了解具体内容可以参看 android 官网. 2. 编译源码 必须编译源码,否则会引发很多问题.记住:如果下载没问题的话,编译只是时间

基于jQuery和hwSlider实现内容左右滑动切换效果附源码下载(一)_jquery

内容滑动切换应用非常广,常见的有幻灯片焦点图.画廊切换等.随着WEB前端技术的广泛应用,内容滑动切换效果占据着web页面重要地位,因此本站Helloweba特别给广大前端爱好者安排了浅显易懂的内容滑动切换效果的开发教程. 先给大家展示下效果图,感觉还不错请参数实现代码,具体效果如下所示: 效果展示      源码下载 本次教程分三个部分: 1.使用jQuery开发基本的内容滑动切换效果, 2.支持移动端触控自适应的内容滑动切换效果, 3.封装内容滑动切换效果jQuery插件. 本文讲解第一部分,

Android入门之使用eclipse进行源码开发的方法

本文实例讲述了Android入门之使用eclipse进行源码开发的方法.分享给大家供大家参考,具体如下: 一.版本说明: 1. eclipse for javaEE 3.5.2 2. jdk1.6 3. adt12.0 4. linux/Ubuntu10.04 或者 linux/ubuntu10.10 二.准备工作: 1. 下载 Android2.3.7 源码 欲了解具体内容可以参看 android 官网. 2. 编译源码 必须编译源码,否则会引发很多问题.记住:如果下载没问题的话,编译只是时间

ASP.Net C#2.0全能数据库组件 (含下载实例源码地址)

asp.net|数据|数据库|下载 /* ?--------------------------?   | Title: ASP.Net C#2.0全能数据库组件 (开源含实例源码)|   | Project: DBOperatorService.Data                    |   | Subarea: DataSet                                   |   | Author: ξ箫音ξ                           

C# .net热力图实例源码

问题描述 C# .net热力图实例源码 谁有C#热力图的实例,求地址求链接,或者谁知道能在哪里学习也好,谢谢了谢谢 解决方案 http://echarts.baidu.com/doc/feature.html 自己去研究一下吧,这个是不限编程语言的,JS的一个库. ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前绝大部分浏览器(IE6/7/8/9/10/11,chrome,firefox,S