├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── values │ │ │ │ ├── dimens-valueBar.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── styles.xml │ │ │ │ ├── dimens.xml │ │ │ │ └── colors.xml │ │ │ ├── values-land │ │ │ │ ├── dimens-valueSelector.xml │ │ │ │ └── dimens.xml │ │ │ ├── menu │ │ │ │ └── menu_main.xml │ │ │ ├── values-w820dp │ │ │ │ └── dimens.xml │ │ │ └── layout │ │ │ │ └── activity_main.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── intertech │ │ │ └── customviewsexample │ │ │ └── MainActivity.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── intertech │ │ └── customviewsexample │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── customviews ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── valueselect_minus.png │ │ │ │ ├── valueselect_plus.png │ │ │ │ ├── valueselect_pressed.png │ │ │ │ ├── valueselect_plus_pressed.png │ │ │ │ ├── valueselect_minus_state.xml │ │ │ │ └── valueselect_plus_state.xml │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── dimens-valueSelector.xml │ │ │ │ ├── dimens-valueBar.xml │ │ │ │ └── attrs.xml │ │ │ └── layout │ │ │ │ └── value_selector.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── intertech │ │ │ └── customviews │ │ │ ├── ValueSelector.java │ │ │ └── ValueBar.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── intertech │ │ └── customviews │ │ └── ApplicationTest.java ├── build.gradle └── proguard-rules.pro ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── runConfigurations.xml └── gradle.xml ├── .gitignore ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /customviews/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':customviews' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/customviews/src/main/res/drawable/valueselect_minus.png -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/customviews/src/main/res/drawable/valueselect_plus.png -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/customviews/src/main/res/drawable/valueselect_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/values/dimens-valueBar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_plus_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntertechInc/android-custom-view-tutorial/HEAD/customviews/src/main/res/drawable/valueselect_plus_pressed.png -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CustomViewsExample 3 | 4 | Hello world! 5 | Settings 6 | 7 | -------------------------------------------------------------------------------- /customviews/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Custom Views 3 | VALUE 4 | CURRENT VALUE 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /customviews/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Jul 16 16:51:48 CDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 7 | -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_minus_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /customviews/src/main/res/drawable/valueselect_plus_state.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values-land/dimens-valueSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15dp 5 | 0dp 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 16dp 4 | 5 | 100dp 6 | 0dp 7 | 8 | 40dp 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values-land/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 16dp 3 | 16dp 4 | 5 | 80dp 6 | 100dp 7 | 8 | 10dp 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 4 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /customviews/src/main/res/values/dimens-valueSelector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 30dp 4 | 14dp 5 | 14dp 6 | 25dp 7 | 10dp 8 | 9 | 10 | -------------------------------------------------------------------------------- /customviews/src/androidTest/java/com/intertech/customviews/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.intertech.customviews; 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/androidTest/java/com/intertech/customviewsexample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.intertech.customviewsexample; 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/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #FFFF00 5 | #FF0000 6 | #D6D6D6 7 | #E5E5E5 8 | #808080 9 | #ff424242 10 | #008000 11 | #0000FF 12 | #354361 13 | #000000 14 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /customviews/src/main/res/values/dimens-valueBar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 60dp 4 | 16dp 5 | 10dp 6 | 12dp 7 | 14dp 8 | 18dp 9 | 24dp 10 | 12dp 11 | 14dp 12 | -------------------------------------------------------------------------------- /customviews/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "21.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 17 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:22.2.0' 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | /*/build/ 3 | 4 | # Crashlytics configuations 5 | com_crashlytics_export_strings.xml 6 | 7 | # Local configuration file (sdk path, etc) 8 | local.properties 9 | 10 | # Gradle generated files 11 | .gradle/ 12 | 13 | # Signing files 14 | .signing/ 15 | 16 | # User-specific configurations 17 | .idea/libraries/ 18 | .idea/workspace.xml 19 | .idea/tasks.xml 20 | .idea/.name 21 | .idea/compiler.xml 22 | .idea/copyright/profiles_settings.xml 23 | .idea/encodings.xml 24 | .idea/misc.xml 25 | .idea/modules.xml 26 | .idea/scopes/scope_settings.xml 27 | .idea/vcs.xml 28 | *.iml 29 | 30 | # OS-specific files 31 | .DS_Store 32 | .DS_Store? 33 | ._* 34 | .Spotlight-V100 35 | .Trashes 36 | ehthumbs.db 37 | Thumbs.db 38 | -------------------------------------------------------------------------------- /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 /Applications/android-sdk-macosx/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/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "21.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.intertech.customviewsexample" 9 | minSdkVersion 17 10 | targetSdkVersion 22 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 | compile 'com.android.support:appcompat-v7:22.2.0' 25 | compile project(':customviews') 26 | } 27 | -------------------------------------------------------------------------------- /customviews/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 /Applications/android-sdk-macosx/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/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # android-custom-view-tutorial 2 | 3 | Android Studio project that provides an example application demonstrating the custom views created in the tutorial series 4 | [Android Custom Views][1]. The code for the custom views is located in a library module within the project. 5 | 6 | ## Value Selector 7 | 8 | View to allow the selection of a numeric value by pressing plus/minus buttons. Pressing and holding a 9 | button will update the value repeatedly. 10 | This view can be configured with a minimum and maximum value. There is also a label that will 11 | display below the current value. 12 | 13 | ![ValueSelector](http://www.intertech.com/Blog/wp-content/uploads/2015/07/value_selector.png "ValueSelector") 14 | 15 | ## Value Bar 16 | 17 | View that displays a colored bar as a ratio of an integer value to a maximum value. There is also a circle 18 | indicator and text that displays at the position of the current value, as well as a label (positioned above the bar). 19 | The maximum value is displayed to the right of the bar. 20 | 21 | ![ValueBar](http://www.intertech.com/Blog/wp-content/uploads/2015/07/value_bar.png "ValueBar") 22 | 23 | [1]: http://www.intertech.com/Blog/android-custom-view-tutorial-part-1-combining-existing-views/ 24 | -------------------------------------------------------------------------------- /customviews/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/intertech/customviewsexample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.intertech.customviewsexample; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Button; 7 | 8 | import com.intertech.customviews.ValueBar; 9 | import com.intertech.customviews.ValueSelector; 10 | 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | 18 | final ValueSelector valueSelector = (ValueSelector) findViewById(R.id.valueSelector); 19 | valueSelector.setMinValue(0); 20 | valueSelector.setMaxValue(100); 21 | 22 | final ValueBar valueBar = (ValueBar) findViewById(R.id.valueBar); 23 | valueBar.setMaxValue(100); 24 | valueBar.setAnimated(true); 25 | valueBar.setAnimationDuration(4000l); 26 | 27 | Button updateButton = (Button) findViewById(R.id.updateButton); 28 | updateButton.setOnClickListener(new View.OnClickListener() { 29 | @Override 30 | public void onClick(View view) { 31 | int value = valueSelector.getValue(); 32 | valueBar.setValue(value); 33 | 34 | //code to use Object Animation instead of the built-in ValueBar animation 35 | //if you use this, be sure the call valueBar.setAnimated(false); 36 | /* 37 | ObjectAnimator anim = ObjectAnimator.ofInt(valueBar, "value", valueBar.getValue(), value); 38 | anim.setDuration(1000); 39 | anim.start(); 40 | */ 41 | } 42 | }); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /customviews/src/main/res/layout/value_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 24 | 25 | 36 | 37 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | 20 | 21 | 22 |