Android仿支付宝手势密码一
Android仿支付宝手势密码二
前面两篇文章介绍了手势密码的下半部分,本文主要介绍手势密码的上面小view部分和应用
一 上面小view
其实明白了前面两篇文章,对手势密码的上半部分就很简单了。思路和前面的手势密码一样,这里不同的就是不画连接线和错误状态,并且没有手指移动。监听手势绘制完成后,直接绘制实心圆。这里代码就不仔细讲解了。
public class GesturePwdSmallView extends View {
private Context mContext;
/**
* 圆点图片
*/
private Bitmap selectedBitmapSmall;
private Bitmap unSelectedBitmapSmall;
private int pieceWidth;//每个大view圆点宽度
private int pieceMargin ;//每个圆间隔的距离
/**
* 手指经过的点
*/
private List<Integer> pressPositionList ;
private String TAG = "GesturePwdView";
private Paint mPaint;
/**
* 用于记录每个点的对应的位置坐标
*/
private HashMap<Integer, GesturePointBean> gesturePointMap = new HashMap<>();
public GesturePwdSmallView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public GesturePwdSmallView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
mContext = context;
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.GesturePwdSmall);
Drawable dw_selected = ta.getDrawable(R.styleable.GesturePwdSmall_selectedDrawableSmall);
Drawable dw_unSeclect = ta.getDrawable(R.styleable.GesturePwdSmall_unselectedDrawableSmall);
if (dw_selected != null) {
selectedBitmapSmall = BitmapUtils.drawableToBitmap(dw_selected);
} else {
selectedBitmapSmall = BitmapUtils.drawableToBitmap(getResources().getDrawable(R.drawable.circle_blue_select));
}
if (dw_unSeclect != null) {
unSelectedBitmapSmall = BitmapUtils.drawableToBitmap(dw_unSeclect);
} else {
unSelectedBitmapSmall = BitmapUtils.drawableToBitmap(getResources().getDrawable(R.drawable.circle_grey_small_unselect));
}
pieceMargin = ta.getDimensionPixelOffset(R.styleable.GesturePwdSmall_pieceMarginSmall, 10);
pieceWidth = unSelectedBitmapSmall.getWidth();
//等待时间,默认30s
mPaint = new Paint();
//避免重新创建时候的错误
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int measureWidth = MeasureSpec.getSize(widthMeasureSpec);
int measureHeight = MeasureSpec.getSize(heightMeasureSpec);
int measureWidthMode = MeasureSpec.getMode(widthMeasureSpec);
int measureHeightMode = MeasureSpec.getMode(heightMeasureSpec);
setMeasuredDimension((measureWidthMode == MeasureSpec.EXACTLY) ? measureWidth : pieceMargin * 2 + pieceWidth * 3, (measureHeightMode == MeasureSpec.EXACTLY) ? measureHeight : pieceMargin * 2 + pieceWidth * 3);
// setMeasuredDimension( pieceMargin * 2 + pieceWidth * 3, (measureHeightMode == MeasureSpec.EXACTLY) ? measureHeight : pieceMargin * 2 + pieceWidth * 3);
}
public void setPressPositionList(List<Integer> pressPositionList) {
this.pressPositionList = pressPositionList;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画大view
int key = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
float x;
float y;
if (j == 0) {
x = (float) (getWidth() / 2 - 1.5 * pieceWidth - pieceMargin);
} else {
x = (float) (getWidth() / 2 - 1.5 * pieceWidth - pieceMargin + j * pieceWidth + pieceMargin * j);
}
y = (float) (i * pieceWidth + i * pieceMargin);
GesturePointBean gestureBean = new GesturePointBean((int) x, (int) y);
gesturePointMap.put(key, gestureBean);
drawCircle(key, x, y, canvas);
key++;
}
}
}
/**
* 画园的时候判断是否有点击的圆
*
* @param k
* @param x
* @param y
* @param canvas
*/
private void drawCircle(int k, float x, float y, Canvas canvas) {
boolean findSelect = false;
if (pressPositionList != null && pressPositionList.size() > 0) {
for (Integer integer : pressPositionList) {
if (integer == k) {
findSelect = true;
}
}
}
if (findSelect) {
canvas.drawBitmap(selectedBitmapSmall, x, y, mPaint);
} else {
canvas.drawBitmap(unSelectedBitmapSmall, x, y, mPaint);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<size
android:width="25dp"
android:height="25dp" />
<solid android:color="@color/Grey300" />
</shape>
</item>
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp">
<shape android:shape="oval">
<solid android:color="@color/white" />
</shape>
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<size
android:width="25dp"
android:height="25dp" />
<solid android:color="@color/Blue500" />
</shape>
</item>
</layer-list>
二 实际应用
这里做一个简单的实际应用在注册界面做监听并保存手势密码,然后在登录界面验证。
2.1 注册界面
public class GesturePwdActiviy extends AppCompatActivity {
private GesturePwdSmallView gesturePwdSmallView;
private GesturePwdView gesturePwdView;
private TextView textView;
private Animation translateanim;
private SharedPreferences sharedPreferences;
/**
* 保存数据SharedPreferences文件的名字
*/
private final String GESTURE_PWD = "GESTURE_PWD";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesturepwd);
gesturePwdSmallView = findViewById(R.id.gesturePwdSmallView);
gesturePwdView = findViewById(R.id.gesturePwdView);
textView = findViewById(R.id.text);
sharedPreferences =getSharedPreferences(GESTURE_PWD,MODE_PRIVATE);
translateanim= AnimationUtils.loadAnimation(GesturePwdActiviy.this,R.anim.gesture_text_anim);
gesturePwdView.setOnChoosePointListener(new GesturePwdView.OnChoosePointListener() {
@Override
public void onDrawFirstFinish(List<Integer> positions) {
textView.setText("请再次绘制图案");
textView.setTextColor(getResources().getColor(R.color.black));
gesturePwdSmallView.setPressPositionList(positions);
}
@Override
public void onError(String text) {
textView.setText(text);
textView.setTextColor(getResources().getColor(R.color.read_d5));
textView.startAnimation(translateanim);
}
@Override
public void onVirfiyFinish(String pwd) {
textView.setText("设置成功可到登录验证");
textView.setTextColor(getResources().getColor(R.color.black));
sharedPreferences.edit().putString(GESTURE_PWD,pwd).commit();
// finish();
Toast.makeText(GesturePwdActiviy.this,pwd,Toast.LENGTH_SHORT).show();
}
@Override
public void onLogin(int type, int drawCount) {
}
});
}
}
这里绘制错误的时候,文字添加了一个动画
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fillBefore="true"
android:fromXDelta="0"
android:repeatCount="3"
android:toXDelta="-10"/>
布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<com.example.learn.home.customview.view.GesturePwdSmallView
android:id="@+id/gesturePwdSmallView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="30dp"
app:pieceMarginSmall="8dp"
app:selectedDrawableSmall="@drawable/circle_blue_small_select"
app:unselectedDrawableSmall="@drawable/circle_grey_small_unselect" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="40dp"
android:layout_marginBottom="40dp"
android:text="绘制图案" />
<com.example.learn.home.customview.view.GesturePwdView
android:id="@+id/gesturePwdView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:pathColor="@color/Blue500"
app:pieceMargin="50dp"
app:selectedDrawable="@drawable/circle_blue_select"
app:unselectedDrawable="@drawable/circle_blue_unselect"
tools:ignore="MissingConstraints" />
</LinearLayout>
2.2 登录界面
public class GesturePwdVerfiyActiviy extends AppCompatActivity {
private GesturePwdView gesturePwdView;
private SharedPreferences sharedPreferences;
private final String GESTURE_PWD = "GESTURE_PWD";
private String TAG = "GesturePwdVerfiyActiviy";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesturepwd_verify);
gesturePwdView = findViewById(R.id.gesturePwdView);
sharedPreferences = getSharedPreferences(GESTURE_PWD, MODE_PRIVATE);
String pwd = sharedPreferences.getString(GESTURE_PWD, "");
Log.d(TAG, "onCreate: pwd==" + pwd);
gesturePwdView.setGesturePwd(pwd);
gesturePwdView.setOnChoosePointListener(new GesturePwdView.OnChoosePointListener() {
@Override
public void onDrawFirstFinish(List<Integer> positions) {
}
@Override
public void onError(String text) {
}
@Override
public void onVirfiyFinish(String pwd) {
}
@Override
public void onLogin(int type, int drawCount) {
Toast.makeText(GesturePwdVerfiyActiviy.this, "登录:" + type + ",绘制次数" + drawCount, Toast.LENGTH_SHORT).show();
}
});
}
}
布局代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<com.example.learn.home.customview.view.GesturePwdView
android:layout_marginTop="100dp"
android:id="@+id/gesturePwdView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
app:pathColor="@color/Blue500"
app:pieceMargin="50dp"
app:selectedDrawable="@drawable/circle_blue_select"
app:unselectedDrawable="@drawable/circle_blue_unselect"
tools:ignore="MissingConstraints" />
</LinearLayout>