├── .gitignore ├── README.md ├── README_zh.md ├── app ├── .gitignore ├── apk │ └── NumberCodeViewDemo.apk ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── linkaipeng │ │ └── numbercodeview │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── linkaipeng │ │ │ └── example │ │ │ ├── MainActivity.java │ │ │ └── NormalNumberCodeViewExampleActivity.java │ └── res │ │ ├── drawable │ │ ├── bg_button.xml │ │ ├── bg_button_n.xml │ │ └── bg_button_p.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── activity_normal_example.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ ├── ic_avatar.png │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── linkaipeng │ └── numbercodeview │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── numbercodeview-lib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── lkp │ │ └── numbercodeview │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── lkp │ │ │ └── numbercodeview │ │ │ ├── BaseNumberCodeView.java │ │ │ ├── ExpandGridView.java │ │ │ ├── bottomsheet │ │ │ ├── BottomSheetNumberCodeView.java │ │ │ └── BottomSheetNumberCodeViewActivity.java │ │ │ └── normal │ │ │ └── NumberCodeView.java │ └── res │ │ ├── anim │ │ ├── push_bottom_to_top.xml │ │ └── push_top_to_bottom.xml │ │ ├── drawable │ │ ├── bg_gray_back_button.xml │ │ ├── bg_numbers_layout.xml │ │ ├── item_border.xml │ │ ├── item_border_selected.xml │ │ └── list_selector.xml │ │ ├── layout │ │ ├── activity_bottom_sheet_number_code_view.xml │ │ ├── item_view_input_group_code.xml │ │ ├── view_bottom_sheet_input_code.xml │ │ ├── view_input_group_code.xml │ │ ├── view_number_edit.xml │ │ └── view_number_input_layout.xml │ │ ├── mipmap-xhdpi │ │ ├── ic_back_gray_n.png │ │ ├── ic_back_gray_p.png │ │ └── ic_input_code_delete.png │ │ └── values │ │ ├── attr.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── lkp │ └── numbercodeview │ └── ExampleUnitTest.java ├── screenshots ├── screenshot01.png ├── screenshot02.png ├── screenshot03.png ├── screenshot04.png └── screenshot05.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | /*.iml 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### [中文文档](https://github.com/linkaipeng/NumberCodeView/blob/master/README_zh.md) 2 | 3 | # NumberCodeView 4 | A number input view which like input password in alipay or wechat pay. 5 | 6 | # Usage 7 | 8 | ### Normal Style 9 | 10 | Normal, start to an activity which include the NumberCodeView. 11 | 12 | Add to your '.xml' file. 13 | 14 | ``` 15 | 21 | ``` 22 | 23 | Use the `numbercodeview:isPassword` attribute. 24 | 25 | ### BottomSheet Style 26 | 27 | Bottom sheet style, an activity with dialog style. Popup from bottom of screen. 28 | 29 | Call Bottom sheet style NumberCodeView with a single line code. Like this: 30 | 31 | ``` 32 | BottomSheetNumberCodeViewActivity.show(this, mIsPassword); 33 | ``` 34 | 35 | ### `isPassword` Attribute 36 | 37 | If it is password, the number will be replaced with symbol ● 38 | 39 | 40 | # Screenshots 41 | 42 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot01.png) 43 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot02.png) 44 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot03.png) 45 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot04.png) 46 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot05.png) 47 | 48 | ## LICENSE 49 | 50 | ``` 51 | Copyright 2015 linkaipeng 52 | 53 | Licensed under the Apache License, Version 2.0 (the "License"); 54 | you may not use this file except in compliance with the License. 55 | You may obtain a copy of the License at 56 | 57 | 58 | 59 | Unless required by applicable law or agreed to in writing, software 60 | distributed under the License is distributed on an "AS IS" BASIS, 61 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 62 | See the License for the specific language governing permissions and 63 | limitations under the License. 64 | 65 | ``` 66 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # NumberCodeView 2 | 一个类似微信支付和支付宝支付的时候输入密码面板的控件。 3 | 4 | # 使用方式 5 | 6 | ### 普通样式 7 | 8 | 正常情况下,你可以把控件的声明写到你的 '.xml' 文件里面。 9 | 10 | ``` 11 | 17 | ``` 18 | 19 | 可以使用 `numbercodeview:isPassword` 这个属性去控制是否是密码,密码的话会用黑点替代数字。 20 | 21 | ### 底部面板样式 22 | 23 | 使用底部样式,那么久可以从界面的底部弹出来。 24 | 25 | 可以通过以下代码进行调用: 26 | 27 | ``` 28 | BottomSheetNumberCodeViewActivity.show(this, mIsPassword); 29 | ``` 30 | 31 | ### `isPassword` 属性 32 | 33 | 如果是密码,那么输入框里面的数字将会用 ● 取代。 34 | 35 | 36 | # 截屏 37 | 38 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot01.png) 39 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot02.png) 40 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot03.png) 41 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot04.png) 42 | ![](https://github.com/linkaipeng/NumberCodeView/raw/master/screenshots/screenshot05.png) 43 | 44 | ## LICENSE 45 | 46 | ``` 47 | Copyright 2015 linkaipeng 48 | 49 | Licensed under the Apache License, Version 2.0 (the "License"); 50 | you may not use this file except in compliance with the License. 51 | You may obtain a copy of the License at 52 | 53 | 54 | 55 | Unless required by applicable law or agreed to in writing, software 56 | distributed under the License is distributed on an "AS IS" BASIS, 57 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 58 | See the License for the specific language governing permissions and 59 | limitations under the License. 60 | 61 | ``` 62 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /*.iml 3 | -------------------------------------------------------------------------------- /app/apk/NumberCodeViewDemo.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkaipeng/NumberCodeView/30148ca4d497615d70bee0b244409ab67424be7c/app/apk/NumberCodeViewDemo.apk -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.linkaipeng.numbercodeview" 9 | minSdkVersion 15 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:23.0.1' 26 | compile 'com.android.support:design:23.0.1' 27 | compile project(':numbercodeview-lib') 28 | } 29 | -------------------------------------------------------------------------------- /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:\Program Files (x86)\android\android-sdk/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/linkaipeng/numbercodeview/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.linkaipeng.numbercodeview; 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 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/linkaipeng/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.linkaipeng.example; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.CheckBox; 11 | import android.widget.CompoundButton; 12 | import android.widget.TextView; 13 | import android.widget.Toast; 14 | 15 | import com.linkaipeng.numbercodeview.R; 16 | import com.lkp.numbercodeview.bottomsheet.BottomSheetNumberCodeViewActivity; 17 | 18 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 19 | 20 | private Button mShowBottomButton; 21 | private Button mShowNormalButton; 22 | 23 | private CheckBox mIsPasswordCheckBox; 24 | private TextView mIsPasswordTextView; 25 | 26 | private boolean mIsPassword = true; 27 | 28 | @Override 29 | protected void onCreate(@Nullable Bundle savedInstanceState) { 30 | super.onCreate(savedInstanceState); 31 | setContentView(R.layout.activity_main); 32 | initView(); 33 | } 34 | 35 | private void initView(){ 36 | getSupportActionBar(); 37 | mIsPasswordCheckBox = (CheckBox) findViewById(R.id.is_password_box); 38 | mIsPasswordTextView = (TextView) findViewById(R.id.is_password_textView); 39 | mShowBottomButton = (Button) findViewById(R.id.show_bottom_button); 40 | mShowNormalButton = (Button) findViewById(R.id.normal_button); 41 | mShowBottomButton.setOnClickListener(this); 42 | mShowNormalButton.setOnClickListener(this); 43 | mIsPasswordCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 44 | @Override 45 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 46 | mIsPassword = isChecked; 47 | if (isChecked) { 48 | mIsPasswordTextView.setText("Now it is password."); 49 | } else { 50 | mIsPasswordTextView.setText("Now it is not password."); 51 | } 52 | } 53 | }); 54 | } 55 | 56 | @Override 57 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 58 | if (resultCode == RESULT_OK && requestCode == 59 | BottomSheetNumberCodeViewActivity.REQUEST_CODE_SHOW_BOTTOM_NUMBER_VIEW) { 60 | String code = data.getStringExtra(BottomSheetNumberCodeViewActivity.KEY_DATA_NUMBER); 61 | Toast.makeText(this, code, Toast.LENGTH_SHORT).show(); 62 | } 63 | } 64 | 65 | @Override 66 | public void onClick(View v) { 67 | int viewId = v.getId(); 68 | switch (viewId) { 69 | case R.id.show_bottom_button: 70 | BottomSheetNumberCodeViewActivity.show(this, mIsPassword); 71 | break; 72 | 73 | case R.id.normal_button: 74 | NormalNumberCodeViewExampleActivity.start(this, mIsPassword); 75 | break; 76 | default: 77 | break; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/linkaipeng/example/NormalNumberCodeViewExampleActivity.java: -------------------------------------------------------------------------------- 1 | package com.linkaipeng.example; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.MenuItem; 9 | import android.widget.Toast; 10 | 11 | import com.linkaipeng.numbercodeview.R; 12 | import com.lkp.numbercodeview.normal.NumberCodeView; 13 | 14 | /** 15 | * Created by linkaipeng on 16/8/2. 16 | */ 17 | public class NormalNumberCodeViewExampleActivity extends AppCompatActivity { 18 | 19 | private static final String KEY_DATA_IS_PASSWORD = "KeyDataIsPassword"; 20 | 21 | public static void start(Context context, boolean isPassword) { 22 | Intent starter = new Intent(context, NormalNumberCodeViewExampleActivity.class); 23 | starter.putExtra(KEY_DATA_IS_PASSWORD, isPassword); 24 | context.startActivity(starter); 25 | } 26 | 27 | private NumberCodeView mNumberCodeView; 28 | 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_normal_example); 33 | initView(); 34 | } 35 | 36 | private void initView(){ 37 | ActionBar actionBar = getSupportActionBar(); 38 | actionBar.setTitle("NormalNumberCodeView"); 39 | actionBar.setDisplayHomeAsUpEnabled(true); 40 | 41 | boolean isPassword = getIntent().getBooleanExtra(KEY_DATA_IS_PASSWORD, true); 42 | mNumberCodeView = (NumberCodeView) findViewById(R.id.numberCodeView); 43 | mNumberCodeView.setIsPassword(isPassword); 44 | mNumberCodeView.setNumberCodeCallback(new NumberCodeView.OnInputNumberCodeCallback() { 45 | @Override 46 | public void onResult(String code) { 47 | Toast.makeText(NormalNumberCodeViewExampleActivity.this, code, Toast.LENGTH_LONG).show(); 48 | } 49 | }); 50 | } 51 | 52 | @Override 53 | public boolean onOptionsItemSelected(MenuItem item) { 54 | if (item.getItemId() == android.R.id.home) { 55 | finish(); 56 | return true; 57 | } 58 | return super.onOptionsItemSelected(item); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button_n.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_button_p.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 23 | 24 | 29 | 30 | 38 | 39 | 40 | 41 | 42 | 43 | 52 | 53 |