- 在之前的demo上面继续实行这个密码解锁功能
- 首先我们先在xml了里面创建一个页面并且在xmlns里面定义一个id号保存原始页面
android:id="@+id/root_layout"
- 定义一些全局变量
//定义一个数组保存控件
ArrayList dotList;
ArrayList lineTagList;
ArrayList selectedList;
//定义一个tag变量
int tag;
//保存上一次被点亮的对象
ImageView lastSelectedDot;
//记录滑动的密码
StringBuilder password;
//提示的文本视图
TextView alertTextView;
//请保存原始密码
String orgPassword;
//保存第一次输入的密码
String firstPassword;
- 定义点和线
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//判断是否已经显示
if (hasFocus) {
//获取容器
RelativeLayout rl = findViewById(R.id.root_layout);
//获取背景视图
ImageView iv = findViewById(R.id.opView);
//获取x和y的坐标
int x = iv.getLeft();
int y = iv.getTop();
//获取屏幕密度
float scale = getResources().getDisplayMetrics().density;
//创建横线 6条
tag=12;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图用于显示线
ImageView lineView = new ImageView(this);
lineView.setVisibility(View.INVISIBLE);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight1);
lineView.setTag(tag);
lineTagList.add(tag);//保存线的tag值
tag+=11;//同一行加上11
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 46.6 * scale) + (int) (99 * scale * j);
params.topMargin = (int) (y + 170 * scale) + (int) (99 * scale * i);
rl.addView(lineView, params);
}
//换一行加上相差22
tag+=11;
}
//创建竖线 6条
tag=14;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
//创建一个视图用于显示线
ImageView lineView = new ImageView(this);
lineView.setVisibility(View.INVISIBLE);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight2);
lineView.setTag(tag);
lineTagList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 42 * scale) + (int) (99 * scale * j);
params.topMargin = (int) (y + 170 * scale) + (int) (99 * scale * i);
rl.addView(lineView, params);
}
}
//创建右斜线 4条
tag=15;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图用于显示线
ImageView rlineView = new ImageView(this);
rlineView.setVisibility(View.INVISIBLE);
//设置图片
rlineView.setBackgroundResource(R.drawable.normal_highlight3);
rlineView.setTag(tag);
lineTagList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 42 * scale) + (int) (99 * scale * j);
params.topMargin = (int) (y + 170 * scale) + (int) (99 * scale * i);
rl.addView(rlineView, params);
}
tag+=11;
}
//创建左斜线 4条
tag=24;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图用于显示线
ImageView llineView = new ImageView(this);
llineView.setVisibility(View.INVISIBLE);
//设置图片
llineView.setBackgroundResource(R.drawable.normal_highlight4);
llineView.setTag(tag);
lineTagList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 53.3 * scale) + (int) (99 * scale * j);
params.topMargin = (int) (y + 170 * scale) + (int) (99 * scale * i);
rl.addView(llineView, params);
}
tag+=11;
}
//创建9个点
tag=1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//创建用于显示点的视图
ImageView dotView = new ImageView(this);
//设置对应的tag值
dotView.setTag(tag);
tag++;
//隐藏视图
dotView.setVisibility(View.INVISIBLE);
//显示对应的图片
dotView.setBackgroundResource(R.drawable.selected_dot);
//创建控件的尺寸
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams
(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 35 * scale) + (int) (99 * scale * j);
params.topMargin = (int) (y + 164 * scale) + (int) (99 * scale * i);
//将控件添加到容器中
rl.addView(dotView, params);
//将这个控件添加到数组
dotList.add(dotView);
System.out.println(dotView.getTag());
}
}
}
}
- 定义一个监听事件
//监听触摸事件
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取事件类型
int action = event.getAction();
//判断是什么事件
ImageView selected;
//获取触摸点的坐标
float x;
float y;
switch (action) {
case MotionEvent.ACTION_DOWN:
//按下
//获取触摸点的坐标
x = event.getX();
y = event.getY();
//判断x和y是不是在某个点的范围内
selected=dotOfTouch(x,y);
if (selected!=null) {
//点亮
selected.setVisibility(View.VISIBLE);
//记录当前这个点
lastSelectedDot=selected;
//将tag值拼接到密码中
password.append(selected.getTag());
//将点亮的点添加到数组中
selectedList.add(selected);
}
break;
case MotionEvent.ACTION_MOVE:
//滑动
//获取触摸点的坐标
x = event.getX();
y = event.getY();
//判断x和y是不是在某个点的范围内
selected=dotOfTouch(x,y);
if (selected!=null) {
//判断这个点是不是起始点
if (lastSelectedDot==null){
//第一个点 点亮
selected.setVisibility(View.VISIBLE);
//记录
lastSelectedDot=selected;
//将tag值拼接到密码中
password.append(selected.getTag());
//将点亮的点添加到数组中
selectedList.add(selected);
}else {
//不是第一个点
//获取上一个点和当前点的tag
int lTag=(Integer) lastSelectedDot.getTag();
int cTag=(Integer)selected.getTag();
//获取两个线的tag值 small*10+big
int lineTag=lTag>cTag?cTag*10+lTag:lTag*10+cTag;
//判断这条线是否存在
if (lineTagList.contains(lineTag)){
//线存在
//点亮点
selected.setVisibility(View.VISIBLE);
//将tag值拼接到密码中
password.append(selected.getTag());
//获取容器对象
RelativeLayout rl=findViewById(R.id.root_layout);
//通过tag值查找子控件
ImageView iv=rl.findViewWithTag(lineTag);
//点亮线
iv.setVisibility(View.VISIBLE);
//记录这个点
lastSelectedDot=selected;
//将点亮的点添加到数组中
selectedList.add(selected);
//将点亮的线添加到数组中
selectedList.add(iv);
}
}
}
break;
case MotionEvent.ACTION_UP:
//离开
// 1.绘制密码 和原始密码比较
//2.设置密码 第一次
//3.设置密码 第二次
if (orgPassword!=null){
//有密码
if (password.toString().equals(orgPassword)){
alertTextView.setText("解锁密码成功");
}else {
alertTextView.setText("解锁密码失败");
}
}else {
//设置密码
//判断第一次还是第二次确认密码
if (firstPassword==null){
//设置密码的第一次
firstPassword=password.toString();
//提示确认密码
alertTextView.setText("请确认密码图案");
}else {
//确认密码
//判断两次是否一致
if (firstPassword.equals(password.toString())){
//设置成功
alertTextView.setText("设置密码成功");
//保存密码
SharedPreferences sp=getSharedPreferences("password",0);
SharedPreferences.Editor editor=sp.edit();
editor.putString("pwd",firstPassword);
editor.commit();
}else {
//设置失败
alertTextView.setText("两次密码不一致 请重新绘制");
firstPassword=null;
}
}
}
clean();
break;
default:
break;
}
return true;
}
- 定义一个清空的方法
//清空
public void clean(){
password.setLength(0);
//隐藏所有选中的视图 点 线
for (ImageView iv:selectedList){
iv.setVisibility(View.INVISIBLE);
}
//清空数组
selectedList.clear();
}
- 定义一个方法判断触摸点是否在某个控件的内部
public ImageView dotOfTouch(float x,float y){
//遍历数组
for (ImageView dot:dotList){
//获取dot相对于屏幕的x y
int[] loc=new int[2];
dot.getLocationOnScreen(loc);
int dx=loc[0];
int dy=loc[1];
//获取在右边的偏移量
int r=dx+dot.getWidth();
//获取最底部偏移量
int b=dy+dot.getHeight();
if ((x<=r&&x>=dx)&&(y<=b&&y>=dy)){
return dot;
}
}
return null;
}
- 在onCreate里面实现
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//准备好数组
dotList = new ArrayList<>();
lineTagList=new ArrayList<>();
password=new StringBuilder();
selectedList=new ArrayList<>();
//获取xml文本控件
alertTextView=findViewById(R.id.tv_alert);
//查找偏好设置里面是否有保存的密码pwd
SharedPreferences sp=getSharedPreferences("password",MODE_PRIVATE);
//获取pwd对应的密码
orgPassword=sp.getString("pwd",null);
if (orgPassword==null){
alertTextView.setText("请设置密码图案");
}else {
alertTextView.setText("请绘制密码图案");
}
}
}
总结
看着这些代码一行一行的实现demo一步一步的体现出来感觉计算机真的魅力太大了这些代码的写出来然后就变成我们想要的东西,虽然我不是很理解这个demo但是下来还是会自己多写几遍的,希望熟能生巧吧。