Android自定義UI手勢(shì)密碼簡單版
先看看效果圖:

ImageLockActivity
package com.example.imagelock;
import com.example.view.NinePointLineView;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
public class ImageLockActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
View v = new NinePointLineView(this);
setContentView(v);
}
}
NinePointLineView
package com.example.view;
import com.example.imagelock.R;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class NinePointLineView extends View {
/**
* 定義3個(gè)Paint,還有一個(gè)坐標(biāo)圓點(diǎn)圖片
*/
Paint linePaint = new Paint();
Paint whiteLinePaint = new Paint();
Paint textPaint = new Paint();
Bitmap defaultBitmap = BitmapFactory.decodeResource(getResources(),R.drawable.lock);
PointInfo[] points = new PointInfo[9];
int width, height;
//坐標(biāo)點(diǎn)的半徑長度
int defaultBitmapRadius = defaultBitmap.getWidth() / 2;
//繪制密碼時(shí)候出現(xiàn)的原點(diǎn)的直徑,半徑
Bitmap selectedBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.indicator_lock_area);
int selectedBitmapDiameter = selectedBitmap.getWidth();
int selectedBitmapRadius = selectedBitmapDiameter / 2;
StringBuffer lockString = new StringBuffer();
Context context;
/** 構(gòu)造器*********************************************/
public NinePointLineView(Context context) {
super(context);
this.context = context;
this.setBackgroundColor(Color.WHITE);
initPaint();
}
public NinePointLineView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.setBackgroundColor(Color.WHITE);
initPaint();
}
private void initPaint() {
//線--包裹9個(gè)原點(diǎn)
linePaint.setColor(Color.RED);
linePaint.setStrokeWidth(defaultBitmap.getWidth());
linePaint.setAntiAlias(true);
linePaint.setStrokeCap(Cap.ROUND);
//線內(nèi)--比原點(diǎn)直徑少5
whiteLinePaint.setColor(Color.GREEN);
whiteLinePaint.setStrokeWidth(defaultBitmap.getWidth() - 5);
whiteLinePaint.setAntiAlias(true);
whiteLinePaint.setStrokeCap(Cap.ROUND);
//字體設(shè)置
textPaint.setTextSize(30);
textPaint.setAntiAlias(true);
textPaint.setTypeface(Typeface.MONOSPACE);
}
/**********************************************************
* 測量
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = getWidth();
height = getHeight();
if (width != 0 && height != 0) {
initPoints(points);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
/**
* 初始化原點(diǎn)
*/
private void initPoints(PointInfo[] points) {
int len = points.length;
//2個(gè)原點(diǎn)的間距
int seletedSpacing = (width - selectedBitmapDiameter * 3) / 4;
//第1個(gè)原點(diǎn)的坐標(biāo)
int seletedX = seletedSpacing;
int seletedY = height - width + seletedSpacing;
//第1個(gè)原點(diǎn)內(nèi)部的小圓的坐標(biāo)
int defaultX = seletedX + selectedBitmapRadius - defaultBitmapRadius;
int defaultY = seletedY + selectedBitmapRadius - defaultBitmapRadius;
for (int i = 0; i < len; i++) {
//第4、7個(gè)原點(diǎn)
if (i == 3 || i == 6) {
seletedX = seletedSpacing;
//第一個(gè)原點(diǎn)y坐標(biāo)+直徑+2點(diǎn)間距離
seletedY += selectedBitmapDiameter + seletedSpacing;
defaultX = seletedX + selectedBitmapRadius
- defaultBitmapRadius;
//第一個(gè)原點(diǎn)y坐標(biāo)+直徑+2點(diǎn)間距離
defaultY += selectedBitmapDiameter + seletedSpacing;
}
points[i] = new PointInfo(i, defaultX, defaultY, seletedX, seletedY);
//原點(diǎn)坐標(biāo)xy為直徑+2點(diǎn)間距離
seletedX += selectedBitmapDiameter + seletedSpacing;
defaultX += selectedBitmapDiameter + seletedSpacing;
}
}
/*****************************************************************/
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
private int startX = 0, startY = 0;
PointInfo startPoint = null;
@Override
protected void onDraw(Canvas canvas) {
drawNinePoint(canvas);
super.onDraw(canvas);
}
/**
*
* @param canvas
*/
private void drawNinePoint(Canvas canvas) {
if (startPoint != null) {
drawEachLine(canvas, startPoint);
}
for(PointInfo pointInfo : points) {
if (pointInfo!=null) {
if (pointInfo.isSelected()) {
canvas.drawBitmap(selectedBitmap, pointInfo.getSeletedX(),pointInfo.getSeletedY(), null);
}
canvas.drawBitmap(defaultBitmap, pointInfo.getDefaultX(),pointInfo.getDefaultY(), null);
}
}
}
private void drawEachLine(Canvas canvas, PointInfo point) {
if (point.hasNextId()) {
int n = point.getNextId();
drawLine(canvas, point.getCenterX(), point.getCenterY(),
points[n].getCenterX(), points[n].getCenterY());
drawEachLine(canvas, points[n]);
}
}
private void drawLine(Canvas canvas, float startX, float startY,
float stopX, float stopY) {
canvas.drawLine(startX, startY, stopX, stopY, linePaint);
canvas.drawLine(startX, startY, stopX, stopY, whiteLinePaint);
}
/**
* ********************************************************************
*/
boolean isUp = false;
int moveX, moveY;
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean flag = true;
//isUp默認(rèn)是false--繪制是否完畢,此時(shí)為true
if (isUp) {
finishDraw();
Toast.makeText(context, "繪制完畢,手指離開,在點(diǎn)擊", 0).show();
flag = false;
} else {
handlingEvent(event);
flag = true;
Toast.makeText(context, "手指一旦繪制", 0).show();
}
//是否處理事件
return flag;
}
private void finishDraw() {
for (PointInfo temp : points) {
temp.setSelected(false);
temp.setNextId(temp.getId());
}
lockString.delete(0, lockString.length());
isUp = false;
invalidate();
}
private void handlingEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
moveX = (int) event.getX();
moveY = (int) event.getY();
for (PointInfo temp : points) {
if (temp.isInMyPlace(moveX, moveY) && temp.isSelected()==false) {
temp.setSelected(true);
startX = temp.getCenterX();
startY = temp.getCenterY();
int len = lockString.length();
if (len != 0) {
int preId = lockString.charAt(len - 1) - 48;
points[preId].setNextId(temp.getId());
}
lockString.append(temp.getId());
break;
}
}
invalidate();
break;
case MotionEvent.ACTION_DOWN:
//獲取按下的xy坐標(biāo)
int downX = (int) event.getX();
int downY = (int) event.getY();
for (PointInfo temp : points) {
//如果符合距離范圍內(nèi)
if (temp.isInMyPlace(downX, downY)) {
//將其設(shè)置為選中狀態(tài)
temp.setSelected(true);
//將選中的圓點(diǎn)設(shè)置為起始位置圓點(diǎn)
startPoint = temp;
//將其圓心作為起始點(diǎn)
startX = temp.getCenterX();
startY = temp.getCenterY();
lockString.append(temp.getId());
break;
}
}
invalidate();
break;
case MotionEvent.ACTION_UP:
startX = startY = moveX = moveY = 0;
//繪制完畢
isUp = true;
invalidate();
break;
default:
break;
}
}
/**
* 原點(diǎn)bean
*/
private class PointInfo {
private boolean selected;
private int id;
private int nextId;
private int defaultX;
private int defaultY;
private int seletedX;
private int seletedY;
public PointInfo(int id, int defaultX, int defaultY, int seletedX,
int seletedY) {
this.id = id;
this.nextId = id;
this.defaultX = defaultX;
this.defaultY = defaultY;
this.seletedX = seletedX;
this.seletedY = seletedY;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public int getId() {
return id;
}
public int getDefaultX() {
return defaultX;
}
public int getDefaultY() {
return defaultY;
}
public int getSeletedX() {
return seletedX;
}
public int getSeletedY() {
return seletedY;
}
public int getCenterX() {
return seletedX + selectedBitmapRadius;
}
public int getCenterY() {
return seletedY + selectedBitmapRadius;
}
public boolean hasNextId() {
return nextId != id;
}
public int getNextId() {
return nextId;
}
public void setNextId(int nextId) {
this.nextId = nextId;
}
/**
* 如果某個(gè)xy值在某個(gè)原點(diǎn)的左右上下范圍內(nèi),就說明ok
*/
public boolean isInMyPlace(int x, int y) {
boolean inX = x > seletedX
&& x < (seletedX + selectedBitmapDiameter);
boolean inY = y > seletedY
&& y < (seletedY + selectedBitmapDiameter);
return (inX && inY);
}
}
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android手勢(shì)密碼的實(shí)現(xiàn)
- Android 簡易手勢(shì)密碼開源庫詳解
- Android自定義控件實(shí)現(xiàn)手勢(shì)密碼
- Android自定義UI手勢(shì)密碼終結(jié)版
- Android仿支付寶手勢(shì)密碼解鎖功能
- Android手勢(shì)密碼實(shí)現(xiàn)實(shí)例代碼
- Android九宮格手勢(shì)密碼代碼設(shè)計(jì)
- Android實(shí)現(xiàn)手勢(shì)密碼功能
- Android自定義UI手勢(shì)密碼改進(jìn)版源碼下載
- 純android代碼實(shí)現(xiàn)九宮格手勢(shì)密碼
相關(guān)文章
Android如何實(shí)現(xiàn)底部菜單固定到底部
這篇文章主要介紹了Android如何實(shí)現(xiàn)底部菜單固定到底部,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Android EditText實(shí)現(xiàn)分割輸入內(nèi)容
這篇文章主要為大家詳細(xì)介紹了Android EditText實(shí)現(xiàn)分割輸入內(nèi)容的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Android使用Canvas?2D實(shí)現(xiàn)循環(huán)菜單效果
循環(huán)菜單有很多種自定義方式,我們可以利用ViewPager或者RecyclerView?+?CarouselLayoutManager?或者RecyclerView?+?PageSnapHelper來實(shí)現(xiàn)這種效果,今天我們使用Canvas?2D來實(shí)現(xiàn)這種效果,感興趣的朋友可以參考下2024-01-01
Android中制作自定義dialog對(duì)話框的實(shí)例分享
這篇文章主要介紹了Android中制作自定義dialog對(duì)話框的實(shí)例分享,安卓自帶的Dialog顯然不夠用,因而我們要繼承Dialog類來制作自己的對(duì)話框,需要的朋友可以參考下2016-04-04
Flutter 使用Navigator進(jìn)行局部跳轉(zhuǎn)頁面的方法
這篇文章主要介紹了Flutter 使用Navigator進(jìn)行局部跳轉(zhuǎn)頁面的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Android?XML數(shù)據(jù)解析要點(diǎn)介紹
這篇文章主要為大家介紹了Android?XML數(shù)據(jù)解析要點(diǎn)介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04
Android Tween動(dòng)畫之RotateAnimation實(shí)現(xiàn)圖片不停旋轉(zhuǎn)效果實(shí)例介紹
Android中如何使用rotate實(shí)現(xiàn)圖片不停旋轉(zhuǎn)的效果,下面與大家共同分析下Tween動(dòng)畫的rotate實(shí)現(xiàn)旋轉(zhuǎn)效果,感興趣的朋友可以參考下哈2013-05-05

