Main_Activity
引用的包:
package com.example.a2_latout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
要用到的全局属性:
//定义一个数组保存控件
ArrayList<ImageView>dotsList;
//保存线的tag值
ArrayList<Integer>lineTagsList;
int tag;
//保存上一次被点亮点的对象
ImageView lastSelectedDot;
//记录滑动密码
StringBuilder password;
//保存原始密码
String orgpassword;
//保存第一次输入的密码
String firstpassword;
//存放所有选中的点和线
ArrayList<ImageView>selectedList;
//提示的文本视图
TextView alertTextView;
onWindowFocusChanged部分:
@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条横线视图的添加:
//创建横线 6条
//12 23
//45 56
//78 89
tag=12;
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);
//隐藏
lineView.setVisibility(View.INVISIBLE);
//设置tag值
lineView.setTag(tag);
lineTagsList.add(tag);//添加tag值到数组
tag+=11;//同一行相差11
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//99是密度为1时的结果
params.leftMargin=x+(int)((70/1.5)scale)+(int)(99scalej);
params.topMargin=y+(int)((255/1.5)scale)+(int)(99scalei);
rl.addView(lineView,params);
}
//换行时tag值额外相差11
tag+=11;
}
6条竖线视图的创建:
//创建竖线 6条
//14 25 36
//47 58 69
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);
//隐藏
lineView.setVisibility(View.INVISIBLE);
//设置tag值
lineView.setTag(tag);
lineTagsList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//99是密度为1时的结果
params.leftMargin=x+(int)((63/1.5)scale)+(int)(99scalej);
params.topMargin=y+(int)((255/1.5)scale)+(int)(99scalei);
rl.addView(lineView,params);
}
}
8条斜线视图的创建:
//创建斜线 右斜 4条
//15 26
//48 59
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);
//隐藏
lineView.setVisibility(View.INVISIBLE);
//设置tag值
lineView.setTag(tag);
lineTagsList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//99是密度为1时的结果
params.leftMargin=x+(int)((63/1.5)scale)+(int)(99scalej);
params.topMargin=y+(int)((255/1.5)scale)+(int)(99scalei);
rl.addView(lineView,params);
System.out.println(lineView.getTag());
}
//换行额外多加11
tag+=11;
}
//创建斜线 左斜 4条
//24 35
//57 68
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);
//隐藏
lineView.setVisibility(View.INVISIBLE);
lineView.setTag(tag);
lineTagsList.add(tag);
tag+=11;
//创建布局参数
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//99是密度为1时的结果
params.leftMargin=x+(int)((80/1.5)scale)+(int)(99scalej);
params.topMargin=y+(int)((255/1.5)scale)+(int)(99scalei);
rl.addView(lineView,params);
}
//换行额外多加11
tag+=11;
}
9个点视图的创建:
//创建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++);
//隐藏视图
dotView.setVisibility(View.INVISIBLE);
//显示对应图片
dotView.setBackgroundResource(R.drawable.selected_dot);
//创建控件的尺寸 布局属性
//宽度和高度
RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
//x、y坐标
System.out.println(scale);
//设置坐标 52、244是在屏幕密度为1.5的结果下得到的 需要重新转换 后面的52是点的大小
params.leftMargin=x+(int)((52/1.5)scale)+(int)((((52+96)j)/1.5)scale);
params.topMargin=y+(int)((244/1.5)scale)+(int)((((52+96)i)/1.5)scale);
//将控件添加到容器中
rl.addView(dotView,params);
//将这个控件添加到数组
dotsList.add(dotView);
}
}
}
}
触摸事件:
@Override
public boolean onTouchEvent(MotionEvent event) {
//获取事件类型
int action=event.getAction();
//判断是什么类型
float x;
float y;
ImageView selected;
switch(action){
按下事件:
case MotionEvent.ACTION_DOWN:
//按下
//获取触摸点坐标
x=event.getX();
y=event.getY();
//判断x,y是不是在某个点范围内
selected=dotOfTouch(x,y);
//点亮 9个点
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);
//将tag拼接到密码中
password.append(selected.getTag());
//将点亮的点添加到数组中
selectedList.add(selected);
//记录
lastSelectedDot=selected;
}else {
//不是第一个点
//获取上一个点和当前点的tag组成线的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 (lineTagsList.contains(lineTag)) {
//线存在
//点亮点
selected.setVisibility(View.VISIBLE);
//将tag拼接到密码中
password.append(selected.getTag());
//将点亮的点添加到数组中
selectedList.add(selected);
//点亮这条线
//获取容器对象
RelativeLayout rl = findViewById(R.id.root_layout);
//通过tag查找子控件
ImageView iv = rl.findViewWithTag(lineTag);
//查找线
iv.setVisibility(View.VISIBLE);
//将点亮的线添加到数组中
selectedList.add(iv);
//记录这个点为上一个点亮的点
lastSelectedDot = selected;
}
}
}
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 ImageView dotOfTouch(float x,float y){
//遍历数组
for(ImageView dot:dotsList){
//获取这个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;
}
清空数据的方法:
//清空
public void clean(){
//清空密码
password.setLength(0);
//隐藏所有选中的视图 点 线
for(ImageView iv:selectedList){
iv.setVisibility(View.INVISIBLE);
}
//清空数组
selectedList.clear();
}
onCreate()部分:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
实例化属性:
//准备好数组 实例化对象
dotsList=new ArrayList<>();
lineTagsList=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("请绘制密码图案");
}
}
}
layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:id="@+id/root_layout">
背景图片:
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/main_bg"
android:scaleType="fitXY"/>
九个点的背景图片:
<ImageView
android:id="@+id/opView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/op_bg"
android:layout_centerInParent="true"
/>
显示文本:
<TextView
android:id="@+id/tv_alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="图案解锁"
android:textSize="20sp"
android:textColor="#ffffff"
android:textAlignment="center"
android:layout_alignTop="@id/opView"
android:layout_marginTop="90dp"/>
</RelativeLayout>
QQ截图20191003175528.jpg QQ截图20191003175547.jpg QQ截图20191003175615.jpg QQ截图20191003175754.jpg QQ截图20191003175805.jpg
网友评论