屏幕锁案例

转载请注明出处:  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

效果图:

时间: 2024-10-09 03:53:18

屏幕锁案例的相关文章

Android下屏幕锁屏弹窗的正确姿势

最近在做一个关于屏幕锁屏悬浮窗的功能,于是在网上搜索了很多安卓屏幕锁屏的相关资料,鉴于网上的资料比较零碎,所以我在这里进行整理总结.本文将从以下两点对屏幕锁屏进行解析: 1. 如何监听系统屏幕锁屏 2. 如何在锁屏界面弹出悬浮窗 如何监听系统屏幕锁屏 经过总结,监听系统的锁屏可以通过以下两种方式: 1) 代码直接判定 2) 接收广播 1) 代码直接判定 代码判断方式,也有两种方法: a) 通过PowerManager的isScreenOn方法,代码如下: PowerManager pm = (P

BroadcastReceiver之屏幕锁屏和解锁监听

对于解锁和锁屏这种用的比较频繁action,谷歌做了限制,必须手动用代码注册 直接上代码:这是注册广播 1 public class MainActivity extends AppCompatActivity { 2 Screen screen; 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.l

屏幕锁屏以及解锁监听

屏幕锁屏以及解锁时会分别发送两个广播SCREEN_ON和SCREEN_OFF,但是这两个action只能通过代码的形式注册才能被监听到,在AndroidManifest.xml中注册根本监听不到. public class ScreenActionReceiver extends BroadcastReceiver { private String TAG = "ScreenActionReceiver"; private boolean isRegisterReceiver = fa

Android判断屏幕锁屏的步骤总结

总共有两类方法: 一.代码直接判定 二.接收广播 现在先说第一类方法(代码直接判定): 1.通过PowerManager的isScreenOn方法,代码如下: PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); boolean isScreenOn = pm.isScreenOn();//如果为true,则表示屏幕“亮”了,否则屏幕“暗”了. 注释已经写的很明白了,现在大概说一下, 屏

android 电源管理,屏幕锁 ,小米2s点亮屏幕,解锁

============问题描述============ 我现在进行的是,通信方面的项目.但是当小米2s测试  来电   的时候,屏幕点亮了,但是没有屏幕没有解锁,只有解锁之后才会出现来点界面.问了别人,说是要看android这个方面的底层,我不知道有什么好的解决办法没有? 这个是电源管理以及解锁屏幕的代码: //保持屏幕常亮 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); WakeLock mW

Android判断屏幕锁屏的方法总结

转载请注明:http://blog.csdn.net/heroxuetao/article/details/24639203 由于做一个项目,需要判断屏幕是否锁屏,发现网上方法很多,但是比较杂,现在进行总结一下: 总共有两类方法: 一.代码直接判定 二.接收广播 现在先说第一类方法(代码直接判定): 1.通过PowerManager的isScreenOn方法,代码如下: PowerManager pm = (PowerManager) context.getSystemService(Conte

Android 解屏幕锁与点亮屏幕(来电时效果)

PowerManager pm=(PowerManager) getSystemService(Context.POWER_SERVICE); //获取电源管理器对象 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright"); //获取PowerManager.WakeLock对象,后面的参数|表示

转载:android.屏幕锁,解锁,在取证上的应用

中国司法-鉴定,2013年第06期杂志

简单的js特效,背景圆球滚动,类似电脑屏幕锁屏气球

html <div class="banner"> <div class="dot dot0"></div> <div class="dot dot1"></div> <div class="dot dot2"></div> <div class="dot dot3"></div> <div c