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"