├── .gitignore ├── .idea ├── gradle.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── intertech │ │ └── customviewsexample │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── intertech │ │ └── customviewsexample │ │ └── MainActivity.java │ └── res │ ├── layout │ └── activity_main.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-land │ ├── dimens-valueSelector.xml │ └── dimens.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens-valueBar.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── customviews ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── intertech │ │ └── customviews │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── intertech │ │ └── customviews │ │ ├── ValueBar.java │ │ └── ValueSelector.java │ └── res │ ├── drawable │ ├── valueselect_minus.png │ ├── valueselect_minus_state.xml │ ├── valueselect_plus.png │ ├── valueselect_plus_pressed.png │ ├── valueselect_plus_state.xml │ └── valueselect_pressed.png │ ├── layout │ └── value_selector.xml │ └── values │ ├── attrs.xml │ ├── dimens-valueBar.xml │ ├── dimens-valueSelector.xml │ └── strings.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.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 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/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/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 12 | 13 | 19 | 20 | 21 | 22 |