fist commit
This commit is contained in:
1
verificationcodeview/.gitignore
vendored
Normal file
1
verificationcodeview/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
34
verificationcodeview/build.gradle
Normal file
34
verificationcodeview/build.gradle
Normal file
@@ -0,0 +1,34 @@
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
|
||||
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
implementation 'com.android.support:appcompat-v7:26.1.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
|
||||
}
|
||||
21
verificationcodeview/proguard-rules.pro
vendored
Normal file
21
verificationcodeview/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.jyn.vcview;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.jyn.verificationcodeview.test", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
2
verificationcodeview/src/main/AndroidManifest.xml
Normal file
2
verificationcodeview/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.jyn.vcview" />
|
||||
@@ -0,0 +1,216 @@
|
||||
package com.jyn.vcview;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Editable;
|
||||
import android.text.InputFilter;
|
||||
import android.text.InputType;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author jiaoyaning
|
||||
* @package com.b2cf.nonghe.widget
|
||||
* @filename VerificationCodeView
|
||||
* @date 2017/10/31
|
||||
*/
|
||||
|
||||
public class VerificationCodeView extends LinearLayout implements TextWatcher, View.OnKeyListener, View.OnFocusChangeListener {
|
||||
|
||||
private Context mContext;
|
||||
private long endTime = 0;
|
||||
private OnCodeFinishListener onCodeFinishListener;
|
||||
|
||||
/**
|
||||
* 输入框数量
|
||||
*/
|
||||
private int mEtNumber;
|
||||
|
||||
/**
|
||||
* 输入框的宽度
|
||||
*/
|
||||
private int mEtWidth;
|
||||
|
||||
/**
|
||||
* 文字颜色
|
||||
*/
|
||||
private int mEtTextColor;
|
||||
|
||||
/**
|
||||
* 文字大小
|
||||
*/
|
||||
private float mEtTextSize;
|
||||
|
||||
/**
|
||||
* 输入框背景
|
||||
*/
|
||||
private int mEtTextBg;
|
||||
|
||||
private int mCursorDrawable;
|
||||
|
||||
public VerificationCodeView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this.mContext = context;
|
||||
@SuppressLint({"Recycle", "CustomViewStyleable"})
|
||||
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.vericationCodeView);
|
||||
mEtNumber = typedArray.getInteger(R.styleable.vericationCodeView_vcv_et_number, 4);
|
||||
mEtWidth = typedArray.getDimensionPixelSize(R.styleable.vericationCodeView_vcv_et_width, 120);
|
||||
mEtTextColor = typedArray.getColor(R.styleable.vericationCodeView_vcv_et_text_color, Color.BLACK);
|
||||
mEtTextSize = typedArray.getDimensionPixelSize(R.styleable.vericationCodeView_vcv_et_text_size, 16);
|
||||
mEtTextBg = typedArray.getResourceId(R.styleable.vericationCodeView_vcv_et_bg, R.drawable.et_login_code);
|
||||
mCursorDrawable = typedArray.getResourceId(R.styleable.vericationCodeView_vcv_et_cursor, R.drawable.et_cursor);
|
||||
|
||||
//释放资源
|
||||
typedArray.recycle();
|
||||
initView();
|
||||
}
|
||||
|
||||
@SuppressLint("ResourceAsColor")
|
||||
private void initView() {
|
||||
for (int i = 0; i < mEtNumber; i++) {
|
||||
EditText editText = new EditText(mContext);
|
||||
int childHPadding = 14;
|
||||
int childVPadding = 14;
|
||||
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(mEtWidth, mEtWidth);
|
||||
layoutParams.bottomMargin = childVPadding;
|
||||
layoutParams.topMargin = childVPadding;
|
||||
layoutParams.leftMargin = childHPadding;
|
||||
layoutParams.rightMargin = childHPadding;
|
||||
layoutParams.gravity = Gravity.CENTER;
|
||||
|
||||
editText.setLayoutParams(layoutParams);
|
||||
editText.setGravity(Gravity.CENTER);
|
||||
editText.setId(i);
|
||||
editText.setCursorVisible(true);
|
||||
editText.setMaxEms(1);
|
||||
editText.setTextColor(mEtTextColor);
|
||||
editText.setTextSize(mEtTextSize);
|
||||
editText.setMaxLines(1);
|
||||
editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)});
|
||||
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
|
||||
editText.setPadding(0, 0, 0, 0);
|
||||
editText.setOnKeyListener(this);
|
||||
editText.setBackgroundResource(mEtTextBg);
|
||||
try {//修改光标的颜色(反射)
|
||||
Field f = TextView.class.getDeclaredField("mCursorDrawableRes");
|
||||
f.setAccessible(true);
|
||||
f.set(editText, mCursorDrawable);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
editText.addTextChangedListener(this);
|
||||
editText.setOnFocusChangeListener(this);
|
||||
editText.setOnKeyListener(this);
|
||||
addView(editText);
|
||||
if (i == 0) {
|
||||
editText.setFocusable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
if (s.length() != 0) {
|
||||
focus();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_DEL) {
|
||||
backFocus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabled(boolean enabled) {
|
||||
int childCount = getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
View child = getChildAt(i);
|
||||
child.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取焦点
|
||||
*/
|
||||
private void focus() {
|
||||
int count = getChildCount();
|
||||
EditText editText;
|
||||
for (int i = 0; i < count; i++) {
|
||||
editText = (EditText) getChildAt(i);
|
||||
if (editText.getText().length() < 1) {
|
||||
editText.setCursorVisible(true);
|
||||
editText.requestFocus();
|
||||
return;
|
||||
} else {
|
||||
editText.setCursorVisible(false);
|
||||
}
|
||||
}
|
||||
EditText lastEditText = (EditText) getChildAt(mEtNumber - 1);
|
||||
if (lastEditText.getText().length() > 0) {
|
||||
lastEditText.requestFocus();
|
||||
getResult();
|
||||
}
|
||||
}
|
||||
|
||||
private void backFocus() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
EditText editText;
|
||||
for (int i = mEtNumber - 1; i >= 0; i--) {
|
||||
editText = (EditText) getChildAt(i);
|
||||
if (editText.getText().length() >= 1 && startTime - endTime > 100) {
|
||||
editText.setText("");
|
||||
editText.setCursorVisible(true);
|
||||
editText.requestFocus();
|
||||
endTime = startTime;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getResult() {
|
||||
StringBuffer stringBuffer = new StringBuffer();
|
||||
EditText editText;
|
||||
for (int i = 0; i < mEtNumber; i++) {
|
||||
editText = (EditText) getChildAt(i);
|
||||
stringBuffer.append(editText.getText());
|
||||
}
|
||||
if (onCodeFinishListener != null) {
|
||||
onCodeFinishListener.onComplete(stringBuffer.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
focus();
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnCodeFinishListener {
|
||||
void onComplete(String content);
|
||||
}
|
||||
}
|
||||
6
verificationcodeview/src/main/res/drawable/et_cursor.xml
Normal file
6
verificationcodeview/src/main/res/drawable/et_cursor.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:width="2dp" />
|
||||
<solid android:color="#0dbc75" />
|
||||
</shape>
|
||||
19
verificationcodeview/src/main/res/drawable/et_login_code.xml
Normal file
19
verificationcodeview/src/main/res/drawable/et_login_code.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:state_window_focused="false">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#FFFFFF" />
|
||||
<stroke android:width="1dp" android:color="#C4C4C4" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:state_focused="true">
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="#ffffff" />
|
||||
<stroke android:width="1dp" android:color="#0dbc75" />
|
||||
<corners android:radius="5dp" />
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
18
verificationcodeview/src/main/res/values/attrs.xml
Normal file
18
verificationcodeview/src/main/res/values/attrs.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- 自定义验证码输入框-->
|
||||
<declare-styleable name="vericationCodeView">
|
||||
<!--输入框的数量-->
|
||||
<attr name="vcv_et_number" format="integer" />
|
||||
<!--输入框的宽度-->
|
||||
<attr name="vcv_et_width" format="dimension|reference" />
|
||||
<!--输入框文字颜色-->
|
||||
<attr name="vcv_et_text_color" format="color|reference" />
|
||||
<!--输入框文字大小-->
|
||||
<attr name="vcv_et_text_size" format="dimension|reference" />
|
||||
<!--输入框背景-->
|
||||
<attr name="vcv_et_bg" format="reference" />
|
||||
<!--光标样式-->
|
||||
<attr name="vcv_et_cursor" format="reference" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
3
verificationcodeview/src/main/res/values/strings.xml
Normal file
3
verificationcodeview/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">VerificationCodeView</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.jyn.vcview;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user