Android_开发Day23图案解锁
目的:
综合运用Java以及C语言的思想来解决问题
技术:
<1> onTouchEvent:
onTouchEvent方法是当屏幕被触摸时系统调用的方法,MotionEvent是获取触摸信息,可以通过该类的getAction()方法来得到触摸事件的类型,该方法的返回值是一个整型,因此可以通过判断数值来判断是什么手势,常用的手势有:
MotionEvent.ACTION_DOWN(点按屏幕)
MotionEvent.ACTION_MOVE(屏幕滑动)
MotionEvent.ACTION_UP(手指抬起)
<2> SharedPreferences:
SharedPreferences是一个与文件操作相关的类主要是储存一些小数据还是基本数据,如文本。SharedPreferences在创建对象时不能用构造方法要用getSharedPreferences("文件名", 读写方式)函数来创建,其中的即可读也可写的方式用数值0表示,一般就用该方式,值得注意的是任何一个SharedPreferences对象只能读数据不能写,因为写需要用该类的一个内部类来实现SharedPreferences.Editor类,调用SharedPreferences里面的edit()方法就能够得到一个SharedPreferences.Editor对象,然后用调用方法putString("键", 值)来写入字符串,当然不止这个方法还有putInt(),putFloat()等方法但是只能放一些基本数据类型。但是这里我们只需要放字符串就够了所以用SharedPreferences。
技术如何使用:
接着上次的图案解锁,创建好界面后就将点与线隐藏,当用户划过点时点亮点,划过两个点时判断两点之间有没有线连接,如果有就点亮点和之间的线,如何判断用户是否划过点呢,由于每个点是一个图片,因此只要获取点按的坐标看是否在图片所在的区域就行了。代码如下:
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//移动
//获取x,y
if (!isUnclock) {
x = event.getX();
y = event.getY();
//判断
select = dotOfTouch(x, y);
if (select != null) {
//判断是不是第一个点
if (lastTag == null) {
//点亮这个点
select.setVisibility(View.VISIBLE);
//记录这个点
lastTag = select;
} else {
//不是第一个
//获取两个点的tag值
int lTag = (Integer) lastTag.getTag();
int cTag = (Integer) select.getTag();
//获取线的tag
Integer lineTag = lTag > cTag ? cTag * 10 + lTag : lTag * 10 + cTag;
//判断是否在一条直线
for (Integer num : onALine) {
String newNum = num.toString();
String newLinTad = lineTag.toString();
if (newLinTad.startsWith(newNum.substring(0, 1)) && newLinTad.endsWith(newNum.substring(2))) {
String nNum1 = newNum.substring(0, 1) + newNum.substring(1, 2);
String nNum2 = newNum.substring(1, 2) + newNum.substring(2);
if (select.getVisibility() != View.VISIBLE) {
RelativeLayout relativeLayout = findViewById(R.id.cl_main);
ImageView imageView = relativeLayout.findViewWithTag(Integer.parseInt(nNum1));
ImageView imageView1 = relativeLayout.findViewWithTag(Integer.parseInt(nNum2));
ImageView dot = relativeLayout.findViewWithTag(Integer.parseInt(newNum.substring(1, 2)));
dot.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
imageView1.setVisibility(View.VISIBLE);
select.setVisibility(View.VISIBLE);
if (password.length() > 0) {
password.append(nNum1.substring(1, 2));
password.append(select.getTag());
} else {
password.append(lastTag.getTag());
password.append(nNum1.substring(1, 2));
password.append(select.getTag());
}
lastTag = select;
}
}
}
//判断这条线是否存在
if (lineList.contains(lineTag)) {
//点亮点
//点亮线
if (select.getVisibility() != View.VISIBLE) {
select.setVisibility(View.VISIBLE);
RelativeLayout rl = findViewById(R.id.cl_main);
ImageView iv = rl.findViewWithTag(lineTag);
iv.setVisibility(View.VISIBLE);
//记录
if (password.length() == 0) {
password.append(lastTag.getTag());
password.append(select.getTag());
} else {
password.append(select.getTag());
}
lastTag = select;
}
}
}
}
}
break;
case MotionEvent.ACTION_UP:
//抬起
//保存密码
if (!isUnclock) {
if (password.length() > 0) {
if (hasPassword == false) {
//没有密码
if (password1 == null) {
//第一次
text.setText("请确认密码");
hide();
password1 = password.toString();
password.replace(0, password.length(), "");
} else {
System.out.println(password1 + "___" + password + "____" + password1.length() + "___" + password.length());
//有密码了
if (password1.equals(password.toString())) {
text.setText("密码设置成功");
//保存密码
SharedPreferences sp = getSharedPreferences("password", 0);
SharedPreferences.Editor editor = sp.edit();
editor.putString("pwd", password.toString());
editor.commit();
} else {
text.setText("两次密码绘制不一致,请重新绘制");
hide();
password.replace(0, password.length(), "");
password1 = null;
}
}
} else {
if (getPassword1.equals(password.toString())) {
text.setText("解锁成功");
ImageView iv = findViewById(R.id.iv_p8);
hide();
iv.setVisibility(View.VISIBLE);
isUnclock = true;
} else {
text.setText("密码错误,请重新绘制");
hide();
password.replace(0, password.length(), "");
}
}
}
}
break;
default:
break;
}
return true;
}
//写一个方法判断触摸点是否在某个控件内部
public ImageView dotOfTouch(float x,float y){
//遍历数组
int[] loc = new int[2];
for (ImageView dot: dotsList) {
dot.getLocationOnScreen(loc);
if ((x <= loc[0] + dot.getWidth() && x >= loc[0]) && (y <= loc[1] + dot.getHeight() && y >= loc[1])){
return dot;
}
}
return null;
}
//将所有的已经显示的控件隐藏
public void hide(){
for (ImageView dot:dotsList) {
dot.setVisibility(View.INVISIBLE);
}
RelativeLayout rl = findViewById(R.id.cl_main);
for (Integer i: lineList) {
rl.findViewWithTag(i).setVisibility(View.INVISIBLE);
lastTag = null;
}
}
当然我们不能光做出效果还要有点实际的东西,需要记录密码,为每个点设置tag值,一般是按照123456789来的,因此点亮一个点时需要记录该点的tag值并与之前的值连接起来形成一个字符串,就是密码了,因此可以将这个密码存到文件中就行了,下次打开时密码就不用设置了。到这里整个项目就结束了,整体代码可以展示出来:
public class MainActivity extends AppCompatActivity {
ArrayList dotsList;
ArrayList lineList;
int tag;
ImageView lastTag;
StringBuilder password = new StringBuilder();
TextView text;
String password1 = null;
boolean hasPassword;
String getPassword1;
boolean isUnclock = false;
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
//获取屏幕密度
float a = getResources().getDisplayMetrics().density;
//判断是否已经显示
if (hasFocus) {
//获取容器
RelativeLayout rl = findViewById(R.id.cl_main);
//获取背景视图
ImageView iv = findViewById(R.id.opView);
//获取x和y
int x = iv.getLeft();
int y = iv.getTop();
//创建横线
tag = 1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView = new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight1);
//设置tag值
tag+=11;
lineView.setTag(tag);
//加tag值
lineList.add(tag);
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 46.6 * a + 99 * a * j);
params.topMargin = (int) (y + 170 * a + 99 * a * i);
rl.addView(lineView, params);
//lineView.setVisibility(View.INVISIBLE);
}
tag+=11;
}
//创建竖线
tag = 14;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
//创建一个视图显示线
ImageView lineView = new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight2);
//添加tag值
lineView.setTag(tag);
//加tag值
lineList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 42 * a + 99 * a * j);
params.topMargin = (int) (y + 170 * a + 99 * a * i);
rl.addView(lineView, params);
//lineView.setVisibility(View.INVISIBLE);
}
}
//创建右竖线
tag = 15;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView = new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight3);
//添加tag值
lineView.setTag(tag);
//加tag值
lineList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 42 * a + 99 * a * j);
params.topMargin = (int) (y + 170 * a + 99 * a * i);
rl.addView(lineView, params);
//lineView.setVisibility(View.INVISIBLE);
}
tag+=11;
}
//创建左竖线
tag = 24;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
//创建一个视图显示线
ImageView lineView = new ImageView(this);
//设置图片
lineView.setBackgroundResource(R.drawable.normal_highlight4);
//设置tag值
lineView.setTag(tag);
//加tag值
lineList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = (int) (x + 54 * a + 99 * a * j);
params.topMargin = (int) (y + 170 * a + 99 * a * i);
rl.addView(lineView, params);
//lineView.setVisibility(View.INVISIBLE);
}
tag+=11;
}
//九个点
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++);
//隐藏视图
dotView.setVisibility(View.VISIBLE);
//显示对应的图片
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 * a + 99 * a * j);
params.topMargin = (int) (y + 164 * a + 99 * a * i);
//将子控件添加到容器中
rl.addView(dotView, params);
//dotView.setVisibility(View.INVISIBLE);
//将控件放到数组里面
dotsList.add(dotView);
}
}
}
}
int[] onALine = {123,456,789,147,159,258,369,357};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println("here");
dotsList = new ArrayList<>();
lineList = new ArrayList<>();
text = findViewById(R.id.tv_text);
//显示请设置密码
SharedPreferences sp = getSharedPreferences("password",0);
if (sp.getString("pwd",null) == null) {
text.setText("请设置密码");
hasPassword = false;
}else {
text.setText("请绘制您的图案");
getPassword1 = sp.getString("pwd",null);
hasPassword = true;
}
ImageView iv = findViewById(R.id.iv_p8);
iv.setVisibility(View.INVISIBLE);
}
float x;
float y;
ImageView select;
Integer a = 1;
int i = 0;
//监听事件
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action){
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//移动
//获取x,y
if (!isUnclock) {
x = event.getX();
y = event.getY();
//判断
select = dotOfTouch(x, y);
if (select != null) {
//判断是不是第一个点
if (lastTag == null) {
//点亮这个点
select.setVisibility(View.VISIBLE);
//记录这个点
lastTag = select;
} else {
//不是第一个
//获取两个点的tag值
int lTag = (Integer) lastTag.getTag();
int cTag = (Integer) select.getTag();
//获取线的tag
Integer lineTag = lTag > cTag ? cTag * 10 + lTag : lTag * 10 + cTag;
//判断是否在一条直线
for (Integer num : onALine) {
String newNum = num.toString();
String newLinTad = lineTag.toString();
if (newLinTad.startsWith(newNum.substring(0, 1)) && newLinTad.endsWith(newNum.substring(2))) {
String nNum1 = newNum.substring(0, 1) + newNum.substring(1, 2);
String nNum2 = newNum.substring(1, 2) + newNum.substring(2);
if (select.getVisibility() != View.VISIBLE) {
RelativeLayout relativeLayout = findViewById(R.id.cl_main);
ImageView imageView = relativeLayout.findViewWithTag(Integer.parseInt(nNum1));
ImageView imageView1 = relativeLayout.findViewWithTag(Integer.parseInt(nNum2));
ImageView dot = relativeLayout.findViewWithTag(Integer.parseInt(newNum.substring(1, 2)));
dot.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
imageView1.setVisibility(View.VISIBLE);
select.setVisibility(View.VISIBLE);
if (password.length() > 0) {
password.append(nNum1.substring(1, 2));
password.append(select.getTag());
} else {
password.append(lastTag.getTag());
password.append(nNum1.substring(1, 2));
password.append(select.getTag());
}
lastTag = select;
}
}
}
//判断这条线是否存在
if (lineList.contains(lineTag)) {
//点亮点
//点亮线
if (select.getVisibility() != View.VISIBLE) {
select.setVisibility(View.VISIBLE);
RelativeLayout rl = findViewById(R.id.cl_main);
ImageView iv = rl.findViewWithTag(lineTag);
iv.setVisibility(View.VISIBLE);
//记录
if (password.length() == 0) {
password.append(lastTag.getTag());
password.append(select.getTag());
} else {
password.append(select.getTag());
}
lastTag = select;
}
}
}
}
}
break;
case MotionEvent.ACTION_UP:
//抬起
//保存密码
if (!isUnclock) {
if (password.length() > 0) {
if (hasPassword == false) {
//没有密码
if (password1 == null) {
//第一次
text.setText("请确认密码");
hide();
password1 = password.toString();
password.replace(0, password.length(), "");
} else {
System.out.println(password1 + "___" + password + "____" + password1.length() + "___" + password.length());
//有密码了
if (password1.equals(password.toString())) {
text.setText("密码设置成功");
//保存密码
SharedPreferences sp = getSharedPreferences("password", 0);
SharedPreferences.Editor editor = sp.edit();
editor.putString("pwd", password.toString());
editor.commit();
} else {
text.setText("两次密码绘制不一致,请重新绘制");
hide();
password.replace(0, password.length(), "");
password1 = null;
}
}
} else {
if (getPassword1.equals(password.toString())) {
text.setText("解锁成功");
ImageView iv = findViewById(R.id.iv_p8);
hide();
iv.setVisibility(View.VISIBLE);
isUnclock = true;
} else {
text.setText("密码错误,请重新绘制");
hide();
password.replace(0, password.length(), "");
}
}
}
}
break;
default:
break;
}
return true;
}
//写一个方法判断触摸点是否在某个控件内部
public ImageView dotOfTouch(float x,float y){
//遍历数组
int[] loc = new int[2];
for (ImageView dot: dotsList) {
dot.getLocationOnScreen(loc);
if ((x <= loc[0] + dot.getWidth() && x >= loc[0]) && (y <= loc[1] + dot.getHeight() && y >= loc[1])){
return dot;
}
}
return null;
}
//将所有的已经显示的控件隐藏
public void hide(){
for (ImageView dot:dotsList) {
dot.setVisibility(View.INVISIBLE);
}
RelativeLayout rl = findViewById(R.id.cl_main);
for (Integer i: lineList) {
rl.findViewWithTag(i).setVisibility(View.INVISIBLE);
lastTag = null;
}
}
}
实际使用效果:
总结:
一个完整的项目是很对知识的运用,因此不管是以前学的C语言还是现在学的Java都是在学习思想,现在所学的东西只不过是以前的东西披了一身马甲罢了,只不过加入了界面而已,但是具体的代码实现也就是灵魂还是以前的枯燥的代码。