diff --git a/README.md b/README.md
index 05959eb..3de72d4 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
[![Download](https://img.shields.io/badge/download-App-blue.svg)](https://raw.githubusercontent.com/jenly1314/SplitEditText/master/app/release/app-release.apk)
[![JCenter](https://img.shields.io/badge/JCenter-1.0.0-46C018.svg)](https://bintray.com/beta/#/jenly/maven/splitedittext)
+[![MavenCentral](https://img.shields.io/maven-central/v/com.github.jenly1314/splitedittext)](https://repo1.maven.org/maven2/com/github/jenly1314/splitedittext)
[![JitPack](https://jitpack.io/v/jenly1314/SplitEditText.svg)](https://jitpack.io/#jenly1314/SplitEditText)
[![CI](https://travis-ci.org/jenly1314/SplitEditText.svg?branch=master)](https://travis-ci.org/jenly1314/SplitEditText)
[![CircleCI](https://circleci.com/gh/jenly1314/SplitEditText.svg?style=svg)](https://circleci.com/gh/jenly1314/SplitEditText)
@@ -12,8 +13,6 @@
SplitEditText for Android 是一个灵活的分割编辑框。常常应用于 **验证码输入** 、**密码输入** 、等场景。
-> 之所以造这个轮子,是因为之前有这样的需求,然后也用过其它类似开源的库([VerificationCodeView](https://github.com/JackTuoTuo/VerificationCodeView)),但是需求随着需求的变动,之前使用的库就不太满足现有的需求。所以最近抽空写了一个。
-
## 特性说明
- [x] 支持设置框数量
- [x] 支持设置框的风格样式
@@ -42,37 +41,24 @@ SplitEditText for Android 是一个灵活的分割编辑框。常常应用于 **
## 引入
-### Maven:
-```maven
-
- com.king.view
- splitedittext
- 1.0.0
- pom
-
-```
-### Gradle:
-```gradle
-//AndroidX
-implementation 'com.king.view:splitedittext:1.0.0'
-```
+1. 在Project的 **build.gradle** 里面添加远程仓库
-### Lvy:
-```lvy
-
-
-
-```
-
-###### 如果Gradle出现compile失败的情况,可以在Project的build.gradle里面添加如下:(也可以使用上面的GitPack来complie)
```gradle
allprojects {
repositories {
- maven { url 'https://dl.bintray.com/jenly/maven' }
+ //...
+ mavenCentral()
}
}
```
+2. 在Module的 **build.gradle** 里面添加引入依赖项
+```gradle
+// AndroidX 版本
+implementation 'com.github.jenly1314:splitedittext:1.1.0'
+
+```
+
## 示例
布局示例
@@ -125,38 +111,41 @@ Java
## 相关推荐
+[CodeTextField](https://github.com/jenly1314/CodeTextField) 一个使用 Compose 实现的验证码输入框
+
[KingKeyboard](https://github.com/jenly1314/KingKeyboard) 自定义键盘,满足各种不同场景的键盘输入需求
## 版本记录
+#### v1.1.0:2023-1-9 (开始发布至MavenCentral)
+* 迁移发布至MavenCentral
+
#### v1.0.0:2021-1-5
* SplitEditText初始版本
## 赞赏
如果您喜欢SplitEditText,或感觉SplitEditText帮助到了您,可以点右上角“Star”支持一下,您的支持就是我的动力,谢谢 :smiley:
您也可以扫描下面的二维码,请作者喝杯咖啡 :coffee:
-
+
+
+
## 关于我
- Name: Jenly
+Name: Jenly
- Email: jenly1314#gmail.com / jenly1314#vip.qq.com
+Email: jenly1314#gmail.com / jenly1314#vip.qq.com
- CSDN: jenly121
+CSDN: jenly121
- CNBlogs: jenly
+CNBlogs: jenly
- GitHub: jenly1314
+GitHub: jenly1314
- Gitee: jenly1314
+Gitee: jenly1314
- 加入QQ群: 20867961
+加入QQ群: 20867961
+
diff --git a/app/build.gradle b/app/build.gradle
index 12348b0..d4f4880 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -42,7 +42,7 @@ dependencies {
testImplementation "junit:junit:$versions.junit"
androidTestImplementation "androidx.test.ext:junit:$versions.androidExtJunit"
androidTestImplementation "androidx.test.espresso:espresso-core:$versions.espressoCore"
+ implementation project(':splitedittext')
- implementation project(':split-edit-text')
}
diff --git a/app/release/app-release.apk b/app/release/app-release.apk
index da42218..7256f4c 100644
Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ
diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json
new file mode 100644
index 0000000..95dfa37
--- /dev/null
+++ b/app/release/output-metadata.json
@@ -0,0 +1,18 @@
+{
+ "version": 2,
+ "artifactType": {
+ "type": "APK",
+ "kind": "Directory"
+ },
+ "applicationId": "com.king.view.splitedittext.app",
+ "variantName": "release",
+ "elements": [
+ {
+ "type": "SINGLE",
+ "filters": [],
+ "versionCode": 2,
+ "versionName": "1.1.0",
+ "outputFile": "app-release.apk"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/app/release/output.json b/app/release/output.json
deleted file mode 100644
index 89d432c..0000000
--- a/app/release/output.json
+++ /dev/null
@@ -1 +0,0 @@
-[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":1,"versionName":"1.0.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index a79c9cc..07e07dd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,23 +4,30 @@ buildscript {
apply from: 'versions.gradle'
repositories {
google()
- jcenter()
+ mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:$versions.gradle"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$versions.dokka"
-
- classpath "com.github.panpf.bintray-publish:bintray-publish:$versions.bintrayRelease"
+// classpath "com.github.panpf.bintray-publish:bintray-publish:$versions.bintrayRelease"
+ classpath "com.vanniktech:gradle-maven-publish-plugin:$versions.mavenPublish"
}
}
allprojects {
repositories {
google()
- jcenter()
+ mavenCentral()
+ }
+}
+allprojects {
+ plugins.withId("com.vanniktech.maven.publish") {
+ mavenPublish {
+ sonatypeHost = "S01"
+ }
}
}
diff --git a/gradle.properties b/gradle.properties
index e21dd54..d458377 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -18,4 +18,29 @@ android.useAndroidX = true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier = true
# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style = official
\ No newline at end of file
+kotlin.code.style = official
+
+VERSION_NAME=1.1.0
+VERSION_CODE=2
+GROUP=com.github.jenly1314
+
+POM_DESCRIPTION=SplitEditText for Android
+POM_URL=https://github.com/jenly1314/SplitEditText
+
+POM_SCM_URL=https://github.com/jenly1314/SplitEditText
+POM_SCM_CONNECTION=scm:git@github.com:jenly1314/SplitEditText.git
+POM_SCM_DEV_CONNECTION=scm:git@github.com:jenly1314/SplitEditText.git
+
+POM_LICENCE_NAME=The MIT License
+POM_LICENCE_URL=https://opensource.org/licenses/mit-license.php
+#POM_LICENCE_NAME=The Apache Software License, Version 2.0
+#POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
+
+POM_DEVELOPER_ID=jenly
+POM_DEVELOPER_NAME=Jenly Yu
+POM_DEVELOPER_URL=https://github.com/jenly1314/
+
+RELEASE_REPOSITORY_URL=https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
+SNAPSHOT_REPOSITORY_URL=https://s01.oss.sonatype.org/content/repositories/snapshots/
+
+RELEASE_SIGNING_ENABLED=false
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 84f773a..c73be40 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
diff --git a/settings.gradle b/settings.gradle
index 57cafe9..e4f6929 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,3 @@
-include ':split-edit-text'
+include ':splitedittext'
include ':app'
rootProject.name = "SplitEditText"
\ No newline at end of file
diff --git a/split-edit-text/.gitignore b/splitedittext/.gitignore
similarity index 100%
rename from split-edit-text/.gitignore
rename to splitedittext/.gitignore
diff --git a/split-edit-text/bintray.gradle b/splitedittext/bintray.gradle
similarity index 97%
rename from split-edit-text/bintray.gradle
rename to splitedittext/bintray.gradle
index da23dac..990b222 100644
--- a/split-edit-text/bintray.gradle
+++ b/splitedittext/bintray.gradle
@@ -1,13 +1,13 @@
-//apply plugin: 'com.novoda.bintray-release'
-apply plugin: 'com.github.panpf.bintray-publish'
-
-//添加
-publish {
- userOrg = 'jenly'//bintray.com用户名
- groupId = 'com.king.view'//jcenter上的路径
- artifactId = 'splitedittext'//项目名称
- publishVersion = app_version.versionName//版本号
- desc = 'SplitEditText for Android'//描述
- website = 'https://github.com/jenly1314/SplitEditText'//网站
- licences = ['MIT']//开源协议
+//apply plugin: 'com.novoda.bintray-release'
+apply plugin: 'com.github.panpf.bintray-publish'
+
+//添加
+publish {
+ userOrg = 'jenly'//bintray.com用户名
+ groupId = 'com.king.view'//jcenter上的路径
+ artifactId = 'splitedittext'//项目名称
+ publishVersion = app_version.versionName//版本号
+ desc = 'SplitEditText for Android'//描述
+ website = 'https://github.com/jenly1314/SplitEditText'//网站
+ licences = ['MIT']//开源协议
}
\ No newline at end of file
diff --git a/split-edit-text/build.gradle b/splitedittext/build.gradle
similarity index 93%
rename from split-edit-text/build.gradle
rename to splitedittext/build.gradle
index 17ff013..05f3ceb 100644
--- a/split-edit-text/build.gradle
+++ b/splitedittext/build.gradle
@@ -1,43 +1,43 @@
-apply plugin: 'com.android.library'
-apply from: 'bintray.gradle'
-
-
-android {
- compileSdkVersion build_versions.compileSdk
- buildToolsVersion build_versions.buildTools
-
- defaultConfig {
- minSdkVersion build_versions.minSdk
- targetSdkVersion build_versions.targetSdk
- versionCode app_version.versionCode
- versionName app_version.versionName
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- consumerProguardFiles 'consumer-rules.pro'
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
-
- lintOptions {
- abortOnError false
- warning 'InvalidPackage'
- }
-
-}
-
-dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
-
- testImplementation "junit:junit:$versions.junit"
- androidTestImplementation "androidx.test.ext:junit:$versions.androidExtJunit"
- androidTestImplementation "androidx.test.espresso:espresso-core:$versions.espressoCore"
-
- compileOnly "androidx.appcompat:appcompat:$versions.appcompat"
-
-}
-
+apply plugin: 'com.android.library'
+//apply from: 'bintray.gradle'
+apply plugin: "com.vanniktech.maven.publish"
+
+android {
+ compileSdkVersion build_versions.compileSdk
+ buildToolsVersion build_versions.buildTools
+
+ defaultConfig {
+ minSdkVersion build_versions.minSdk
+ targetSdkVersion build_versions.targetSdk
+ versionCode app_version.versionCode
+ versionName app_version.versionName
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles 'consumer-rules.pro'
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ lintOptions {
+ abortOnError false
+ warning 'InvalidPackage'
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+
+ testImplementation "junit:junit:$versions.junit"
+ androidTestImplementation "androidx.test.ext:junit:$versions.androidExtJunit"
+ androidTestImplementation "androidx.test.espresso:espresso-core:$versions.espressoCore"
+
+ compileOnly "androidx.appcompat:appcompat:$versions.appcompat"
+
+}
+
diff --git a/split-edit-text/consumer-rules.pro b/splitedittext/consumer-rules.pro
similarity index 100%
rename from split-edit-text/consumer-rules.pro
rename to splitedittext/consumer-rules.pro
diff --git a/splitedittext/gradle.properties b/splitedittext/gradle.properties
new file mode 100644
index 0000000..90f0177
--- /dev/null
+++ b/splitedittext/gradle.properties
@@ -0,0 +1,3 @@
+POM_NAME=SplitEditText
+POM_ARTIFACT_ID=splitedittext
+POM_PACKAGING=aar
\ No newline at end of file
diff --git a/split-edit-text/proguard-rules.pro b/splitedittext/proguard-rules.pro
similarity index 97%
rename from split-edit-text/proguard-rules.pro
rename to splitedittext/proguard-rules.pro
index 64b4a05..481bb43 100644
--- a/split-edit-text/proguard-rules.pro
+++ b/splitedittext/proguard-rules.pro
@@ -1,21 +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.
+# 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
\ No newline at end of file
diff --git a/split-edit-text/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java b/splitedittext/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java
similarity index 96%
rename from split-edit-text/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java
rename to splitedittext/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java
index 788822f..b0994dd 100644
--- a/split-edit-text/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java
+++ b/splitedittext/src/androidTest/java/com/king/view/splitedittext/ExampleInstrumentedTest.java
@@ -1,26 +1,26 @@
-package com.king.view.splitedittext;
-
-import android.content.Context;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.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 Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
- assertEquals("com.king.view.splitedittext.test", appContext.getPackageName());
- }
+package com.king.view.splitedittext;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.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 Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.king.view.splitedittext.test", appContext.getPackageName());
+ }
}
\ No newline at end of file
diff --git a/split-edit-text/src/main/AndroidManifest.xml b/splitedittext/src/main/AndroidManifest.xml
similarity index 97%
rename from split-edit-text/src/main/AndroidManifest.xml
rename to splitedittext/src/main/AndroidManifest.xml
index dcbcc77..c762f4e 100644
--- a/split-edit-text/src/main/AndroidManifest.xml
+++ b/splitedittext/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/split-edit-text/src/main/java/com/king/view/splitedittext/SplitEditText.java b/splitedittext/src/main/java/com/king/view/splitedittext/SplitEditText.java
similarity index 64%
rename from split-edit-text/src/main/java/com/king/view/splitedittext/SplitEditText.java
rename to splitedittext/src/main/java/com/king/view/splitedittext/SplitEditText.java
index 2860d66..90f84d7 100644
--- a/split-edit-text/src/main/java/com/king/view/splitedittext/SplitEditText.java
+++ b/splitedittext/src/main/java/com/king/view/splitedittext/SplitEditText.java
@@ -1,574 +1,605 @@
-package com.king.view.splitedittext;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.text.InputFilter;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.appcompat.widget.AppCompatEditText;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * @author Jenly
- */
-public class SplitEditText extends AppCompatEditText {
-
- /**
- * 画笔
- */
- private Paint mPaint;
-
- /**
- * 画笔宽度
- */
- private float mStrokeWidth;
-
- /**
- * 边框颜色
- */
- private int mBorderColor = 0xFF666666;
- /**
- * 输入的边框颜色
- */
- private int mInputBorderColor = 0xFF1E90FF;
- /**
- * 焦点的边框颜色
- */
- private int mFocusBorderColor;
-
- /**
- * 框的背景颜色
- */
- private int mBoxBackgroundColor;
-
- /**
- * 框的圆角大小
- */
- private float mBorderCornerRadius;
-
- /**
- * 框与框之间的间距大小
- */
- private float mBorderSpacing;
-
- /**
- * 输入框宽度
- */
- private float mBoxWidth;
-
- /**
- * 输入框高度
- */
- private float mBoxHeight;
-
- /**
- * 允许输入的最大长度
- */
- private int mMaxLength = 6;
-
- /**
- * 文本长度
- */
- private int mTextLength;
- /**
- * 路径
- */
- private Path mPath;
-
- private RectF mRectF;
- private float[] mRadiusFirstArray;
- private float[] mRadiusLastArray;
-
- /**
- * 边框风格
- */
- private @BorderStyle int mBorderStyle = BorderStyle.BOX;
-
- /**
- * 边框风格
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({BorderStyle.BOX, BorderStyle.LINE})
- public @interface BorderStyle {
- /**
- * 框
- */
- int BOX = 0;
- /**
- * 线
- */
- int LINE = 1;
- }
-
- /**
- * 文本风格
- */
- private @TextStyle int mTextStyle = TextStyle.PLAIN_TEXT;
-
-
- /**
- * 文本风格
- */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({TextStyle.PLAIN_TEXT, TextStyle.CIPHER_TEXT})
- public @interface TextStyle {
- /**
- * 明文
- */
- int PLAIN_TEXT = 0;
- /**
- * 密文
- */
- int CIPHER_TEXT = 1;
- }
-
- /**
- * 密文掩码
- */
- private String mCipherMask;
-
- /**
- * 是否是粗体
- */
- private boolean isFakeBoldText;
-
- private static final String DEFAULT_CIPHER_MASK = "*";
-
- private boolean isDraw;
-
- private OnTextInputListener mOnTextInputListener;
-
- public SplitEditText(@NonNull Context context) {
- this(context,null);
- }
-
- public SplitEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
- this(context, attrs,android.R.attr.editTextStyle);
- }
-
- public SplitEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init(context,attrs);
- }
-
-
- private void init(@NonNull Context context, @Nullable AttributeSet attrs){
-
- DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
- mStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1f,displayMetrics);
- mBorderSpacing = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,8f,displayMetrics);
- setPadding(0,0,0,0);
-
- TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.SplitEditText);
- final int count = a.getIndexCount();
- for (int i = 0; i < count; i++) {
- int attr = a.getIndex(i);
- if(attr == R.styleable.SplitEditText_setStrokeWidth){
- mStrokeWidth = a.getDimension(attr,mStrokeWidth);
- }else if (attr == R.styleable.SplitEditText_setBorderColor){
- mBorderColor = a.getColor(attr,mBorderColor);
- }else if (attr == R.styleable.SplitEditText_setInputBorderColor){
- mInputBorderColor = a.getColor(attr,mInputBorderColor);
- }else if (attr == R.styleable.SplitEditText_setFocusBorderColor){
- mFocusBorderColor = a.getColor(attr,mFocusBorderColor);
- }else if (attr == R.styleable.SplitEditText_setBoxBackgroundColor){
- mBoxBackgroundColor = a.getColor(attr,mBoxBackgroundColor);
- }else if (attr == R.styleable.SplitEditText_setBorderCornerRadius){
- mBorderCornerRadius = a.getDimension(attr,mBorderCornerRadius);
- }else if (attr == R.styleable.SplitEditText_setBorderSpacing){
- mBorderSpacing = a.getDimension(attr,mBorderSpacing);
- }else if (attr == R.styleable.SplitEditText_setMaxLength){
- mMaxLength = a.getInt(attr,mMaxLength);
- }else if (attr == R.styleable.SplitEditText_setBorderStyle){
- mBorderStyle = a.getInt(attr,mBorderStyle);
- }else if (attr == R.styleable.SplitEditText_setTextStyle){
- mTextStyle = a.getInt(attr,mTextStyle);
- }else if (attr == R.styleable.SplitEditText_setCipherMask){
- mCipherMask = a.getString(attr);
- }else if (attr == R.styleable.SplitEditText_setFakeBoldText){
- isFakeBoldText = a.getBoolean(attr,false);
- }
- }
-
- a.recycle();
-
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setAntiAlias(true);
- mPaint.setTextAlign(Paint.Align.CENTER);
-
- mPath = new Path();
- mRadiusFirstArray = new float[8];
- mRadiusLastArray = new float[8];
- mRectF = new RectF(0,0,0,0);
-
- if(TextUtils.isEmpty(mCipherMask)){
- mCipherMask = DEFAULT_CIPHER_MASK;
- }else if(mCipherMask.length() > 1){
- mCipherMask = mCipherMask.substring(0,1);
- }
-
- setBackground(null);
- setCursorVisible(false);
- setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)});
- }
-
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
-
- int width = w - getPaddingLeft() - getPaddingRight();
- int height = h - getPaddingTop() - getPaddingBottom();
- updateSizeChanged(width,height);
- }
-
- private void updateSizeChanged(int width,int height){
- //如果框与框之间的间距小于0或者总间距大于控件可用宽度则将间距重置为0
- if(mBorderSpacing < 0 || (mMaxLength - 1) * mBorderSpacing > width){
- mBorderSpacing = 0;
- }
- //计算出每个框的宽度
- mBoxWidth = (width - (mMaxLength - 1) * mBorderSpacing) / mMaxLength - mStrokeWidth;
- mBoxHeight = height - mStrokeWidth;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- //移除super.onDraw(canvas);不绘制EditText相关的
- //绘制边框
- drawBorders(canvas);
- }
-
- private void drawBorders(Canvas canvas){
- isDraw = true;
- //遍历绘制未输入文本的框边界
- for(int i = mTextLength; i < mMaxLength; i++){
- drawBorder(canvas,i,mBorderColor);
- }
-
- int color = mInputBorderColor != 0 ? mInputBorderColor : mBorderColor;
- //遍历绘制已输入文本的框边界
- for(int i = 0; i < mTextLength; i++){
- drawBorder(canvas,i,color);
- }
-
- //绘制焦点框边界
- if(mTextLength < mMaxLength && mFocusBorderColor != 0 && isFocused()){
- drawBorder(canvas,mTextLength,mFocusBorderColor);
- }
- }
-
- private void drawBorder(Canvas canvas,int position,int borderColor){
- mPaint.setStrokeWidth(mStrokeWidth);
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setFakeBoldText(false);
- mPaint.setColor(borderColor);
-
- //计算出对应的矩形
- float left = getPaddingLeft() + mStrokeWidth / 2 + (mBoxWidth + mBorderSpacing) * position;
- float top = getPaddingTop() + mStrokeWidth / 2;
- mRectF.set(left,top,left + mBoxWidth,top + mBoxHeight);
-
- //边框风格
- switch (mBorderStyle){
- case BorderStyle.BOX:
- drawBorderBox(canvas,position,borderColor);
- break;
- case BorderStyle.LINE:
- drawBorderLine(canvas);
- break;
- }
- if(mTextLength > position && !TextUtils.isEmpty(getText())){
- drawText(canvas,position);
- }
- }
-
- private void drawText(Canvas canvas,int position){
- mPaint.setStrokeWidth(0);
- mPaint.setColor(getCurrentTextColor());
- mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
- mPaint.setTextSize(getTextSize());
- mPaint.setFakeBoldText(isFakeBoldText);
- float x = mRectF.centerX();
- //y轴坐标 = 中心线 + 文字高度的一半 - 基线到文字底部的距离(也就是bottom)
- float y = mRectF.centerY() + (mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top) / 2 - mPaint.getFontMetrics().bottom;
- switch (mTextStyle){
- case TextStyle.PLAIN_TEXT:
- canvas.drawText(String.valueOf(getText().charAt(position)),x,y,mPaint);
- break;
- case TextStyle.CIPHER_TEXT:
- canvas.drawText(mCipherMask,x,y,mPaint);
- break;
- }
- }
-
- /**
- * 绘制框风格
- * @param canvas
- * @param position
- */
- private void drawBorderBox(Canvas canvas,int position,int borderColor){
- if(mBorderCornerRadius > 0){//当边框带有圆角时
- if(mBorderSpacing == 0){//当边框之间的间距为0时,只需要开始一个和最后一个框有圆角
- if(position == 0 || position == mMaxLength - 1){
- if(mBoxBackgroundColor != 0){
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(mBoxBackgroundColor);
- canvas.drawPath(getRoundRectPath(mRectF,position == 0),mPaint);
- }
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(borderColor);
- canvas.drawPath(getRoundRectPath(mRectF,position == 0),mPaint);
- }else{
- if(mBoxBackgroundColor != 0){
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(mBoxBackgroundColor);
- canvas.drawRect(mRectF,mPaint);
- }
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(borderColor);
- canvas.drawRect(mRectF,mPaint);
- }
- }else{
- if(mBoxBackgroundColor != 0){
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(mBoxBackgroundColor);
- canvas.drawRoundRect(mRectF,mBorderCornerRadius,mBorderCornerRadius,mPaint);
- }
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(borderColor);
- canvas.drawRoundRect(mRectF,mBorderCornerRadius,mBorderCornerRadius,mPaint);
- }
- }else{
- if(mBoxBackgroundColor != 0){
- mPaint.setStyle(Paint.Style.FILL);
- mPaint.setColor(mBoxBackgroundColor);
- canvas.drawRect(mRectF,mPaint);
- }
- mPaint.setStyle(Paint.Style.STROKE);
- mPaint.setColor(borderColor);
- canvas.drawRect(mRectF,mPaint);
- }
- }
-
- /**
- * 绘制线风格
- * @param canvas
- */
- private void drawBorderLine(Canvas canvas){
- float y = getPaddingTop() + mBoxHeight;
- canvas.drawLine(mRectF.left,y,mRectF.right,y,mPaint);
- }
-
- private Path getRoundRectPath(RectF rectF,boolean isFirst){
- mPath.reset();
- if(isFirst){
- //左上角
- mRadiusFirstArray[0] = mBorderCornerRadius;
- mRadiusFirstArray[1] = mBorderCornerRadius;
- //左下角
- mRadiusFirstArray[6] = mBorderCornerRadius;
- mRadiusFirstArray[7] = mBorderCornerRadius;
- mPath.addRoundRect(rectF,mRadiusFirstArray, Path.Direction.CW);
- }else{
- //右上角
- mRadiusLastArray[2] = mBorderCornerRadius;
- mRadiusLastArray[3] = mBorderCornerRadius;
- //右下角
- mRadiusLastArray[4] = mBorderCornerRadius;
- mRadiusLastArray[5] = mBorderCornerRadius;
- mPath.addRoundRect(rectF,mRadiusLastArray, Path.Direction.CW);
- }
- return mPath;
- }
-
-
- @Override
- protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
- super.onTextChanged(text, start, lengthBefore, lengthAfter);
- mTextLength = text.length();
- refreshView();
- //改变监听
- if(mOnTextInputListener != null){
- mOnTextInputListener.onTextInputChanged(text.toString(),mTextLength);
- if(mTextLength == mMaxLength){
- mOnTextInputListener.onTextInputCompleted(text.toString());
- }
- }
- }
-
- @Override
- protected void onSelectionChanged(int selStart, int selEnd) {
- super.onSelectionChanged(selStart, selEnd);
- if (selStart == selEnd) {
- setSelection(getText() == null ? 0 : getText().length());
- }
- }
-
- @Override
- protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(focused, direction, previouslyFocusedRect);
- //焦点改变时刷新状态
- refreshView();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- isDraw = false;
- }
-
- public int getBorderColor() {
- return mBorderColor;
- }
-
- public int getInputBorderColor() {
- return mInputBorderColor;
- }
-
- public int getFocusBorderColor() {
- return mFocusBorderColor;
- }
-
- public int getBoxBackgroundColor() {
- return mBoxBackgroundColor;
- }
-
- public float getBorderCornerRadius() {
- return mBorderCornerRadius;
- }
-
- public float getBorderSpacing() {
- return mBorderSpacing;
- }
-
- @BorderStyle
- public int getBorderStyle() {
- return mBorderStyle;
- }
-
-
- public void setBorderColor(int borderColor) {
- this.mBorderColor = borderColor;
- refreshView();
- }
-
- public void setInputBorderColor(int inputBorderColor) {
- this.mInputBorderColor = inputBorderColor;
- refreshView();
- }
-
- public void setFocusBorderColor(int focusBorderColor) {
- this.mFocusBorderColor = focusBorderColor;
- refreshView();
- }
-
- public void setBoxBackgroundColor(int boxBackgroundColor) {
- this.mBoxBackgroundColor = boxBackgroundColor;
- refreshView();
- }
-
- public void setBorderCornerRadius(float borderCornerRadius) {
- this.mBorderCornerRadius = borderCornerRadius;
- refreshView();
- }
-
- public void setBorderSpacing(float borderSpacing) {
- this.mBorderSpacing = borderSpacing;
- refreshView();
- }
-
- public void setBorderStyle(@TextStyle int borderStyle) {
- this.mBorderStyle = borderStyle;
- refreshView();
- }
-
- @TextStyle
- public int getTextStyle() {
- return mTextStyle;
- }
-
- public void setTextStyle(@TextStyle int textStyle) {
- this.mTextStyle = textStyle;
- refreshView();
- }
-
- public String getCipherMask() {
- return mCipherMask;
- }
-
- /**
- * 是否粗体
- * @param fakeBoldText
- */
- public void setFakeBoldText(boolean fakeBoldText) {
- isFakeBoldText = fakeBoldText;
- refreshView();
- }
-
- /**
- * 设置密文掩码 不设置时,默认为{@link #DEFAULT_CIPHER_MASK}
- * @param cipherMask
- */
- public void setCipherMask(String cipherMask) {
- this.mCipherMask = cipherMask;
- refreshView();
- }
-
- /**
- * 刷新视图
- */
- private void refreshView(){
- if(isDraw){
- invalidate();
- }
- }
-
- /**
- * 设置文本输入监听
- * @param onTextInputListener
- */
- public void setOnTextInputListener(OnTextInputListener onTextInputListener) {
- this.mOnTextInputListener = onTextInputListener;
- }
-
- public static abstract class OnSimpleTextInputListener implements OnTextInputListener{
-
- @Override
- public void onTextInputChanged(String text, int length) {
-
- }
-
- }
-
- /**
- * 文本输入监听
- */
- public interface OnTextInputListener{
- /**
- * Text改变监听
- * @param text
- * @param length
- */
- void onTextInputChanged(String text,int length);
-
- /**
- * Text输入完成
- * @param text
- */
- void onTextInputCompleted(String text);
- }
-}
+package com.king.view.splitedittext;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.text.InputFilter;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatEditText;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author Jenly
+ */
+public class SplitEditText extends AppCompatEditText {
+
+ /**
+ * 画笔
+ */
+ private Paint mPaint;
+ /**
+ * 画笔宽度
+ */
+ private float mStrokeWidth;
+ /**
+ * 边框颜色
+ */
+ private int mBorderColor = 0xFF666666;
+ /**
+ * 输入的边框颜色
+ */
+ private int mInputBorderColor = 0xFF1E90FF;
+ /**
+ * 焦点的边框颜色
+ */
+ private int mFocusBorderColor;
+
+ /**
+ * 框的背景颜色
+ */
+ private int mBoxBackgroundColor;
+
+ /**
+ * 框的圆角大小
+ */
+ private float mBorderCornerRadius;
+
+ /**
+ * 框与框之间的间距大小
+ */
+ private float mBorderSpacing;
+
+ /**
+ * 输入框宽度
+ */
+ private float mBoxWidth;
+
+ /**
+ * 输入框高度
+ */
+ private float mBoxHeight;
+
+ /**
+ * 允许输入的最大长度
+ */
+ private int mMaxLength = 6;
+
+ /**
+ * 文本长度
+ */
+ private int mTextLength;
+ /**
+ * 路径
+ */
+ private Path mPath;
+
+ private RectF mRectF;
+ private float[] mRadiusFirstArray;
+ private float[] mRadiusLastArray;
+
+ /**
+ * 边框风格
+ */
+ private @BorderStyle
+ int mBorderStyle = BorderStyle.BOX;
+
+ /**
+ * 边框风格
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({BorderStyle.BOX, BorderStyle.LINE})
+ public @interface BorderStyle {
+ /**
+ * 框
+ */
+ int BOX = 0;
+ /**
+ * 线
+ */
+ int LINE = 1;
+ }
+
+ /**
+ * 文本风格
+ */
+ private @TextStyle
+ int mTextStyle = TextStyle.PLAIN_TEXT;
+
+ /**
+ * 文本风格
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TextStyle.PLAIN_TEXT, TextStyle.CIPHER_TEXT})
+ public @interface TextStyle {
+ /**
+ * 明文
+ */
+ int PLAIN_TEXT = 0;
+ /**
+ * 密文
+ */
+ int CIPHER_TEXT = 1;
+ }
+
+ /**
+ * 密文掩码
+ */
+ private String mCipherMask;
+
+ /**
+ * 是否是粗体
+ */
+ private boolean isFakeBoldText;
+ /**
+ * 默认密码显示的掩码
+ */
+ private static final String DEFAULT_CIPHER_MASK = "*";
+
+ private boolean isDraw;
+
+ private OnTextInputListener mOnTextInputListener;
+
+ public SplitEditText(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public SplitEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, android.R.attr.editTextStyle);
+ }
+
+ public SplitEditText(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context, attrs);
+ }
+
+ /**
+ * 初始化
+ *
+ * @param context
+ * @param attrs
+ */
+ private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
+
+ DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
+ mStrokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1f, displayMetrics);
+ mBorderSpacing = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, displayMetrics);
+ setPadding(0, 0, 0, 0);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SplitEditText);
+ final int count = a.getIndexCount();
+ for (int i = 0; i < count; i++) {
+ int attr = a.getIndex(i);
+ if (attr == R.styleable.SplitEditText_setStrokeWidth) {
+ mStrokeWidth = a.getDimension(attr, mStrokeWidth);
+ } else if (attr == R.styleable.SplitEditText_setBorderColor) {
+ mBorderColor = a.getColor(attr, mBorderColor);
+ } else if (attr == R.styleable.SplitEditText_setInputBorderColor) {
+ mInputBorderColor = a.getColor(attr, mInputBorderColor);
+ } else if (attr == R.styleable.SplitEditText_setFocusBorderColor) {
+ mFocusBorderColor = a.getColor(attr, mFocusBorderColor);
+ } else if (attr == R.styleable.SplitEditText_setBoxBackgroundColor) {
+ mBoxBackgroundColor = a.getColor(attr, mBoxBackgroundColor);
+ } else if (attr == R.styleable.SplitEditText_setBorderCornerRadius) {
+ mBorderCornerRadius = a.getDimension(attr, mBorderCornerRadius);
+ } else if (attr == R.styleable.SplitEditText_setBorderSpacing) {
+ mBorderSpacing = a.getDimension(attr, mBorderSpacing);
+ } else if (attr == R.styleable.SplitEditText_setMaxLength) {
+ mMaxLength = a.getInt(attr, mMaxLength);
+ } else if (attr == R.styleable.SplitEditText_setBorderStyle) {
+ mBorderStyle = a.getInt(attr, mBorderStyle);
+ } else if (attr == R.styleable.SplitEditText_setTextStyle) {
+ mTextStyle = a.getInt(attr, mTextStyle);
+ } else if (attr == R.styleable.SplitEditText_setCipherMask) {
+ mCipherMask = a.getString(attr);
+ } else if (attr == R.styleable.SplitEditText_setFakeBoldText) {
+ isFakeBoldText = a.getBoolean(attr, false);
+ }
+ }
+
+ a.recycle();
+
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPaint.setAntiAlias(true);
+ mPaint.setTextAlign(Paint.Align.CENTER);
+
+ mPath = new Path();
+ mRadiusFirstArray = new float[8];
+ mRadiusLastArray = new float[8];
+ mRectF = new RectF(0, 0, 0, 0);
+
+ if (TextUtils.isEmpty(mCipherMask)) {
+ mCipherMask = DEFAULT_CIPHER_MASK;
+ } else if (mCipherMask.length() > 1) {
+ mCipherMask = mCipherMask.substring(0, 1);
+ }
+
+ setBackground(null);
+ setCursorVisible(false);
+ setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)});
+ }
+
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+ int width = w - getPaddingLeft() - getPaddingRight();
+ int height = h - getPaddingTop() - getPaddingBottom();
+ updateSizeChanged(width, height);
+ }
+
+ private void updateSizeChanged(int width, int height) {
+ // 如果框与框之间的间距小于0或者总间距大于控件可用宽度则将间距重置为0
+ if (mBorderSpacing < 0 || (mMaxLength - 1) * mBorderSpacing > width) {
+ mBorderSpacing = 0;
+ }
+ // 计算出每个框的宽度
+ mBoxWidth = (width - (mMaxLength - 1) * mBorderSpacing) / mMaxLength - mStrokeWidth;
+ mBoxHeight = height - mStrokeWidth;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ // 移除super.onDraw(canvas);不绘制EditText相关的
+ // 绘制边框
+ drawBorders(canvas);
+ }
+
+ /**
+ * 绘制边框 - 根据最大长度绘制边框
+ *
+ * @param canvas
+ */
+ private void drawBorders(Canvas canvas) {
+ isDraw = true;
+ // 遍历绘制未输入文本的框边界
+ for (int i = mTextLength; i < mMaxLength; i++) {
+ drawBorder(canvas, i, mBorderColor);
+ }
+
+ int color = mInputBorderColor != 0 ? mInputBorderColor : mBorderColor;
+ // 遍历绘制已输入文本的框边界
+ for (int i = 0; i < mTextLength; i++) {
+ drawBorder(canvas, i, color);
+ }
+
+ // 绘制焦点框边界
+ if (mTextLength < mMaxLength && mFocusBorderColor != 0 && isFocused()) {
+ drawBorder(canvas, mTextLength, mFocusBorderColor);
+ }
+ }
+
+ /**
+ * 绘制边框
+ *
+ * @param canvas
+ * @param position
+ * @param borderColor
+ */
+ private void drawBorder(Canvas canvas, int position, int borderColor) {
+ mPaint.setStrokeWidth(mStrokeWidth);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setFakeBoldText(false);
+ mPaint.setColor(borderColor);
+
+ // 计算出对应的矩形
+ float left = getPaddingLeft() + mStrokeWidth / 2 + (mBoxWidth + mBorderSpacing) * position;
+ float top = getPaddingTop() + mStrokeWidth / 2;
+ mRectF.set(left, top, left + mBoxWidth, top + mBoxHeight);
+
+ // 边框风格
+ switch (mBorderStyle) {
+ case BorderStyle.BOX:
+ drawBorderBox(canvas, position, borderColor);
+ break;
+ case BorderStyle.LINE:
+ drawBorderLine(canvas);
+ break;
+ }
+ if (mTextLength > position && !TextUtils.isEmpty(getText())) {
+ drawText(canvas, position);
+ }
+ }
+
+ /**
+ * 绘制文本内容
+ * @param canvas
+ * @param position
+ */
+ private void drawText(Canvas canvas, int position) {
+ mPaint.setStrokeWidth(0);
+ mPaint.setColor(getCurrentTextColor());
+ mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ mPaint.setTextSize(getTextSize());
+ mPaint.setFakeBoldText(isFakeBoldText);
+ float x = mRectF.centerX();
+ // y轴坐标 = 中心线 + 文字高度的一半 - 基线到文字底部的距离(也就是bottom)
+ float y = mRectF.centerY() + (mPaint.getFontMetrics().bottom - mPaint.getFontMetrics().top) / 2 - mPaint.getFontMetrics().bottom;
+ switch (mTextStyle) {
+ case TextStyle.PLAIN_TEXT:
+ canvas.drawText(String.valueOf(getText().charAt(position)), x, y, mPaint);
+ break;
+ case TextStyle.CIPHER_TEXT:
+ canvas.drawText(mCipherMask, x, y, mPaint);
+ break;
+ }
+ }
+
+ /**
+ * 绘制框风格
+ *
+ * @param canvas
+ * @param position
+ */
+ private void drawBorderBox(Canvas canvas, int position, int borderColor) {
+ // 当边框带有圆角时
+ if (mBorderCornerRadius > 0) {
+ // 当边框之间的间距为0时,只需要开始一个和最后一个框有圆角
+ if (mBorderSpacing == 0) {
+ if (position == 0 || position == mMaxLength - 1) {
+ if (mBoxBackgroundColor != 0) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(mBoxBackgroundColor);
+ canvas.drawPath(getRoundRectPath(mRectF, position == 0), mPaint);
+ }
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(borderColor);
+ canvas.drawPath(getRoundRectPath(mRectF, position == 0), mPaint);
+ } else {
+ if (mBoxBackgroundColor != 0) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(mBoxBackgroundColor);
+ canvas.drawRect(mRectF, mPaint);
+ }
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(borderColor);
+ canvas.drawRect(mRectF, mPaint);
+ }
+ } else {
+ if (mBoxBackgroundColor != 0) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(mBoxBackgroundColor);
+ canvas.drawRoundRect(mRectF, mBorderCornerRadius, mBorderCornerRadius, mPaint);
+ }
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(borderColor);
+ canvas.drawRoundRect(mRectF, mBorderCornerRadius, mBorderCornerRadius, mPaint);
+ }
+ } else {
+ if (mBoxBackgroundColor != 0) {
+ mPaint.setStyle(Paint.Style.FILL);
+ mPaint.setColor(mBoxBackgroundColor);
+ canvas.drawRect(mRectF, mPaint);
+ }
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setColor(borderColor);
+ canvas.drawRect(mRectF, mPaint);
+ }
+ }
+
+ /**
+ * 绘制线风格
+ *
+ * @param canvas
+ */
+ private void drawBorderLine(Canvas canvas) {
+ float y = getPaddingTop() + mBoxHeight;
+ canvas.drawLine(mRectF.left, y, mRectF.right, y, mPaint);
+ }
+
+ private Path getRoundRectPath(RectF rectF, boolean isFirst) {
+ mPath.reset();
+ if (isFirst) {
+ // 左上角
+ mRadiusFirstArray[0] = mBorderCornerRadius;
+ mRadiusFirstArray[1] = mBorderCornerRadius;
+ // 左下角
+ mRadiusFirstArray[6] = mBorderCornerRadius;
+ mRadiusFirstArray[7] = mBorderCornerRadius;
+ mPath.addRoundRect(rectF, mRadiusFirstArray, Path.Direction.CW);
+ } else {
+ // 右上角
+ mRadiusLastArray[2] = mBorderCornerRadius;
+ mRadiusLastArray[3] = mBorderCornerRadius;
+ // 右下角
+ mRadiusLastArray[4] = mBorderCornerRadius;
+ mRadiusLastArray[5] = mBorderCornerRadius;
+ mPath.addRoundRect(rectF, mRadiusLastArray, Path.Direction.CW);
+ }
+ return mPath;
+ }
+
+
+ @Override
+ protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
+ super.onTextChanged(text, start, lengthBefore, lengthAfter);
+ mTextLength = text.length();
+ refreshView();
+ // 改变监听
+ if (mOnTextInputListener != null) {
+ mOnTextInputListener.onTextInputChanged(text.toString(), mTextLength);
+ if (mTextLength == mMaxLength) {
+ mOnTextInputListener.onTextInputCompleted(text.toString());
+ }
+ }
+ }
+
+ @Override
+ protected void onSelectionChanged(int selStart, int selEnd) {
+ super.onSelectionChanged(selStart, selEnd);
+ if (selStart == selEnd) {
+ setSelection(getText() == null ? 0 : getText().length());
+ }
+ }
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ // 焦点改变时刷新状态
+ refreshView();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ isDraw = false;
+ }
+
+ public int getBorderColor() {
+ return mBorderColor;
+ }
+
+ public int getInputBorderColor() {
+ return mInputBorderColor;
+ }
+
+ public int getFocusBorderColor() {
+ return mFocusBorderColor;
+ }
+
+ public int getBoxBackgroundColor() {
+ return mBoxBackgroundColor;
+ }
+
+ public float getBorderCornerRadius() {
+ return mBorderCornerRadius;
+ }
+
+ public float getBorderSpacing() {
+ return mBorderSpacing;
+ }
+
+ @BorderStyle
+ public int getBorderStyle() {
+ return mBorderStyle;
+ }
+
+
+ public void setBorderColor(int borderColor) {
+ this.mBorderColor = borderColor;
+ refreshView();
+ }
+
+ public void setInputBorderColor(int inputBorderColor) {
+ this.mInputBorderColor = inputBorderColor;
+ refreshView();
+ }
+
+ public void setFocusBorderColor(int focusBorderColor) {
+ this.mFocusBorderColor = focusBorderColor;
+ refreshView();
+ }
+
+ public void setBoxBackgroundColor(int boxBackgroundColor) {
+ this.mBoxBackgroundColor = boxBackgroundColor;
+ refreshView();
+ }
+
+ public void setBorderCornerRadius(float borderCornerRadius) {
+ this.mBorderCornerRadius = borderCornerRadius;
+ refreshView();
+ }
+
+ public void setBorderSpacing(float borderSpacing) {
+ this.mBorderSpacing = borderSpacing;
+ refreshView();
+ }
+
+ public void setBorderStyle(@TextStyle int borderStyle) {
+ this.mBorderStyle = borderStyle;
+ refreshView();
+ }
+
+ @TextStyle
+ public int getTextStyle() {
+ return mTextStyle;
+ }
+
+ public void setTextStyle(@TextStyle int textStyle) {
+ this.mTextStyle = textStyle;
+ refreshView();
+ }
+
+ public String getCipherMask() {
+ return mCipherMask;
+ }
+
+ /**
+ * 是否粗体
+ *
+ * @param fakeBoldText
+ */
+ public void setFakeBoldText(boolean fakeBoldText) {
+ isFakeBoldText = fakeBoldText;
+ refreshView();
+ }
+
+ /**
+ * 设置密文掩码 不设置时,默认为{@link #DEFAULT_CIPHER_MASK}
+ *
+ * @param cipherMask
+ */
+ public void setCipherMask(String cipherMask) {
+ this.mCipherMask = cipherMask;
+ refreshView();
+ }
+
+ /**
+ * 刷新视图
+ */
+ private void refreshView() {
+ if (isDraw) {
+ invalidate();
+ }
+ }
+
+ /**
+ * 设置文本输入监听
+ *
+ * @param onTextInputListener
+ */
+ public void setOnTextInputListener(OnTextInputListener onTextInputListener) {
+ this.mOnTextInputListener = onTextInputListener;
+ }
+
+ public static abstract class OnSimpleTextInputListener implements OnTextInputListener {
+
+ @Override
+ public void onTextInputChanged(String text, int length) {
+
+ }
+
+ }
+
+ /**
+ * 文本输入监听
+ */
+ public interface OnTextInputListener {
+ /**
+ * Text改变监听
+ *
+ * @param text
+ * @param length
+ */
+ void onTextInputChanged(@NonNull String text, int length);
+
+ /**
+ * Text输入完成
+ *
+ * @param text
+ */
+ void onTextInputCompleted(@NonNull String text);
+ }
+}
diff --git a/split-edit-text/src/main/res/values/attrs.xml b/splitedittext/src/main/res/values/attrs.xml
similarity index 97%
rename from split-edit-text/src/main/res/values/attrs.xml
rename to splitedittext/src/main/res/values/attrs.xml
index fe92002..af4d0cc 100644
--- a/split-edit-text/src/main/res/values/attrs.xml
+++ b/splitedittext/src/main/res/values/attrs.xml
@@ -1,25 +1,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/split-edit-text/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java b/splitedittext/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java
similarity index 96%
rename from split-edit-text/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java
rename to splitedittext/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java
index f6bc726..bf83c22 100644
--- a/split-edit-text/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java
+++ b/splitedittext/src/test/java/com/king/view/splitedittext/ExampleUnitTest.java
@@ -1,17 +1,17 @@
-package com.king.view.splitedittext;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see Testing documentation
- */
-public class ExampleUnitTest {
- @Test
- public void addition_isCorrect() {
- assertEquals(4, 2 + 2);
- }
+package com.king.view.splitedittext;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
}
\ No newline at end of file
diff --git a/versions.gradle b/versions.gradle
index 1d1d448..7697be4 100644
--- a/versions.gradle
+++ b/versions.gradle
@@ -1,22 +1,24 @@
//App
def app_version = [:]
-app_version.versionCode = 1
-app_version.versionName = "1.0.0"
+app_version.versionCode = 2
+app_version.versionName = "1.1.0"
ext.app_version = app_version
//build version
def build_versions = [:]
build_versions.minSdk = 16
-build_versions.targetSdk = 29
-build_versions.compileSdk = 29
-build_versions.buildTools = "29.0.3"
+build_versions.targetSdk = 30
+build_versions.compileSdk = 30
+build_versions.buildTools = "30.0.3"
ext.build_versions = build_versions
//App dependencies
def versions = [:]
+
+versions.mavenPublish = '0.18.0'
versions.bintrayRelease = "1.0.0"
versions.dokka = "1.4.20"
-versions.gradle = "3.6.2"
+versions.gradle = "4.2.2"
versions.kotlin = "1.4.21"
versions.appcompat = "1.2.0"
versions.coreKtx = "1.3.2"