├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── dictionaries │ └── alex.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── demo.apk ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── qwert2603 │ │ └── vector_integer_view_example │ │ └── MainActivity.java │ └── res │ ├── layout │ └── activity_main.xml │ └── values │ ├── dimens.xml │ ├── integer.xml │ └── styles.xml ├── art ├── device-2018-08-22-111118.png ├── device-2018-08-22-111149.png ├── device-2018-08-22-120319 (3).gif ├── device-2018-08-22-120319.gif └── device-2018-08-22-124411.gif ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── qwert2603 │ │ │ ├── rename_viv.kt_xt │ │ │ └── vector_integer_view │ │ │ ├── DigitAdapter.java │ │ │ ├── DigitItemAnimator.java │ │ │ ├── Utils.java │ │ │ └── VectorIntegerView.java │ └── res │ │ ├── drawable │ │ ├── viv_asl_pathmorph_digits.xml │ │ ├── viv_avd_pathmorph_digits_0_to_1.xml │ │ ├── viv_avd_pathmorph_digits_0_to_2.xml │ │ ├── viv_avd_pathmorph_digits_0_to_3.xml │ │ ├── viv_avd_pathmorph_digits_0_to_4.xml │ │ ├── viv_avd_pathmorph_digits_0_to_5.xml │ │ ├── viv_avd_pathmorph_digits_0_to_6.xml │ │ ├── viv_avd_pathmorph_digits_0_to_7.xml │ │ ├── viv_avd_pathmorph_digits_0_to_8.xml │ │ ├── viv_avd_pathmorph_digits_0_to_9.xml │ │ ├── viv_avd_pathmorph_digits_0_to_m.xml │ │ ├── viv_avd_pathmorph_digits_0_to_n.xml │ │ ├── viv_avd_pathmorph_digits_1_to_0.xml │ │ ├── viv_avd_pathmorph_digits_1_to_2.xml │ │ ├── viv_avd_pathmorph_digits_1_to_3.xml │ │ ├── viv_avd_pathmorph_digits_1_to_4.xml │ │ ├── viv_avd_pathmorph_digits_1_to_5.xml │ │ ├── viv_avd_pathmorph_digits_1_to_6.xml │ │ ├── viv_avd_pathmorph_digits_1_to_7.xml │ │ ├── viv_avd_pathmorph_digits_1_to_8.xml │ │ ├── viv_avd_pathmorph_digits_1_to_9.xml │ │ ├── viv_avd_pathmorph_digits_1_to_m.xml │ │ ├── viv_avd_pathmorph_digits_1_to_n.xml │ │ ├── viv_avd_pathmorph_digits_2_to_0.xml │ │ ├── viv_avd_pathmorph_digits_2_to_1.xml │ │ ├── viv_avd_pathmorph_digits_2_to_3.xml │ │ ├── viv_avd_pathmorph_digits_2_to_4.xml │ │ ├── viv_avd_pathmorph_digits_2_to_5.xml │ │ ├── viv_avd_pathmorph_digits_2_to_6.xml │ │ ├── viv_avd_pathmorph_digits_2_to_7.xml │ │ ├── viv_avd_pathmorph_digits_2_to_8.xml │ │ ├── viv_avd_pathmorph_digits_2_to_9.xml │ │ ├── viv_avd_pathmorph_digits_2_to_m.xml │ │ ├── viv_avd_pathmorph_digits_2_to_n.xml │ │ ├── viv_avd_pathmorph_digits_3_to_0.xml │ │ ├── viv_avd_pathmorph_digits_3_to_1.xml │ │ ├── viv_avd_pathmorph_digits_3_to_2.xml │ │ ├── viv_avd_pathmorph_digits_3_to_4.xml │ │ ├── viv_avd_pathmorph_digits_3_to_5.xml │ │ ├── viv_avd_pathmorph_digits_3_to_6.xml │ │ ├── viv_avd_pathmorph_digits_3_to_7.xml │ │ ├── viv_avd_pathmorph_digits_3_to_8.xml │ │ ├── viv_avd_pathmorph_digits_3_to_9.xml │ │ ├── viv_avd_pathmorph_digits_3_to_m.xml │ │ ├── viv_avd_pathmorph_digits_3_to_n.xml │ │ ├── viv_avd_pathmorph_digits_4_to_0.xml │ │ ├── viv_avd_pathmorph_digits_4_to_1.xml │ │ ├── viv_avd_pathmorph_digits_4_to_2.xml │ │ ├── viv_avd_pathmorph_digits_4_to_3.xml │ │ ├── viv_avd_pathmorph_digits_4_to_5.xml │ │ ├── viv_avd_pathmorph_digits_4_to_6.xml │ │ ├── viv_avd_pathmorph_digits_4_to_7.xml │ │ ├── viv_avd_pathmorph_digits_4_to_8.xml │ │ ├── viv_avd_pathmorph_digits_4_to_9.xml │ │ ├── viv_avd_pathmorph_digits_4_to_m.xml │ │ ├── viv_avd_pathmorph_digits_4_to_n.xml │ │ ├── viv_avd_pathmorph_digits_5_to_0.xml │ │ ├── viv_avd_pathmorph_digits_5_to_1.xml │ │ ├── viv_avd_pathmorph_digits_5_to_2.xml │ │ ├── viv_avd_pathmorph_digits_5_to_3.xml │ │ ├── viv_avd_pathmorph_digits_5_to_4.xml │ │ ├── viv_avd_pathmorph_digits_5_to_6.xml │ │ ├── viv_avd_pathmorph_digits_5_to_7.xml │ │ ├── viv_avd_pathmorph_digits_5_to_8.xml │ │ ├── viv_avd_pathmorph_digits_5_to_9.xml │ │ ├── viv_avd_pathmorph_digits_5_to_m.xml │ │ ├── viv_avd_pathmorph_digits_5_to_n.xml │ │ ├── viv_avd_pathmorph_digits_6_to_0.xml │ │ ├── viv_avd_pathmorph_digits_6_to_1.xml │ │ ├── viv_avd_pathmorph_digits_6_to_2.xml │ │ ├── viv_avd_pathmorph_digits_6_to_3.xml │ │ ├── viv_avd_pathmorph_digits_6_to_4.xml │ │ ├── viv_avd_pathmorph_digits_6_to_5.xml │ │ ├── viv_avd_pathmorph_digits_6_to_7.xml │ │ ├── viv_avd_pathmorph_digits_6_to_8.xml │ │ ├── viv_avd_pathmorph_digits_6_to_9.xml │ │ ├── viv_avd_pathmorph_digits_6_to_m.xml │ │ ├── viv_avd_pathmorph_digits_6_to_n.xml │ │ ├── viv_avd_pathmorph_digits_7_to_0.xml │ │ ├── viv_avd_pathmorph_digits_7_to_1.xml │ │ ├── viv_avd_pathmorph_digits_7_to_2.xml │ │ ├── viv_avd_pathmorph_digits_7_to_3.xml │ │ ├── viv_avd_pathmorph_digits_7_to_4.xml │ │ ├── viv_avd_pathmorph_digits_7_to_5.xml │ │ ├── viv_avd_pathmorph_digits_7_to_6.xml │ │ ├── viv_avd_pathmorph_digits_7_to_8.xml │ │ ├── viv_avd_pathmorph_digits_7_to_9.xml │ │ ├── viv_avd_pathmorph_digits_7_to_m.xml │ │ ├── viv_avd_pathmorph_digits_7_to_n.xml │ │ ├── viv_avd_pathmorph_digits_8_to_0.xml │ │ ├── viv_avd_pathmorph_digits_8_to_1.xml │ │ ├── viv_avd_pathmorph_digits_8_to_2.xml │ │ ├── viv_avd_pathmorph_digits_8_to_3.xml │ │ ├── viv_avd_pathmorph_digits_8_to_4.xml │ │ ├── viv_avd_pathmorph_digits_8_to_5.xml │ │ ├── viv_avd_pathmorph_digits_8_to_6.xml │ │ ├── viv_avd_pathmorph_digits_8_to_7.xml │ │ ├── viv_avd_pathmorph_digits_8_to_9.xml │ │ ├── viv_avd_pathmorph_digits_8_to_m.xml │ │ ├── viv_avd_pathmorph_digits_8_to_n.xml │ │ ├── viv_avd_pathmorph_digits_9_to_0.xml │ │ ├── viv_avd_pathmorph_digits_9_to_1.xml │ │ ├── viv_avd_pathmorph_digits_9_to_2.xml │ │ ├── viv_avd_pathmorph_digits_9_to_3.xml │ │ ├── viv_avd_pathmorph_digits_9_to_4.xml │ │ ├── viv_avd_pathmorph_digits_9_to_5.xml │ │ ├── viv_avd_pathmorph_digits_9_to_6.xml │ │ ├── viv_avd_pathmorph_digits_9_to_7.xml │ │ ├── viv_avd_pathmorph_digits_9_to_8.xml │ │ ├── viv_avd_pathmorph_digits_9_to_m.xml │ │ ├── viv_avd_pathmorph_digits_9_to_n.xml │ │ ├── viv_avd_pathmorph_digits_m_to_0.xml │ │ ├── viv_avd_pathmorph_digits_m_to_1.xml │ │ ├── viv_avd_pathmorph_digits_m_to_2.xml │ │ ├── viv_avd_pathmorph_digits_m_to_3.xml │ │ ├── viv_avd_pathmorph_digits_m_to_4.xml │ │ ├── viv_avd_pathmorph_digits_m_to_5.xml │ │ ├── viv_avd_pathmorph_digits_m_to_6.xml │ │ ├── viv_avd_pathmorph_digits_m_to_7.xml │ │ ├── viv_avd_pathmorph_digits_m_to_8.xml │ │ ├── viv_avd_pathmorph_digits_m_to_9.xml │ │ ├── viv_avd_pathmorph_digits_m_to_n.xml │ │ ├── viv_avd_pathmorph_digits_n_to_0.xml │ │ ├── viv_avd_pathmorph_digits_n_to_1.xml │ │ ├── viv_avd_pathmorph_digits_n_to_2.xml │ │ ├── viv_avd_pathmorph_digits_n_to_3.xml │ │ ├── viv_avd_pathmorph_digits_n_to_4.xml │ │ ├── viv_avd_pathmorph_digits_n_to_5.xml │ │ ├── viv_avd_pathmorph_digits_n_to_6.xml │ │ ├── viv_avd_pathmorph_digits_n_to_7.xml │ │ ├── viv_avd_pathmorph_digits_n_to_8.xml │ │ ├── viv_avd_pathmorph_digits_n_to_9.xml │ │ ├── viv_avd_pathmorph_digits_n_to_m.xml │ │ ├── viv_vd_pathmorph_digits_eight.xml │ │ ├── viv_vd_pathmorph_digits_five.xml │ │ ├── viv_vd_pathmorph_digits_four.xml │ │ ├── viv_vd_pathmorph_digits_minus.xml │ │ ├── viv_vd_pathmorph_digits_nine.xml │ │ ├── viv_vd_pathmorph_digits_nth.xml │ │ ├── viv_vd_pathmorph_digits_one.xml │ │ ├── viv_vd_pathmorph_digits_seven.xml │ │ ├── viv_vd_pathmorph_digits_six.xml │ │ ├── viv_vd_pathmorph_digits_three.xml │ │ ├── viv_vd_pathmorph_digits_two.xml │ │ └── viv_vd_pathmorph_digits_zero.xml │ │ ├── layout │ │ ├── viv_item_digit.xml │ │ └── viv_vector_digit_view.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── integer.xml │ │ └── pathmorph_digits.xml │ └── test │ └── java │ └── com │ └── qwert2603 │ └── vector_integer_view │ └── UtilsTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/dictionaries/alex.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | qwert 5 | strokewidth 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 39 | 40 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VectorIntegerView 2 | 3 | [![](https://jitpack.io/v/qwert2603/VectorIntegerView.svg)](https://jitpack.io/#qwert2603/VectorIntegerView) 4 | 5 | `VectorIntegerView` (viv) is custom view to display integers on Android via great animations `minSdkVersion 21`. 6 | 7 | Paths for vector drawables drawables are taken [here](https://github.com/alexjlockwood/adp-delightful-details). 8 | 9 | ## [Showcase video](https://www.youtube.com/watch?v=tTQlPH3ROMw) 10 | 11 | ## [Demo APK](https://github.com/qwert2603/VectorIntegerView/blob/master/app/demo.apk) 12 | 13 | ## Article on [Habr.com](https://habr.com/post/420919/) 14 | 15 | ![art](https://github.com/qwert2603/VectorIntegerView/blob/master/art/device-2018-08-22-124411.gif) 16 | 17 | ## Customizing 18 | 19 | ### `VectorIntegerView` has following XML-attributes: 20 | 21 | * ***viv_vector_integer*** initial integer to show (0 by default). 22 | * ***viv_digit_color*** color of integer (black by default). 23 | 24 | ### Other properties may be configured by overriding resourses from library: 25 | #### (those will be applied to all `VectorIntegerView` in app, for example see [demo-app](https://github.com/qwert2603/VectorIntegerView/tree/master/app)) 26 | 27 | * ***@integer/viv_animation_duration*** defines duration of animation (400ms by default). 28 | * ***@dimen/viv_digit_size*** defines size of one digit (24dp by default). 29 | * ***@dimen/viv_digit_translateX*** applied to all avd-digits, to center them horizontally. 30 | * ***@dimen/viv_digit_translateY*** applied to all avd-digits, to center them vertically. 31 | * ***@dimen/viv_digit_strokewidth*** applied to all avd-digits. 32 | * ***@dimen/viv_digit_margin_horizontal*** applied to all digit-views (-3dp by default). This is needed to make horizontal spaces between digits smaller, because avd-digits are square. 33 | 34 | ## In code 35 | ### XML 36 | ```xml 37 | 44 | ``` 45 | 46 | ### Java / Kotlin 47 | Digit can be set also via code as `BigInteger` as well as digit color: 48 | ```java 49 | final VectorIntegerView vectorIntegerView = findViewById(R.id.vectorIntegerView); 50 | vectorIntegerView.setInteger( 51 | vectorIntegerView.getInteger().add(BigInteger.ONE), 52 | /* animated = */ true 53 | ); 54 | vectorIntegerView.setDigitColor(getColor(R.color.colorAccent)); 55 | ``` 56 | Also there is overloaded function that allows set integer as ```long```: 57 | ```java 58 | vectorIntegerView.setInteger(1918L, false); 59 | ``` 60 | For example see [demo-app](https://github.com/qwert2603/VectorIntegerView/tree/master/app). 61 | 62 | ## Under the hood 63 | 64 | [`VectorIntegerView`](https://github.com/qwert2603/VectorIntegerView/blob/master/library/src/main/java/com/qwert2603/vector_integer_view/VectorIntegerView.java) is implemented by `RecyclerView` and each digit is `ImageView` with `` drawable. 65 | 66 | Animation are controlled by custom `RecyclerView`'s item animator: [`DigitItemAnimator`](https://github.com/qwert2603/VectorIntegerView/blob/master/library/src/main/java/com/qwert2603/vector_integer_view/DigitItemAnimator.java). 67 | 68 | When animated each digit stays on it's own position. This is done via `DiffUtil` in [`DigitAdapter`](https://github.com/qwert2603/VectorIntegerView/blob/master/library/src/main/java/com/qwert2603/vector_integer_view/DigitAdapter.java). 69 | 70 | ## Download 71 | 72 | ``` 73 | allprojects { 74 | repositories { 75 | ... 76 | maven { url 'https://jitpack.io' } 77 | } 78 | } 79 | ``` 80 | 81 | ``` 82 | dependencies { 83 | implementation 'com.github.qwert2603:VectorIntegerView:x.y.z' 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.qwert2603.vector_integer_view_example" 7 | minSdkVersion 21 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | } 12 | buildTypes { 13 | release { 14 | shrinkResources true 15 | minifyEnabled true 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation project(path: ':library') 23 | // implementation 'com.github.qwert2603:VectorIntegerView:1.2.1' 24 | 25 | ext.support_version = '28.0.0' 26 | implementation "com.android.support:appcompat-v7:$support_version" 27 | implementation "com.android.support:design:$support_version" 28 | } 29 | -------------------------------------------------------------------------------- /app/demo.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qwert2603/VectorIntegerView/d7d87ae261ce7ffe88b00b3da5e4e8fbaa2e57a1/app/demo.apk -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/qwert2603/vector_integer_view_example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.qwert2603.vector_integer_view_example; 2 | 3 | import android.graphics.Color; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.CheckBox; 8 | import android.widget.EditText; 9 | 10 | import com.qwert2603.vector_integer_view.VectorIntegerView; 11 | 12 | import java.math.BigInteger; 13 | 14 | public class MainActivity extends AppCompatActivity { 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | 21 | final VectorIntegerView vectorIntegerView = findViewById(R.id.vectorIntegerView); 22 | final VectorIntegerView vectorIntegerView_2 = findViewById(R.id.vectorIntegerView_2); 23 | final CheckBox animateCheckBox = findViewById(R.id.animate_CheckBox); 24 | 25 | findViewById(R.id.plus_Button).setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | vectorIntegerView.setInteger( 29 | vectorIntegerView.getInteger().add(BigInteger.ONE), 30 | /* animated = */ animateCheckBox.isChecked() 31 | ); 32 | } 33 | }); 34 | findViewById(R.id.minus_Button).setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | vectorIntegerView.setInteger( 38 | vectorIntegerView.getInteger().subtract(BigInteger.ONE), 39 | animateCheckBox.isChecked() 40 | ); 41 | } 42 | }); 43 | findViewById(R.id.x17_Button).setOnClickListener(new View.OnClickListener() { 44 | @Override 45 | public void onClick(View v) { 46 | vectorIntegerView.setInteger( 47 | vectorIntegerView.getInteger().multiply(BigInteger.valueOf(17)), 48 | animateCheckBox.isChecked() 49 | ); 50 | } 51 | }); 52 | findViewById(R.id.setNumber_Button).setOnClickListener(new View.OnClickListener() { 53 | @Override 54 | public void onClick(View v) { 55 | long number = 0; 56 | try { 57 | number = Long.parseLong(((EditText) findViewById(R.id.number_EditText)).getText().toString()); 58 | } catch (NumberFormatException ignored) { 59 | } 60 | vectorIntegerView.setInteger(number, animateCheckBox.isChecked()); 61 | vectorIntegerView_2.setInteger(number, true); 62 | } 63 | }); 64 | findViewById(R.id.red_Button).setOnClickListener(new View.OnClickListener() { 65 | @Override 66 | public void onClick(View v) { 67 | vectorIntegerView.setDigitColor(Color.RED); 68 | } 69 | }); 70 | findViewById(R.id.green_Button).setOnClickListener(new View.OnClickListener() { 71 | @Override 72 | public void onClick(View v) { 73 | vectorIntegerView.setDigitColor(Color.GREEN); 74 | } 75 | }); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 21 | 22 | 29 | 30 | 31 | 32 | 41 | 42 | 47 | 48 |