Android 간단 한 제스처 암호 오픈 소스 라 이브 러 리 상세 설명
본 고 는 안 드 로 이 드 제스처 암호 오픈 소스 라 이브 러 리 의 사용 과 실현 에 대한 상세 한 과정 을 소개 한다.이 오픈 소스 라 이브 러 리 는 주로 다음 과 같은 몇 가지 기능 을 실현 한다.
4.567917.제스처 암호 의 그리 기 를 지원 하고 암호 저장 기능 을 지원 합 니 다.잠 금 을 풀 때 자동 으로 암호 에 대한 결 과 를 제공 합 니 다4.567917.비밀 번 호 를 그 리 는 방법 을 봉 인 했 습 니 다.두 번 의 비밀번호 가 일치 하 는 지 보다 제스처 비밀 번 호 를 빠르게 설정 할 수 있 습 니 다
github 링크 는 다음 과 같 습 니 다.스타 의 지원 을 받 을 수 있 을 것 같 습 니 다~
github 링크 개인 블 로그
사용 효과
우선 사용 효과 보기:
사용 방법
XML 레이아웃 파일 에서 이 컨트롤 을 사용 합 니 다.
<com.syd.oden.gesturelock.view.GestureLockViewGroup
android:id="@+id/gesturelock"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:preference_id="1"
android:layout_marginTop="30dp"
app:count="3" />
설정 할 수 있 는 매개 변 수 는 다음 과 같 습 니 다.
private void initGesture() {
mGestureLockViewGroup = (GestureLockViewGroup) findViewById(R.id.gesturelock);
gestureEventListener();
gesturePasswordSettingListener();
gestureRetryLimitListener();
}
제스처 암호 감청 이벤트 설정
private void gestureEventListener() {
mGestureLockViewGroup.setGestureEventListener(new GestureEventListener() {
@Override
public void onGestureEvent(boolean matched) {
mylog.d("onGestureEvent matched: " + matched);
if (!matched) {
tv_state.setTextColor(Color.RED);
tv_state.setText(" ");
} else {
if (isReset) {
isReset = false;
Toast.makeText(MainActivity.this, " !", Toast.LENGTH_SHORT).show();
resetGesturePattern();
} else {
tv_state.setTextColor(Color.WHITE);
tv_state.setText(" ");
}
}
}
});
}
비밀번호 가 설정 되 어 있 으 면 이 반전 에 들 어가 결 과 를 처리 합 니 다.위의 예 에 비밀 번 호 를 재 설정 하 는 처리 가 추가 되 었 습 니 다.제스처 암호 설정
private void gesturePasswordSettingListener() {
mGestureLockViewGroup.setGesturePasswordSettingListener(new GesturePasswordSettingListener() {
@Override
public boolean onFirstInputComplete(int len) {
if (len > 3) {
tv_state.setTextColor(Color.WHITE);
tv_state.setText(" ");
return true;
} else {
tv_state.setTextColor(Color.RED);
tv_state.setText(" 4 , !");
return false;
}
}
@Override
public void onSuccess() {
tv_state.setTextColor(Color.WHITE);
Toast.makeText(MainActivity.this, " !", Toast.LENGTH_SHORT).show();
tv_state.setText(" !");
}
@Override
public void onFail() {
tv_state.setTextColor(Color.RED);
tv_state.setText(" , ");
}
});
}
암호 가 설정 되 어 있 지 않 으 면 제스처 를 그 릴 때 이 반전 에 들 어 갑 니 다.그 려 진 터치 포인트 의 수 를 되 돌려 줍 니 다.onFirst InputComplete 에서 true 를 되 돌려 주면 두 번 째 제스처 암 호 를 그립 니 다.두 번 입력 하면 자동 으로 암 호 를 저장 합 니 다.재 시도 횟수 제한 감청 초과
private void gestureRetryLimitListener() {
mGestureLockViewGroup.setGestureUnmatchedExceedListener(3, new GestureUnmatchedExceedListener() {
@Override
public void onUnmatchedExceedBoundary() {
tv_state.setTextColor(Color.RED);
tv_state.setText(" , !");
}
});
}
이 감청 사건 이 설정 되 어 있 으 면 입력 오 류 는 횟수 제한 이 있 고 상한 선 을 초과 한 후 리 셋 에 들 어가 이 리 셋 에서 처리 합 니 다.암 호 를 지 우 는 논 리 는 스스로 판단 처 리 를 하면 됩 니 다.구체 적 으로 github 의 demo 를 볼 수 있 습 니 다.
기타 API
public void removePassword() :
public void savePassword() : , ,
public void getPassword():
public void setRetryTimes(int retryTimes) :
public boolean isSetPassword() :
public void resetView() : Reset
프로젝트 에서 이 라 이브 러 리 가 져 오기두 줄 코드 만 추가:
프로젝트 의 build.gradle 에 추가:
allprojects {
repositories {
...
maven { url "https://jitpack.io" }
}
}
module 의 build.gradle 에 의존 도 를 추가 합 니 다:
dependencies {
compile 'com.github.autume:GestureLock:1.0.0'
}
전체적인 사용 이 이 렇 습 니 다.간단 하지 않 습 니까?구체 적 실현 과정
실현 과정 에 대해 서 는 직접 가 져 다 쓰 는 것 만으로 도 이 부분 을 생략 할 수 있다.
사용자 정의 제스처 암호 의 원형 view
이 부분 은 주로 Hongyang 의 큰 블 로 그 를 참고 하여 조금 수정 하 였 습 니 다.
입력 매개 변수 초기 화
public GestureLockView(Context context, int colorNoFingerr, int colorFingerOn, int colorCorrect, int colorError) {
super(context);
this.mColorNoFinger = colorNoFingerr;
this.mColorFingerOn = colorFingerOn;
this.mColorFingerUpCorrect = colorCorrect;
this.mColorFingerUpError = colorError;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mArrowPath = new Path();
}
터치 상태 에 따라 원 을 그립 니 다.
@Override
protected void onDraw(Canvas canvas) {
switch (mCurrentStatus) {
case STATUS_FINGER_ON:
//
mPaint.setStyle(Style.STROKE);
mPaint.setColor(mColorFingerOn);
mPaint.setStrokeWidth(2);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
//
mPaint.setStyle(Style.FILL);
canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
break;
case STATUS_FINGER_UP:
//
if (GestureLockViewGroup.isCorrect)
mPaint.setColor(mColorFingerUpCorrect);
else
mPaint.setColor(mColorFingerUpError);
mPaint.setStyle(Style.STROKE);
mPaint.setStrokeWidth(2);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
//
mPaint.setStyle(Style.FILL);
canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
drawArrow(canvas);
break;
case STATUS_NO_FINGER:
//
mPaint.setStyle(Style.STROKE);
mPaint.setColor(mColorNoFinger);
canvas.drawCircle(mCenterX, mCenterY, mRadius, mPaint);
//
mPaint.setStyle(Style.FILL);
mPaint.setColor(mColorNoFinger);
canvas.drawCircle(mCenterX, mCenterY, mRadius * mInnerCircleRadiusRate, mPaint);
break;
}
}
화살표 그리 기
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = MeasureSpec.getSize(widthMeasureSpec);
mHeight = MeasureSpec.getSize(heightMeasureSpec);
//
mWidth = mWidth < mHeight ? mWidth : mHeight;
mRadius = mCenterX = mCenterY = mWidth / 2;
mRadius -= mStrokeWidth / 2;
// , , , GestureLockView
float mArrowLength = mWidth / 2 * mArrowRate;
mArrowPath.moveTo(mWidth / 2, mStrokeWidth + 2);
mArrowPath.lineTo(mWidth / 2 - mArrowLength, mStrokeWidth + 2 + mArrowLength);
mArrowPath.lineTo(mWidth / 2 + mArrowLength, mStrokeWidth + 2 + mArrowLength);
mArrowPath.close();
mArrowPath.setFillType(Path.FillType.WINDING);
}
private void drawArrow(Canvas canvas) {
if (mArrowDegree != -1) {
mPaint.setStyle(Paint.Style.FILL);
canvas.save();
canvas.rotate(mArrowDegree, mCenterX, mCenterY);
canvas.drawPath(mArrowPath, mPaint);
canvas.restore();
}
}
제스처 암 호 를 사용자 정의 하 는 ViewGroup사용자 정의 view 속성 추가
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="color_no_finger" format="color" />
<attr name="color_finger_on" format="color" />
<attr name="color_finger_up_correct" format="color" />
<attr name="color_finger_up_error" format="color" />
<attr name="count" format="integer" />
<attr name="preference_id" format="integer" />
<declare-styleable name="GestureLockViewGroup">
<attr name="color_no_finger" />
<attr name="color_finger_on" />
<attr name="color_finger_up_correct" />
<attr name="color_finger_up_error" />
<attr name="count" />
<attr name="preference_id" />
</declare-styleable>
</resources>
매개 변수 가 져 오기 및 초기 화
public GestureLockViewGroup(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
/**
*
*/
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.GestureLockViewGroup, defStyle, 0);
mNoFingerColor = a.getColor(R.styleable.GestureLockViewGroup_color_no_finger, mNoFingerColor);
mFingerOnColor = a.getColor(R.styleable.GestureLockViewGroup_color_finger_on, mFingerOnColor);
mFingerUpColorCorrect = a.getColor(R.styleable.GestureLockViewGroup_color_finger_up_correct, mFingerUpColorCorrect);
mFingerUpColorError = a.getColor(R.styleable.GestureLockViewGroup_color_finger_up_error, mFingerUpColorError);
mCount = a.getInt(R.styleable.GestureLockViewGroup_count, mCount);
mPrferenceId = a.getInt(R.styleable.GestureLockViewGroup_preference_id, mPrferenceId);
a.recycle();
/**
*
*/
gesturePreference = new GesturePreference(context, mPrferenceId);
password = gesturePreference.ReadStringPreference();
Log.d(TAG, "password now is : " + password);
isSetPassword = !password.equals("null"); //
isInPasswordSettingMode = !isSetPassword; // ,
//
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPath = new Path();
}
매개 변수 에 따라 원 그리 기onMeasure 후 이 방법 을 사용 하여 원형 행렬 을 그립 니 다.
private GestureLockView[] mGestureLockViews; // GestureLockView
private void initViews() {
// mGestureLockViews
if (mGestureLockViews == null) {
mGestureLockViews = new GestureLockView[mCount * mCount];
// GestureLockView
mGestureLockViewWidth = (int) (4 * mWidth * 1.0f / (5 * mCount + 1));
// GestureLockView
mMarginBetweenLockView = (int) (mGestureLockViewWidth * 0.25);
// GestureLockView
mPaint.setStrokeWidth(mGestureLockViewWidth * 0.29f);
for (int i = 0; i < mGestureLockViews.length; i++) {
// GestureLockView
mGestureLockViews[i] = new GestureLockView(getContext(), mNoFingerColor, mFingerOnColor, mFingerUpColorCorrect, mFingerUpColorError);
mGestureLockViews[i].setId(i + 1);
// , GestureLockView
RelativeLayout.LayoutParams lockerParams = new RelativeLayout.LayoutParams(
mGestureLockViewWidth, mGestureLockViewWidth);
// ,
if (i % mCount != 0) {
lockerParams.addRule(RelativeLayout.RIGHT_OF,
mGestureLockViews[i - 1].getId());
}
// , View
if (i > mCount - 1) {
lockerParams.addRule(RelativeLayout.BELOW,
mGestureLockViews[i - mCount].getId());
}
//
int rightMargin = mMarginBetweenLockView;
int bottomMargin = mMarginBetweenLockView;
int leftMagin = 0;
int topMargin = 0;
/**
* View
*/
if (i >= 0 && i < mCount)//
{
topMargin = mMarginBetweenLockView;
}
if (i % mCount == 0)//
{
leftMagin = mMarginBetweenLockView;
}
lockerParams.setMargins(leftMagin, topMargin, rightMargin,
bottomMargin);
mGestureLockViews[i].setMode(Mode.STATUS_NO_FINGER);
addView(mGestureLockViews[i], lockerParams);
}
}
}
터치 감청 에서 서로 다른 사건 을 처리 하 다.
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
Log.d(TAG, "mTryTimes : " + mTryTimes);
// ,
if (mTryTimes <= 0 && isRetryTimeLimit) {
return true;
}
switch (action) {
case MotionEvent.ACTION_DOWN:
reset(); //
break;
case MotionEvent.ACTION_MOVE:
drawAndGetSelectedWhenTouchMove(x, y);
break;
case MotionEvent.ACTION_UP:
if (isInPasswordSettingMode) {
if (gesturePasswordSettingListener != null)
setPasswordHandle(); //
} else {
if (mChoose.size() > 0) {
isCorrect = checkAnswer();
} else {
return true;
}
if (gestureEventListener != null) {
gestureEventListener.onGestureEvent(isCorrect); //
}
if (this.mTryTimes == 0) {
gestureUnmatchedExceedListener.onUnmatchedExceedBoundary(); // ,
}
}
drawWhenTouchUp();
break;
}
invalidate();
return true;
}
private void drawAndGetSelectedWhenTouchMove(int x, int y) {
mPaint.setColor(mFingerOnColor);
mPaint.setAlpha(50);
GestureLockView child = getChildIdByPos(x, y);
if (child != null) {
int cId = child.getId();
if (!mChoose.contains(cId)) {
mChoose.add(cId);
mChooseString = mChooseString + cId;
child.setMode(Mode.STATUS_FINGER_ON);
//
mLastPathX = child.getLeft() / 2 + child.getRight() / 2;
mLastPathY = child.getTop() / 2 + child.getBottom() / 2;
if (mChoose.size() == 1)//
{
mPath.moveTo(mLastPathX, mLastPathY);
} else
// ,
{
mPath.lineTo(mLastPathX, mLastPathY);
}
}
}
//
mTmpTarget.x = x;
mTmpTarget.y = y;
}
private void drawWhenTouchUp() {
if (isCorrect) {
mPaint.setColor(mFingerUpColorCorrect);
} else {
mPaint.setColor(mFingerUpColorError);
}
mPaint.setAlpha(50);
Log.d(TAG, "mChoose = " + mChoose);
// ,
mTmpTarget.x = mLastPathX;
mTmpTarget.y = mLastPathY;
// UP
setItemModeUp();
//
for (int i = 0; i + 1 < mChoose.size(); i++) {
int childId = mChoose.get(i);
int nextChildId = mChoose.get(i + 1);
GestureLockView startChild = (GestureLockView) findViewById(childId);
GestureLockView nextChild = (GestureLockView) findViewById(nextChildId);
int dx = nextChild.getLeft() - startChild.getLeft();
int dy = nextChild.getTop() - startChild.getTop();
//
int angle = (int) Math.toDegrees(Math.atan2(dy, dx)) + 90;
startChild.setArrowDegree(angle);
}
}
암호 처리 설정:
private void setPasswordHandle() {
if (isWaitForFirstInput) {
if (gesturePasswordSettingListener.onFirstInputComplete(mChooseString.length())) {
firstInputPassword = mChooseString;
isWaitForFirstInput = false;
}
} else {
if (firstInputPassword.equals(mChooseString)) {
gesturePasswordSettingListener.onSuccess();
savePassword(mChooseString);
isInPasswordSettingMode = false;
} else {
gesturePasswordSettingListener.onFail();
}
}
reset();
}
제스처 암호 가 올 바른 지 확인 하기:
public boolean checkAnswer() {
if (password.equals(mChooseString)) {
return true;
} else {
if (isRetryTimeLimit)
this.mTryTimes--;
return false;
}
}
초기 화:
private void reset() {
mChoose.clear();
mChooseString = "";
mPath.reset();
for (GestureLockView gestureLockView : mGestureLockViews) {
gestureLockView.setMode(Mode.STATUS_NO_FINGER);
gestureLockView.setArrowDegree(-1);
}
}
대외 적 으로 공개 하 는 방법 들
public void setGestureEventListener(GestureEventListener gestureEventListener) {
this.gestureEventListener = gestureEventListener;
}
public void setGestureUnmatchedExceedListener(int retryTimes, GestureUnmatchedExceedListener gestureUnmatchedExceedListener) {
isRetryTimeLimit = true;
this.mTryTimes = retryTimes;
this.gestureUnmatchedExceedListener = gestureUnmatchedExceedListener;
}
public void setGesturePasswordSettingListener(GesturePasswordSettingListener gesturePasswordSettingListener) {
this.gesturePasswordSettingListener = gesturePasswordSettingListener;
}
public void removePassword() {
gesturePreference.WriteStringPreference("null");
this.isSetPassword = false;
isWaitForFirstInput = true;
isInPasswordSettingMode = true;
}
public void savePassword(String password) {
this.password = password;
gesturePreference.WriteStringPreference(password);
}
public String getPassword() {
return password;
}
public void resetView() {
reset();
invalidate();
}
public void setRetryTimes(int retryTimes) {
this.mTryTimes = retryTimes;
}
public boolean isSetPassword() {
return isSetPassword;
}
암호 로 저 장 된 Preference 정의간단 한 저장 과 읽 기 입 니 다.
public GesturePreference(Context context, int nameTableId) {
this.context = context;
if (nameTableId != -1)
this.nameTable = nameTable + nameTableId;
}
public void WriteStringPreference(String data) {
SharedPreferences preferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
editor.putString(nameTable, data);
editor.commit();
}
public String ReadStringPreference() {
SharedPreferences preferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
return preferences.getString(nameTable, "null");
}
총결산ok,이로써 전체 제스처 암호 의 실현 이 완료 되 었 습 니 다.
이상 은 안 드 로 이 드 에 대한 간단 한 제스처 비밀 번 호 를 실현 하 는 자 료 를 정리 하고 관련 자 료 를 계속 정리 하 는 것 입 니 다.본 사이트 에 대한 지원 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.