屏幕锁案例

转载请注明出处:  http://blog.csdn.net/forwardyzk/article/details/42676213

现在的手机都有屏幕锁,有图案的,有数字的。下面介绍一个使用图案的屏幕锁。

思路:

1.根据屏幕的宽度,计算出9个点的坐标和半径。
2.使用画笔画出9个圆。
3.根据触摸的坐标判断是否在圆的范围之内,如果在圆的范围之内,表示此圆被触摸了。
4.根绝触摸圆的顺序,根据圆心,构建滑动的path,然后使用画笔画出。


计算圆的圆心和半径

int perSize = 0;
		if (cycles == null && (perSize = getWidth() / 6) > 0) {
			cycles = new MyCycle[9];
			for (int i = 0; i < 3; i++) {
				for (int j = 0; j < 3; j++) {
					MyCycle cycle = new MyCycle();
					cycle.setNum(i * 3 + j);
					cycle.setOx(perSize * (j * 2 + 1));
					cycle.setOy(perSize * (i * 2 + 1));
					cycle.setR(perSize * 0.5f);
					cycles[i * 3 + j] = cycle;
				}
			}
		}
根绝控件的宽度,将控件的宽度分为6部分,圆心在1,3,5的线上。

如图:



初始化画笔

paintNormal = new Paint();
		paintNormal.setAntiAlias(true);
		paintNormal.setStrokeWidth(3);
		paintNormal.setStyle(Paint.Style.STROKE);
setAntiAlias(true):设置线的边缘平滑

setStrokeWidth():设置线宽

setStyle()设置样式Paint.Style.STROKE ,Paint.Style.FILL,Paint.Style.FILL_STROKE


在onTouchEvevt()对触摸事件进行处理

public boolean onTouchEvent(MotionEvent event) {
		if (canContinue) {
			switch (event.getAction()) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_MOVE: {
				eventX = (int) event.getX();
				eventY = (int) event.getY();
				for (int i = 0; i < cycles.length; i++) {
					if (cycles[i].isPointIn(eventX, eventY)) {
						cycles[i].setOnTouch(true);
						if (!linedCycles.contains(cycles[i].getNum())) {
							linedCycles.add(cycles[i].getNum());
						}
					}
				}
				break;
			}
			case MotionEvent.ACTION_UP: {
				// 暂停触碰
				canContinue = false;
				if (linedCycles.size() >= minCountCycle) {// 大于等于连接圆的最小个数
					// 检查结果
					StringBuffer sb = new StringBuffer();
					for (int i = 0; i < linedCycles.size(); i++) {
						sb.append(linedCycles.get(i));
					}
					result = key.equals(sb.toString());
					if (onGestureFinishListener != null) {
						onGestureFinishListener.OnGestureFinish(result);
					}
				} else {
					Toast.makeText(getContext(), "最少连接" + minCountCycle + "个圆",
							0).show();
				}
				timer = new Timer();
				timer.schedule(new TimerTask() {
					@Override
					public void run() {
						// 还原
						eventX = eventY = 0;
						for (int i = 0; i < cycles.length; i++) {
							cycles[i].setOnTouch(false);
						}
						linedCycles.clear();
						linePath.reset();
						canContinue = true;
						postInvalidate();
					}
				}, 1000);
				break;
			}
			}
			invalidate();
		}
		return true;
	}

MotionEvent.ACTION_DOWN和MotionEvent.ACTION_MOVE中根据按下和移动的坐标,判断是在那一个圆形图形范围内,如在其范围内,那么就添加到一个保存触摸的圆的集合中。为了计算其滑动的线路和判断线路是否正确。在添加之前,要保证集合中没有此圆,否则线路就会重复。

MotionEvent.ACTION_UP:在手指离开的时候,根绝存放触摸圆的集合,计算其触摸的顺序(形成的图形)是否正确,是根绝圆对象的代表的数字做判断。当手指离开时,把计算结果通过接口传递出去。

public class MyCycle {
	private int ox;          // 圆心横坐标
	private int oy;          // 圆心纵坐标
	private float r;         // 半径长度
	private Integer num;     // 代表数值
	private boolean onTouch; // false=未选中
	public int getOx() {
		return ox;
	}
	public void setOx(int ox) {
		this.ox = ox;
	}
	public int getOy() {
		return oy;
	}
	public void setOy(int oy) {
		this.oy = oy;
	}
	public float getR() {
		return r;
	}
	public void setR(float r) {
		this.r = r;
	}
	public Integer getNum() {
		return num;
	}
	public void setNum(Integer num) {
		this.num = num;
	}
	public boolean isOnTouch() {
		return onTouch;
	}
	public void setOnTouch(boolean onTouch) {
		this.onTouch = onTouch;
	}
	public boolean isPointIn(int x, int y) {
		double distance = Math.sqrt((x - ox) * (x - ox) + (y - oy) * (y - oy));
		return distance < r;
	}

判断是否在其范围内是亮点之间的距离是否小于半径来做判断。

要记得最后离开的后,延迟清除触摸的图形。

在onDraw方法中,根绝触摸的顺序,触摸的状态随时更改图形的颜色。

protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		for (int i = 0; i < cycles.length; i++) {
			if (!canContinue && !result) {
				paintOnTouch.setColor(ERROR_COLOR);
				paintInnerCycle.setColor(ERROR_COLOR);
				paintLines.setColor(ERROR_COLOR);
			} else if (cycles[i].isOnTouch()) {
				paintOnTouch.setColor(OUT_CYCLE_ONTOUCH);
				paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);
				paintLines.setColor(LINE_COLOR);
			} else {
				paintNormal.setColor(OUT_CYCLE_NORMAL);
				paintInnerCycle.setColor(INNER_CYCLE_ONTOUCH);
				paintLines.setColor(LINE_COLOR);
			}
			if (cycles[i].isOnTouch()) {
				if (!isShowPattern) {
					canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),
							cycles[i].getR(), paintNormal);
				} else {

					canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),
							cycles[i].getR(), paintOnTouch);
					drawInnerBlueCycle(cycles[i], canvas);
				}
			} else {
				canvas.drawCircle(cycles[i].getOx(), cycles[i].getOy(),
						cycles[i].getR(), paintNormal);
			}
		}
		drawLine(canvas);
	}


