├── .gitignore ├── .travis.yml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── xw │ │ └── sample │ │ └── fillblankviewdemo │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── xw │ │ └── sample │ │ └── fillblankviewdemo │ │ ├── MainActivity.java │ │ ├── PasswordDemoActivity.java │ │ └── TextDemoActivity.java │ └── res │ ├── layout │ ├── activity_main.xml │ ├── activity_password_demo.xml │ └── activity_text_demo.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── fillblankview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── xw │ │ └── repo │ │ └── fillblankview │ │ └── FillBlankView.java │ └── res │ └── values │ ├── attrs.xml │ └── strings.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── demo2.png └── demo3.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # [Android] ======================== 2 | # Built application files 3 | *.apk 4 | *.ap_ 5 | 6 | # Files for the Dalvik VM 7 | *.dex 8 | 9 | # Java class files 10 | *.class 11 | 12 | # Generated files 13 | bin/ 14 | gen/ 15 | 16 | # Gradle files 17 | .gradle/ 18 | build/ 19 | 20 | # Local configuration file (sdk path, etc) 21 | local.properties 22 | 23 | # Proguard folder generated by Eclipse 24 | proguard/ 25 | 26 | # Log Files 27 | *.log 28 | 29 | 30 | ## Directory-based project format: 31 | .idea/ 32 | 33 | ## File-based project format: 34 | *.ipr 35 | *.iws 36 | 37 | ## Plugin-specific files: 38 | 39 | # IntelliJ 40 | out/ 41 | 42 | # mpeltonen/sbt-idea plugin 43 | .idea_modules/ 44 | 45 | # JIRA plugin 46 | atlassian-ide-plugin.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | 51 | 52 | # [Maven] ======================== 53 | target/ 54 | pom.xml.tag 55 | pom.xml.releaseBackup 56 | pom.xml.versionsBackup 57 | pom.xml.next 58 | release.properties 59 | 60 | 61 | # [Gradle-Android] ======================== 62 | 63 | # Ignore Gradle GUI config 64 | gradle-app.setting 65 | 66 | # Gradle Signing 67 | signing.properties 68 | trestle.keystore 69 | 70 | # Mobile Tools for Java (J2ME) 71 | .mtj.tmp/ 72 | 73 | # Package Files # 74 | *.war 75 | *.ear 76 | 77 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 78 | hs_err_pid* 79 | 80 | # Misc 81 | /.idea/workspace.xml 82 | .DS_Store 83 | /captures 84 | **/*.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | 3 | jdk: oraclejdk7 4 | 5 | android: 6 | components: 7 | # Uncomment the lines below if you want to 8 | # use the latest revision of Android SDK Tools 9 | # - platform-tools 10 | # - tools 11 | 12 | # The BuildTools version used by your project 13 | - build-tools-23.0.2 14 | 15 | # The SDK version used to compile your project 16 | - android-23 17 | 18 | # Additional components 19 | - extra-android-support 20 | - extra-google-google_play_services 21 | - extra-google-m2repository 22 | - extra-android-m2repository 23 | # - addon-google_apis-google-19 24 | # - add-on 25 | # - extra 26 | 27 | # Specify at least one system image, 28 | # if you need to run emulator(s) during your tests 29 | - sys-img-armeabi-v7a-android-21 30 | # - sys-img-x86-android-17 31 | 32 | licenses: 33 | - 'android-sdk-license-.+' 34 | 35 | env: 36 | global: 37 | # install timeout in minutes (2 minutes by default) 38 | - ADB_INSTALL_TIMEOUT=8 39 | 40 | # Emulator Management: Create, Start and Wait 41 | before_script: 42 | - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a 43 | - emulator -avd test -no-skin -no-audio -no-window & 44 | - android-wait-for-emulator 45 | - adb shell input keyevent 82 & 46 | 47 | before_install: 48 | - chmod +x gradlew 49 | 50 | script: 51 | - ./gradlew assembleDebug 52 | 53 | notifications: 54 | email: false 55 | 56 | sudo: false -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Download](https://api.bintray.com/packages/woxingxiao/maven/fillblankview/images/download.svg)](https://bintray.com/woxingxiao/maven/fillblankview/_latestVersion) 2 | 3 | ### 仿手机支付宝支付数字密码输入验证,文字信息输入验证 4 | 5 | ### Gradle 6 | ```groovy 7 | dependencies{ 8 | compile 'com.xw.repo:fillblankview:2.1@aar' 9 | } 10 | ``` 11 | 12 | ### Screenshot 13 | 14 | >**password inputs** 15 | 16 | ![demo2](https://github.com/woxingxiao/FillBlankViewDemo/blob/master/screenshots/demo2.png) 17 | 18 | >**text inputs** 19 | 20 | ![demo3](https://github.com/woxingxiao/FillBlankViewDemo/blob/master/screenshots/demo3.png) 21 | 22 | ### XML 23 | ```xml 24 | 40 | ``` 41 | ```xml 42 | 47 | 48 | 56 | ``` 57 | Check the demo for more usage. 58 | 59 | ### Attributes 60 | attr | format 61 | -------- | --- 62 | blankNum|integer 63 | blankSpace|dimension 64 | blankSolidColor|color 65 | blankStrokeColor|color 66 | blankStrokeWidth|dimension 67 | blankCornerRadius|dimension 68 | blankFocusedStrokeColor|color 69 | isPasswordMode|boolean 70 | dotSize|dimension 71 | dotColor|color 72 | textMatchedColor|color 73 | textNotMatchedColor|color 74 | 75 | ### License 76 | ``` 77 | The MIT License (MIT) 78 | 79 | Copyright (c) 2017 woxingxiao 80 | 81 | Permission is hereby granted, free of charge, to any person obtaining a copy 82 | of this software and associated documentation files (the "Software"), to deal 83 | in the Software without restriction, including without limitation the rights 84 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 85 | copies of the Software, and to permit persons to whom the Software is 86 | furnished to do so, subject to the following conditions: 87 | 88 | The above copyright notice and this permission notice shall be included in all 89 | copies or substantial portions of the Software. 90 | 91 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 92 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 93 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 94 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 95 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 96 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 97 | SOFTWARE. 98 | ``` 99 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 27 5 | buildToolsVersion "27.0.3" 6 | 7 | defaultConfig { 8 | applicationId "com.xw.sample.fillblankviewdemo" 9 | minSdkVersion 14 10 | targetSdkVersion 27 11 | versionCode 5 12 | versionName "2.1" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: 'libs', include: ['*.jar']) 24 | implementation 'com.android.support:appcompat-v7:27.1.1' 25 | implementation 'com.android.support:cardview-v7:27.1.1' 26 | implementation project(':fillblankview') 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\android-sdk-windows/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xw/sample/fillblankviewdemo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.repo.xw.fillblankviewdemo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/xw/sample/fillblankviewdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.xw.sample.fillblankviewdemo; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | public class MainActivity extends AppCompatActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_main); 14 | 15 | findViewById(R.id.show_password_demo).setOnClickListener(new View.OnClickListener() { 16 | @Override 17 | public void onClick(View v) { 18 | startActivity(new Intent(MainActivity.this, PasswordDemoActivity.class)); 19 | } 20 | }); 21 | 22 | findViewById(R.id.show_text_demo).setOnClickListener(new View.OnClickListener() { 23 | @Override 24 | public void onClick(View v) { 25 | startActivity(new Intent(MainActivity.this, TextDemoActivity.class)); 26 | } 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/xw/sample/fillblankviewdemo/PasswordDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.xw.sample.fillblankviewdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.Button; 7 | 8 | import com.xw.repo.fillblankview.FillBlankView; 9 | 10 | public class PasswordDemoActivity extends AppCompatActivity implements View.OnClickListener { 11 | 12 | private FillBlankView mFillBlankView1, mFillBlankView2, mFillBlankView3, mFillBlankView4; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_password_demo); 18 | 19 | mFillBlankView1 = (FillBlankView) findViewById(R.id.fill_blank_view1); 20 | mFillBlankView2 = (FillBlankView) findViewById(R.id.fill_blank_view2); 21 | mFillBlankView3 = (FillBlankView) findViewById(R.id.fill_blank_view3); 22 | mFillBlankView4 = (FillBlankView) findViewById(R.id.fill_blank_view4); 23 | Button mButton1 = (Button) findViewById(R.id.button1); 24 | Button mButton2 = (Button) findViewById(R.id.button2); 25 | Button mButton3 = (Button) findViewById(R.id.button3); 26 | Button mButton4 = (Button) findViewById(R.id.button4); 27 | Button mButton5 = (Button) findViewById(R.id.button5); 28 | Button mButton6 = (Button) findViewById(R.id.button6); 29 | Button mButton7 = (Button) findViewById(R.id.button7); 30 | Button mButton8 = (Button) findViewById(R.id.button8); 31 | Button mButton9 = (Button) findViewById(R.id.button9); 32 | Button mButton11 = (Button) findViewById(R.id.button11); 33 | Button mButton12 = (Button) findViewById(R.id.button12); 34 | 35 | mButton1.setOnClickListener(this); 36 | mButton2.setOnClickListener(this); 37 | mButton3.setOnClickListener(this); 38 | mButton4.setOnClickListener(this); 39 | mButton5.setOnClickListener(this); 40 | mButton6.setOnClickListener(this); 41 | mButton7.setOnClickListener(this); 42 | mButton8.setOnClickListener(this); 43 | mButton9.setOnClickListener(this); 44 | mButton11.setOnClickListener(this); 45 | mButton12.setOnClickListener(this); 46 | } 47 | 48 | @Override 49 | public void onClick(View v) { 50 | switch (v.getId()) { 51 | case R.id.button1: 52 | mFillBlankView1.getText().append("1"); 53 | mFillBlankView2.getText().append("1"); 54 | mFillBlankView3.getText().append("1"); 55 | mFillBlankView4.getText().append("1"); 56 | break; 57 | case R.id.button2: 58 | mFillBlankView1.getText().append("2"); 59 | mFillBlankView2.getText().append("2"); 60 | mFillBlankView3.getText().append("2"); 61 | mFillBlankView4.getText().append("2"); 62 | break; 63 | case R.id.button3: 64 | mFillBlankView1.getText().append("3"); 65 | mFillBlankView2.getText().append("3"); 66 | mFillBlankView3.getText().append("3"); 67 | mFillBlankView4.getText().append("3"); 68 | break; 69 | case R.id.button4: 70 | mFillBlankView1.getText().append("4"); 71 | mFillBlankView2.getText().append("4"); 72 | mFillBlankView3.getText().append("4"); 73 | mFillBlankView4.getText().append("4"); 74 | break; 75 | case R.id.button5: 76 | mFillBlankView1.getText().append("5"); 77 | mFillBlankView2.getText().append("5"); 78 | mFillBlankView3.getText().append("5"); 79 | mFillBlankView4.getText().append("5"); 80 | break; 81 | case R.id.button6: 82 | mFillBlankView1.getText().append("6"); 83 | mFillBlankView2.getText().append("6"); 84 | mFillBlankView3.getText().append("6"); 85 | mFillBlankView4.getText().append("6"); 86 | break; 87 | case R.id.button7: 88 | mFillBlankView1.getText().append("7"); 89 | mFillBlankView2.getText().append("7"); 90 | mFillBlankView3.getText().append("7"); 91 | mFillBlankView4.getText().append("7"); 92 | break; 93 | case R.id.button8: 94 | mFillBlankView1.getText().append("8"); 95 | mFillBlankView2.getText().append("8"); 96 | mFillBlankView3.getText().append("8"); 97 | mFillBlankView4.getText().append("8"); 98 | break; 99 | case R.id.button9: 100 | mFillBlankView1.getText().append("9"); 101 | mFillBlankView2.getText().append("9"); 102 | mFillBlankView3.getText().append("9"); 103 | mFillBlankView4.getText().append("9"); 104 | break; 105 | case R.id.button11: 106 | mFillBlankView1.getText().append("0"); 107 | mFillBlankView2.getText().append("0"); 108 | mFillBlankView3.getText().append("0"); 109 | mFillBlankView4.getText().append("0"); 110 | break; 111 | case R.id.button12: 112 | if (mFillBlankView1.getText().length() * mFillBlankView2.getText().length() * 113 | mFillBlankView3.getText().length() * mFillBlankView4.getText().length() == 0) 114 | return; 115 | mFillBlankView1.getText().delete(mFillBlankView1.getText().length() - 1, 116 | mFillBlankView1.getText().length()); 117 | mFillBlankView2.getText().delete(mFillBlankView2.getText().length() - 1, 118 | mFillBlankView2.getText().length()); 119 | mFillBlankView3.getText().delete(mFillBlankView3.getText().length() - 1, 120 | mFillBlankView3.getText().length()); 121 | mFillBlankView4.getText().delete(mFillBlankView4.getText().length() - 1, 122 | mFillBlankView4.getText().length()); 123 | break; 124 | } 125 | } 126 | 127 | } -------------------------------------------------------------------------------- /app/src/main/java/com/xw/sample/fillblankviewdemo/TextDemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.xw.sample.fillblankviewdemo; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.view.inputmethod.InputMethodManager; 8 | import android.widget.EditText; 9 | import android.widget.TextView; 10 | 11 | import com.xw.repo.fillblankview.FillBlankView; 12 | 13 | public class TextDemoActivity extends AppCompatActivity implements View.OnClickListener { 14 | 15 | private FillBlankView mFillBlankView1, mFillBlankView2, mFillBlankView3, mFillBlankView4; 16 | private TextView matchedText1, matchedText2, matchedText3, matchedText4; 17 | 18 | @Override 19 | protected void onCreate(Bundle savedInstanceState) { 20 | super.onCreate(savedInstanceState); 21 | setContentView(R.layout.activity_text_demo); 22 | 23 | mFillBlankView1 = (FillBlankView) findViewById(R.id.fill_blank_view1); 24 | mFillBlankView2 = (FillBlankView) findViewById(R.id.fill_blank_view2); 25 | mFillBlankView3 = (FillBlankView) findViewById(R.id.fill_blank_view3); 26 | mFillBlankView4 = (FillBlankView) findViewById(R.id.fill_blank_view4); 27 | matchedText1 = (TextView) findViewById(R.id.matched_text1); 28 | matchedText2 = (TextView) findViewById(R.id.matched_text2); 29 | matchedText3 = (TextView) findViewById(R.id.matched_text3); 30 | matchedText4 = (TextView) findViewById(R.id.matched_text4); 31 | 32 | mFillBlankView1.setOnClickListener(this); 33 | mFillBlankView2.setOnClickListener(this); 34 | mFillBlankView3.setOnClickListener(this); 35 | mFillBlankView4.setOnClickListener(this); 36 | 37 | mFillBlankView1.setOriginalText("Android"); 38 | mFillBlankView2.setOriginalText("Hello, world", 7, 0); 39 | mFillBlankView3.setOriginalText("13800000000", 3, 4); 40 | mFillBlankView4.setOriginalText("FillBlank", 0, 5); 41 | 42 | mFillBlankView1.setOnTextMatchedListener(new FillBlankView.OnTextMatchedListener() { 43 | @Override 44 | public void matched(boolean isMatched, String originalText) { 45 | if (isMatched) { 46 | matchedText1.setText("matched !"); 47 | } else { 48 | matchedText1.setText(""); 49 | } 50 | } 51 | }); 52 | mFillBlankView2.setOnTextMatchedListener(new FillBlankView.OnTextMatchedListener() { 53 | @Override 54 | public void matched(boolean isMatched, String originalText) { 55 | if (isMatched) { 56 | matchedText2.setText("matched !"); 57 | } else { 58 | matchedText2.setText(""); 59 | } 60 | } 61 | }); 62 | mFillBlankView3.setOnTextMatchedListener(new FillBlankView.OnTextMatchedListener() { 63 | @Override 64 | public void matched(boolean isMatched, String originalText) { 65 | if (isMatched) { 66 | matchedText3.setText("matched !"); 67 | matchedText3.setTextColor(getResources().getColor(R.color.green)); 68 | } else if (mFillBlankView3.getFilledText().length() == "13800000000".length()) { 69 | matchedText3.setText("not match !"); 70 | matchedText3.setTextColor(getResources().getColor(R.color.colorAccent)); 71 | } else { 72 | matchedText3.setText(""); 73 | } 74 | } 75 | }); 76 | mFillBlankView4.setOnTextMatchedListener(new FillBlankView.OnTextMatchedListener() { 77 | @Override 78 | public void matched(boolean isMatched, String originalText) { 79 | if (isMatched) { 80 | matchedText4.setText("matched !"); 81 | } else { 82 | matchedText4.setText(""); 83 | } 84 | } 85 | }); 86 | } 87 | 88 | @Override 89 | public void onClick(View v) { 90 | switch (v.getId()) { 91 | case R.id.fill_blank_view1: 92 | showInputMethod(mFillBlankView1); 93 | break; 94 | case R.id.fill_blank_view2: 95 | showInputMethod(mFillBlankView2); 96 | break; 97 | case R.id.fill_blank_view3: 98 | showInputMethod(mFillBlankView3); 99 | break; 100 | case R.id.fill_blank_view4: 101 | showInputMethod(mFillBlankView4); 102 | break; 103 | } 104 | } 105 | 106 | private void showInputMethod(EditText editText) { 107 | editText.setFocusable(true); 108 | editText.setFocusableInTouchMode(true); 109 | editText.requestFocus(); 110 | 111 | InputMethodManager inputManager = (InputMethodManager) editText.getContext().getSystemService( 112 | Context.INPUT_METHOD_SERVICE); 113 | inputManager.showSoftInput(editText, 0); 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 16 | 17 | 26 | 27 | 28 | 34 | 35 | 44 | 45 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_password_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 21 | 22 | 31 | 32 | 43 | 44 | 60 | 61 | 67 | 68 |