有四中画笔,paintNormal:正常显示的使用的画笔,paintOnTouch:触摸后的外圆使用的画笔,paintInnerCycle:触摸后的内圆使用的画笔,paintLines:连线使用的画笔。

根绝当前的状态,设置画笔的的颜色,颜色如下

对应五种颜色

private int OUT_CYCLE_NORMAL = Color.rgb(108, 119, 138); // 正常外圆颜色
	private int OUT_CYCLE_ONTOUCH = Color.rgb(025, 066, 103); // 选中外圆颜色
	private int INNER_CYCLE_ONTOUCH = Color.rgb(002, 210, 255); // 选择内圆颜色
	private int LINE_COLOR = Color.argb(127, 002, 210, 255); // 连接线颜色
	private int ERROR_COLOR = Color.argb(127, 255, 000, 000); // 连接错误醒目提示颜色

画出触摸的线路

private void drawLine(Canvas canvas) {
		if (!isShowPattern) {
			return;
		}
		linePath.reset();
		if (linedCycles.size() > 0) {
			for (int i = 0; i < linedCycles.size(); i++) {
				int index = linedCycles.get(i);
				float x = cycles[index].getOx();
				float y = cycles[index].getOy();
				if (i == 0) {
					linePath.moveTo(x, y);
				} else {
					linePath.lineTo(x, y);
				}
			}
			if (canContinue) {
				linePath.lineTo(eventX, eventY);
			} else {
				linePath.lineTo(
						cycles[linedCycles.get(linedCycles.size() - 1)].getOx(),
						cycles[linedCycles.get(linedCycles.size() - 1)].getOy());
			}
			canvas.drawPath(linePath, paintLines);
		}
	}
根绝触摸过的圆的圆心,按照顺序把圆心连接起啦,就构成了连接的线路。

使用的主要方法有:

setMinCountCycle(int minCountCycle):设置连接最小圆的个数,默认为1

setShowPattern(boolean isShowPath):是否显示连接的图案,默认显示

setOnGestureFinishListener(
OnGestureFinishListener onGestureFinishListener):设置结果返回值监听

setKey(String key):设置正确图案代表的值

==========================================

设置画笔的颜色和线宽,不设置有默认值

setErrorColor(int color):结果错误显示的颜色

setLinesPaint(float width, int color):设置连线的线宽和颜色

setNormalPaint(float width, int color):设置默认外圆展示的线宽和颜色

setOnTouchPaint(float width, int color):设置触摸外圆的线宽和颜色

setInnerCyclePaint(float width, int color):设置触摸内圆的线宽和颜色


使用步骤:

<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:background="@drawable/start_background"
    tools:context=".MainActivity" >

    <com.example.view.GestureLockView
        android:id="@+id/gv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="#0000" />

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

	private GestureLockView gv;
	private SharedPreLockUtils spUtil;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		spUtil = SharedPreLockUtils.getInstance(getApplicationContext());
		gv = (GestureLockView) findViewById(R.id.gv);
		gv.setKey("0124678"); // Z 字型
		gv.setOnGestureFinishListener(new OnGestureFinishListener() {
			@Override
			public void OnGestureFinish(boolean success) {
				Toast.makeText(MainActivity.this, String.valueOf(success),
						Toast.LENGTH_SHORT).show();
				if (success) {
					startSettingActivity();
				}
			}
		});
		gv.setShowPattern(spUtil.getIsShowPattern());
	}

	public void startSettingActivity() {
		MainActivity.this.startActivity(new Intent(MainActivity.this,
				SettingActivity.class));
	}

	@Override
	protected void onResume() {
		super.onResume();
		gv.setShowPattern(spUtil.getIsShowPattern());
		if (spUtil.getBoolean("ISCHANGE", false)) {
			gv.setNormalPaint(
					3f,
					MainActivity.this.getResources().getColor(
							android.R.color.holo_red_light));
			gv.setLinesPaint(
					10f,
					MainActivity.this.getResources().getColor(
							android.R.color.holo_green_light));
			gv.setInnerCyclePaint(25f, MainActivity.this.getResources()
					.getColor(android.R.color.darker_gray));
			gv.setOnTouchPaint(
					10f,
					MainActivity.this.getResources().getColor(
							android.R.color.holo_orange_dark));
			gv.setErrorColor(

			MainActivity.this.getResources().getColor(
					android.R.color.holo_purple));
		}
	}
}

使用了滑动开关,其使用方法请参考自定义滑动开关

源码下载: http://download.csdn.net/detail/forwardyzk/8357367

效果图:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值