├── .idea ├── .name ├── vcs.xml ├── misc.xml ├── runConfigurations.xml ├── gradle.xml ├── jarRepositories.xml └── codeStyles │ └── Project.xml ├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── in │ │ │ └── krharsh17 │ │ │ └── barview_sample │ │ │ └── MainActivity.kt │ ├── test │ │ └── java │ │ │ └── in │ │ │ └── krharsh17 │ │ │ └── barview_sample │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── in │ │ └── krharsh17 │ │ └── barview_sample │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── library ├── consumer-rules.pro ├── .gitignore ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── res │ │ │ ├── drawable │ │ │ │ └── label_background.png │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── styles.xml │ │ │ │ └── attrs.xml │ │ │ └── layout │ │ │ │ └── alert_dialogue.xml │ │ └── java │ │ │ └── in │ │ │ └── krharsh17 │ │ │ └── barview │ │ │ ├── Constants.kt │ │ │ ├── BarModel.kt │ │ │ ├── Bar.kt │ │ │ ├── BarView.kt │ │ │ └── BarGroup.kt │ ├── test │ │ └── java │ │ │ └── in │ │ │ └── krharsh17 │ │ │ └── barview │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── in │ │ └── krharsh17 │ │ └── barview │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── .settings └── org.eclipse.buildship.core.prefs ├── demo-apk └── app-debug.apk ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .dependabot └── config.yml ├── .gitignore ├── .project ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── boring-cyborg.yml ├── .travis.yml ├── gradle.properties ├── PULL_REQUEST_TEMPLATE.md ├── updateApk.sh ├── gradlew.bat ├── CODE_OF_CONDUCT.md ├── README.md ├── CONTRIBUTING.md └── gradlew /.idea/.name: -------------------------------------------------------------------------------- 1 | BarView -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/consumer-rules.pro: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | rootProject.name='BarView' 3 | -------------------------------------------------------------------------------- /.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /demo-apk/app-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/demo-apk/app-debug.apk -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BarView 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | - package_manager: "java:gradle" 4 | directory: "/" 5 | update_schedule: "weekly" -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /library/src/main/res/drawable/label_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/library/src/main/res/drawable/label_background.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krharsh17/barview-android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Dec 11 14:55:21 IST 2019 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-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | #72FC26 7 | #FFEB3B 8 | #F720A1 9 | #18CEFC 10 | 11 | -------------------------------------------------------------------------------- /library/src/test/java/in/krharsh17/barview/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import org.junit.Assert 4 | import org.junit.Test 5 | 6 | /** 7 | * Example local unit test, which will execute on the development machine (host). 8 | * 9 | * @see [Testing documentation](http://d.android.com/tools/testing) 10 | */ 11 | class ExampleUnitTest { 12 | @Test 13 | fun additionIsCorrect() { 14 | Assert.assertEquals(4, 2 + 2.toLong()) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/test/java/in/krharsh17/barview_sample/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package in.krharsh17.barview_sample; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void additionIsCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | barview-android 4 | Project barview-android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /library/src/main/java/in/krharsh17/barview/Constants.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import `in`.krharsh17.barview.BarView 4 | 5 | interface Constants { 6 | companion object { 7 | const val LABEL_TEXT_COLOR = "#424242" 8 | const val VALUE_TEXT_COLOR = "#FFFFFF" 9 | const val RIPPLE_COLOR = "#EEEEEE" 10 | const val CHAR_ARRAY = "0123456789ABCDEF" 11 | val DEFAULT_INTRO_ANIMATION: Int = BarView.Companion.INTRO_ANIM_NONE 12 | const val DEFAULT_ANIMATION_DURATION = 1400 13 | } 14 | } -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /library/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BarView 3 | Highlight 4 | Fade 5 | Delete 6 | Remove Highlight? 7 | Remove Fade? 8 | Green 9 | Yellow 10 | Pink 11 | Blue 12 | Select a Highlight Color : 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /library/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /library/src/main/java/in/krharsh17/barview/BarModel.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | /** 4 | * This class is represents a BarView entity and contains all the attributes 5 | * required to instantiate a BarGroup 6 | */ 7 | class BarModel 8 | /** 9 | * parameterized constructor 10 | * 11 | * @param label for the barGroup instance 12 | * @param value for approximating the length of Bargroup instance 13 | * @param color hex color value for the fill of barGroup instance 14 | * @param fillRatio for determining the percentage of the bar to be filled 15 | */( 16 | /** 17 | * getters and setters 18 | */ 19 | var label: String, var value: String, var color: String, var fillRatio: Float, var elevation: Int, var radius: Int) -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /library/src/androidTest/java/in/krharsh17/barview/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * @see [Testing documentation](http://d.android.com/tools/testing) 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | Assert.assertEquals("in.krharsh17.barview.test", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /library/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 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 20 | 21 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | sudo: required 3 | jdk: oraclejdk8 4 | android: 5 | components: 6 | - tools 7 | - platform-tools 8 | - build-tools-29.0.2 9 | - android-29 10 | - extra-google-google_play_services 11 | - extra-google-m2repository 12 | - extra-android-m2repository 13 | licenses: 14 | - android-sdk-license-.+ 15 | before_install: 16 | - 'yes | sdkmanager "platforms;android-29"' 17 | - 'chmod +x ./gradlew' 18 | script: 19 | - 'echo "Hello! This is Travis"' 20 | - './gradlew build' 21 | before_cache: 22 | - 'rm -f $HOME/.gradle/caches/modules-2/modules-2.lock' 23 | - 'rm -fr $HOME/.gradle/caches/*/plugin-resolution/' 24 | after_success: 25 | - 'bash updateApk.sh' 26 | cache: 27 | directories: 28 | - $HOME/.gradle/caches/ 29 | - $HOME/.gradle/wrapper/ 30 | - $HOME/.android/build-cache 31 | -------------------------------------------------------------------------------- /app/src/androidTest/java/in/krharsh17/barview_sample/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package in.krharsh17.barview_sample; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | 25 | assertEquals("in.krharsh17.barview_sample", appContext.getPackageName()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | 21 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Issue that this pull request solves 2 | 3 | Fixes: # (issue number) 4 | 5 | ## Proposed changes 6 | 7 | Brief description of what is fixed or changed 8 | 9 | ## Types of changes 10 | 11 | _Put an `x` in the boxes that apply_ 12 | 13 | - [ ] Bugfix (non-breaking change which fixes an issue) 14 | - [ ] New feature (non-breaking change which adds functionality) 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 16 | - [ ] Documentation update (Documentation content changed) 17 | - [ ] Other (please describe): 18 | 19 | ## Checklist 20 | 21 | _Put an `x` in the boxes that apply_ 22 | 23 | - [ ] My code follows the style guidelines of this project 24 | - [ ] I have performed a self-review of my own code 25 | - [ ] I have commented my code, particularly in hard-to-understand areas 26 | - [ ] I have made corresponding changes to the documentation 27 | - [ ] My changes generate no new warnings 28 | 29 | ## Screenshots 30 | 31 | Please attach the screenshots of the changes made in case of change in user interface 32 | 33 | ## Other information 34 | 35 | Any other information that is important to this pull request 36 | -------------------------------------------------------------------------------- /library/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/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion 29 6 | buildToolsVersion "29.0.2" 7 | defaultConfig { 8 | applicationId "in.krharsh17.barview_sample" 9 | minSdkVersion 21 10 | targetSdkVersion 29 11 | versionCode 1 12 | versionName "1.0" 13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation project (":library") 25 | implementation fileTree(dir: 'libs', include: ['*.jar']) 26 | implementation 'androidx.appcompat:appcompat:1.1.0' 27 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 28 | testImplementation 'junit:junit:4.12' 29 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 30 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 31 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 32 | implementation "androidx.core:core-ktx:+" 33 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 34 | } 35 | repositories { 36 | mavenCentral() 37 | } 38 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | group='com.github.krharsh17' 5 | android { 6 | compileSdkVersion 29 7 | buildToolsVersion "29.0.2" 8 | 9 | 10 | defaultConfig { 11 | minSdkVersion 21 12 | targetSdkVersion 29 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | consumerProguardFiles 'consumer-rules.pro' 18 | } 19 | 20 | buildTypes { 21 | release { 22 | minifyEnabled false 23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 24 | } 25 | } 26 | 27 | } 28 | 29 | dependencies { 30 | implementation fileTree(dir: 'libs', include: ['*.jar']) 31 | 32 | implementation 'androidx.appcompat:appcompat:1.1.0' 33 | testImplementation 'junit:junit:4.12' 34 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 35 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' 36 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3' 37 | implementation "androidx.core:core-ktx:+" 38 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 39 | } 40 | repositories { 41 | mavenCentral() 42 | } 43 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /updateApk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | export PUBLISH_BRANCH=${PUBLISH_BRANCH:-master} 5 | export DEVELOPMENT_BRANCH=${DEVELOPMENT_BRANCH:-develop} 6 | 7 | # Setup git 8 | git config --global user.email "noreply@travis.com" 9 | git config --global user.name "Travis CI" 10 | 11 | # Execute the following script only if it's merge to development or master branch 12 | if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_REPO_SLUG" != "krharsh17/barview-android" ] || ! [ "$TRAVIS_BRANCH" == "$DEVELOPMENT_BRANCH" -o "$TRAVIS_BRANCH" == "$PUBLISH_BRANCH" ]; then 13 | echo "We upload apk only for changes in Development or Master" 14 | exit 0 15 | fi 16 | 17 | # Generates app bundle 18 | ./gradlew bundleRelease 19 | 20 | # Clone the repository 21 | git clone --quiet --branch=apk "https://krharsh17:$GITHUB_KEY@github.com/krharsh17/barview-android" apk > /dev/null 22 | 23 | cd apk 24 | 25 | # Remove old files 26 | if [ "$TRAVIS_BRANCH" == "$PUBLISH_BRANCH" ]; then 27 | rm -rf barview-master* 28 | else 29 | rm -rf barview-dev* 30 | fi 31 | 32 | # Copy apk files 33 | find ../app/build/outputs -type f -name '*.apk' -exec cp -v {} . \; 34 | 35 | for file in app*; do 36 | if [ "$TRAVIS_BRANCH" == "$PUBLISH_BRANCH" ]; then 37 | mv "$file" barview-master-"${file:4}" 38 | 39 | elif [ "$TRAVIS_BRANCH" == "$DEVELOPMENT_BRANCH" ]; then 40 | mv "$file" barview-dev-"${file:4}" 41 | fi 42 | done 43 | 44 | git checkout --orphan temporary 45 | 46 | git add . 47 | git commit -m "Travis build pushed to [$TRAVIS_BRANCH]" 48 | 49 | # Delete current apk branch 50 | git branch -D apk 51 | # Rename current branch to apk 52 | git branch -m apk 53 | 54 | git push origin apk -f --quiet > /dev/null -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/in/krharsh17/barview_sample/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview_sample 2 | 3 | import `in`.krharsh17.barview.BarModel 4 | import `in`.krharsh17.barview.BarView 5 | import `in`.krharsh17.barview.BarView.Companion.randomColor 6 | import android.os.Bundle 7 | import androidx.appcompat.app.AppCompatActivity 8 | import java.util.* 9 | 10 | class MainActivity : AppCompatActivity() { 11 | var barView: BarView? = null 12 | var cornerRadius = 20 //in dp 13 | override fun onCreate(savedInstanceState: Bundle?) { 14 | super.onCreate(savedInstanceState) 15 | setContentView(R.layout.activity_main) 16 | barView = findViewById(R.id.barview) 17 | val barModels: ArrayList = ArrayList() 18 | barModels.add(BarModel( 19 | "Samsung", 20 | "30.91", 21 | randomColor, 22 | 0.31f, 0, 0 23 | )) 24 | barModels.add(BarModel( 25 | "Apple", 26 | "25.89", 27 | randomColor, 28 | 1f, 5, 5 29 | )) 30 | barModels.add(BarModel( 31 | "Huawei", 32 | "10.98", 33 | randomColor, 34 | 0.11f, 8, 4 35 | )) 36 | barModels.add(BarModel( 37 | "Xiaomi", 38 | "7.8", 39 | randomColor, 40 | 0.07f, 12, 7 41 | )) 42 | barModels.add(BarModel( 43 | "Oppo", 44 | "4.31", 45 | randomColor, 46 | 0.04f, 7, 18 47 | )) 48 | barModels.add(BarModel( 49 | "Others", 50 | "20.11", 51 | randomColor, 52 | 0.20f, 8, 10 53 | )) 54 | barView!!.setData(barModels) 55 | barView!!.setCornerRadius(cornerRadius) 56 | barView!!.onBarClickListener = object : BarView.OnBarClickListener { 57 | override fun onBarClicked(pos: Int) { 58 | // Do Something 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 26 | * Trolling, insulting/derogatory comments, and personal or political attacks 27 | * Public or private harassment 28 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 29 | * Other conduct which could reasonably be considered inappropriate in a professional setting 30 | 31 | ## Our Responsibilities 32 | 33 | Project maintainers are responsible for clarifying the standards of acceptable 34 | behavior and are expected to take appropriate and fair corrective action in 35 | response to any instances of unacceptable behavior. 36 | 37 | Project maintainers have the right and responsibility to remove, edit, or 38 | reject comments, commits, code, wiki edits, issues, and other contributions 39 | that are not aligned to this Code of Conduct, or to ban temporarily or 40 | permanently any contributor for other behaviors that they deem inappropriate, 41 | threatening, offensive, or harmful. 42 | 43 | ## Scope 44 | 45 | This Code of Conduct applies both within project spaces and in public spaces 46 | when an individual is representing the project or its community. Examples of 47 | representing a project or community include using an official project e-mail 48 | address, posting via an official social media account, or acting as an appointed 49 | representative at an online or offline event. Representation of a project may be 50 | further defined and clarified by project maintainers. 51 | 52 | ## Enforcement 53 | 54 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 55 | reported by contacting the project team at kharsh39@gmail.com. All 56 | complaints will be reviewed and investigated and will result in a response that 57 | is deemed necessary and appropriate to the circumstances. The project team is 58 | obligated to maintain confidentiality with regard to the reporter of an incident. 59 | Further details of specific enforcement policies may be posted separately. 60 | 61 | Project maintainers who do not follow or enforce the Code of Conduct in good 62 | faith may face temporary or permanent repercussions as determined by other 63 | members of the project's leadership. 64 | 65 | ## Attribution 66 | 67 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, 68 | available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) 69 | 70 | For answers to common questions about this code of conduct, see [faq](https://www.contributor-covenant.org/faq) 71 | -------------------------------------------------------------------------------- /library/src/main/res/layout/alert_dialogue.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 18 | 19 | 24 | 25 | 33 | 34 | 42 | 43 | 51 | 52 | 60 | 61 | 69 | 70 | 71 | 78 | 79 | 86 | 87 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | xmlns:android 14 | 15 | ^$ 16 | 17 | 18 | 19 |
20 |
21 | 22 | 23 | 24 | xmlns:.* 25 | 26 | ^$ 27 | 28 | 29 | BY_NAME 30 | 31 |
32 |
33 | 34 | 35 | 36 | .*:id 37 | 38 | http://schemas.android.com/apk/res/android 39 | 40 | 41 | 42 |
43 |
44 | 45 | 46 | 47 | .*:name 48 | 49 | http://schemas.android.com/apk/res/android 50 | 51 | 52 | 53 |
54 |
55 | 56 | 57 | 58 | name 59 | 60 | ^$ 61 | 62 | 63 | 64 |
65 |
66 | 67 | 68 | 69 | style 70 | 71 | ^$ 72 | 73 | 74 | 75 |
76 |
77 | 78 | 79 | 80 | .* 81 | 82 | ^$ 83 | 84 | 85 | BY_NAME 86 | 87 |
88 |
89 | 90 | 91 | 92 | .* 93 | 94 | http://schemas.android.com/apk/res/android 95 | 96 | 97 | ANDROID_ATTRIBUTE_ORDER 98 | 99 |
100 |
101 | 102 | 103 | 104 | .* 105 | 106 | .* 107 | 108 | 109 | BY_NAME 110 | 111 |
112 |
113 |
114 |
115 |
116 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BarView 2 | 3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/896439f51e884b569b90e34527f06676)](https://app.codacy.com/manual/kharsh39/barview-android?utm_source=github.com&utm_medium=referral&utm_content=krharsh17/barview-android&utm_campaign=Badge_Grade_Dashboard) 4 | [![Build Status](https://travis-ci.com/krharsh17/barview-android.svg?branch=develop)](https://travis-ci.com/krharsh17/barview-android) ![JitPack](https://img.shields.io/jitpack/v/github/krharsh17/barview-android?color=%23FFAE42) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/krharsh17/barview-android) 5 | 6 | [![](https://jitpack.io/v/krharsh17/barview-android/month.svg)](https://jitpack.io/#krharsh17/barview-android) 7 | 8 | ![](https://forthebadge.com/images/badges/built-for-android.svg) ![](https://forthebadge.com/images/badges/check-it-out.svg) 9 | 10 | BarView is a native android UI library that allows representation of data in bar graph with slick look and smooth animations. Currently the library is in a very early stage so it does not look very good 😋. 11 | 12 | This project has been selected for **[GirlScript Summer of Code 2020](https://www.gssoc.tech/)**. To begin contributing 13 | - Go through the [guidelines](https://github.com/krharsh17/barview-android/blob/develop/CONTRIBUTING.md) 14 | - Fork a copy of the project to your profile 15 | - Go through the issues and comment on one to get it assigned to yourself 16 | - Discuss on the [gitter](https://gitter.im/barview-android/community) or [slack](https://gssoc20.slack.com/) channel if you have any doubts 17 | - Make the changes in code and create a PR on the main repository 18 | - Ask for a review from a mentor/admin and wait until your code gets merged! 19 | 20 | ## Table of Contents 21 | - [Goal](#goal) 22 | - [Current Progress](#current-progress) 23 | - [Installation](#installation) 24 | - [Usage](#usage) 25 | 26 | ## Goal 27 | 28 | ![Design](https://i.ibb.co/C8XtG1F/Metric-Screen-Bar-Graph.png) 29 | 30 | ## Current Progress 31 | 32 | ![Progress](https://i.imgur.com/ZKLBH03.png) 33 | 34 | ## Installation 35 | 36 | - In your project level build.gradle 37 | ``` 38 | allprojects { 39 | repositories { 40 | ... 41 | maven { url 'https://jitpack.io' } 42 | } 43 | } 44 | ``` 45 | 46 | - In your app level build.gradle 47 | ``` 48 | dependencies { 49 | implementation 'com.github.krharsh17:barview-android:1.0' 50 | } 51 | ``` 52 | 53 | ## Usage 54 | 55 | - XML 56 | ``` 57 | 69 | ``` 70 | 71 | - Important 72 | - All `app:` attributes are optional 73 | - The default values of `app:` attributes are mentioned above 74 | - `barGroupSpacing` & `barHeight` are in dp, while `valueTextSize` & `labelTextSize` are in sp 75 | 76 | 77 | - Java 78 | ``` 79 | 80 | BarView barview = findViewById(R.id.barview); 81 | 82 | ArrayList barModels = new ArrayList<>(); 83 | 84 | barModels.add(new BarModel( 85 | "label_text", 86 | "value_text", 87 | "color_hex", 88 | fill_ratio_float 89 | ) 90 | ); 91 | 92 | //Add more BarModels here.. 93 | 94 | barview.setData(barModels); 95 | 96 | ``` 97 | 98 | ## System Requirements 99 | 100 | - Git 101 | - Android Studio 102 | 103 | ## Learning Resources 104 | 105 | - https://developer.android.com/studio/install 106 | - https://try.github.io/ 107 | 108 | The demo apk for the project is available [here](https://github.com/krharsh17/barview-android/blob/develop/demo-apk/app-debug.apk) 109 | -------------------------------------------------------------------------------- /.github/boring-cyborg.yml: -------------------------------------------------------------------------------- 1 | ##### Labeler ########################################################################################################## 2 | # Enable "labeler" for your PR that would add labels to PRs based on the paths that are modified in the PR. 3 | labelPRBasedOnFilePath: 4 | # Add 'label1' to any changes within 'example' folder or any subfolders 5 | library-update: 6 | - library/**/* 7 | 8 | # Add 'label2' to any file changes within 'example2' folder 9 | # label2: 10 | # - example2/* 11 | 12 | # Complex: Add 'area/core' label to any change within the 'core' package 13 | sample-update: 14 | - app/src/* 15 | - app/src/**/* 16 | 17 | # Add 'test' label to any change to *.spec.js files within the source dir 18 | 19 | ##### Greetings ######################################################################################################## 20 | # Comment to be posted to welcome users when they open their first PR 21 | firstPRWelcomeComment: > 22 | Thanks for opening this pull request! Please make sure you have checked out our contributing guidelines. 23 | 24 | # Comment to be posted to congratulate user on their first merged PR 25 | firstPRMergeComment: > 26 | Awesome work, congrats on your first merged pull request! 27 | 28 | # Comment to be posted to on first time issues 29 | firstIssueWelcomeComment: > 30 | Thanks for opening your first issue here! Be sure to follow the issue template! 31 | 32 | ###### IssueLink Adder ################################################################################################# 33 | # Insert Issue (Jira/Github etc) link in PR description based on the Issue ID in PR title. 34 | # insertIssueLinkInPrDescription: 35 | # specify the placeholder for the issue link that should be present in the description 36 | # descriptionIssuePlaceholderRegexp: "^Issue link: (.*)$" 37 | # matchers: 38 | # you can have several matches - for different types of issues 39 | # only the first matching entry is replaced 40 | # jiraIssueMatch: 41 | # specify the regexp of issue id that you can find in the title of the PR 42 | # the match groups can be used to build the issue id (${1}, ${2}, etc.). 43 | # titleIssueIdRegexp: \[(AIRFLOW-[0-9]{4})\] 44 | # the issue link to be added. ${1}, ${2} ... are replaced with the match groups from the 45 | # title match (remember to use quotes) 46 | # descriptionIssueLink: "[${1}](https://issues.apache.org/jira/browse/${1}/)" 47 | # docOnlyIssueMatch: 48 | # titleIssueIdRegexp: \[(AIRFLOW-X{4})\] 49 | # descriptionIssueLink: "`Document only change`" 50 | 51 | ###### Title Validator ################################################################################################# 52 | # Verifies if commit/PR titles match the regexp specified 53 | # verifyTitles: 54 | # Regular expression that should be matched by titles of commits or PR 55 | # titleRegexp: ^\[AIRFLOW-[0-9]{4}\].*$|^\[AIRFLOW-XXXX\].*$ 56 | # If set to true, it will only check the commit in case there is a single commit. 57 | # In case of multiple commits it will check PR title. 58 | # This reflects the standard behaviour of Github that for `Squash & Merge` GitHub 59 | # takes the title of the squashed commit from PR title rather than from commit message ¯\_(ツ)_/¯ 60 | # For single-commit PRs it takes the squashed commit message from the commit as expected. 61 | # 62 | # If set to false it will check all commit messages. This is useful when you do not squash commits at merge. 63 | # validateEitherPrOrSingleCommitTitle: true 64 | 65 | ###### PR/Branch Up-To-Date Checker #################################################################################### 66 | # Check if the branch is up to date with master when certain files are modified 67 | checkUpToDate: 68 | # File paths that you want to check for 69 | # In this example, it checks if the branch is up to date when alembic migrations are modified in the PR. 70 | # It helps avoid multiple heads in alembic migrations in a collaborative development project. 71 | - airflow/migrations/* 72 | - airflow/migrations/**/* 73 | - airflow/alembic.ini -------------------------------------------------------------------------------- /library/src/main/java/in/krharsh17/barview/Bar.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import android.R 4 | import android.animation.ValueAnimator 5 | import android.content.Context 6 | import android.content.res.ColorStateList 7 | import android.graphics.drawable.ColorDrawable 8 | import android.graphics.drawable.RippleDrawable 9 | import android.graphics.drawable.StateListDrawable 10 | import android.os.Build 11 | import android.view.View 12 | import android.view.animation.DecelerateInterpolator 13 | 14 | internal class Bar 15 | /** 16 | * It can be called by anyone directly from code to create a new instance of the view. 17 | * This constructor doesn’t have access to XML attributes, so you have to fill the parameters manually, using setters. 18 | * 19 | * @param context of the activity 20 | */ 21 | (context: Context?) : View(context) { 22 | /** 23 | * this fuction sets up the relative width of the Bar with respect to the progress 24 | * value given to the BarModel. 25 | * 26 | * @param progress 27 | */ 28 | //increaseWidth is used to give some extra width to bar so that this extra width is used by shadow 29 | fun setProgress(progress: Float, increaseWidth: Int, animationType: Int, animationDuration: Int) { 30 | val params = this.layoutParams 31 | if (animationType == BarView.INTRO_ANIM_EXPAND) { 32 | expand(this, animationDuration, Math.round(params.width * progress)) 33 | } else if (animationType == BarView.INTRO_ANIM_NONE) { 34 | this.visibility = VISIBLE 35 | params.width = Math.round(params.width * progress) + increaseWidth 36 | this.layoutParams = params 37 | } 38 | invalidate() 39 | requestLayout() 40 | } 41 | 42 | override fun onAttachedToWindow() { 43 | super.onAttachedToWindow() 44 | this.isClickable = true 45 | this.isFocusable = true 46 | } 47 | 48 | companion object { 49 | /** 50 | * Sets a ripple drawable as the background of the bar 51 | * The background can display ripples on touch 52 | * 53 | * @param view - The view to set the background to 54 | * @param normalColor - Color when unpressed 55 | * @param touchColor - Color when pressed 56 | */ 57 | fun setRippleDrawable(view: View, normalColor: Int, touchColor: Int) { 58 | try { 59 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 60 | val rippleDrawable = RippleDrawable(ColorStateList.valueOf(touchColor), view.background, null) 61 | view.background = rippleDrawable 62 | } else { 63 | val stateListDrawable = StateListDrawable() 64 | stateListDrawable.addState(intArrayOf(R.attr.state_pressed), ColorDrawable(touchColor)) 65 | stateListDrawable.addState(intArrayOf(R.attr.state_focused), ColorDrawable(touchColor)) 66 | stateListDrawable.addState(intArrayOf(), ColorDrawable(normalColor)) 67 | view.background = stateListDrawable 68 | } 69 | } catch (e: Exception) { 70 | } 71 | } 72 | 73 | /** 74 | * Animator function for the 'expand' intro animation 75 | * 76 | * @param v 77 | * @param duration 78 | * @param targetWidth 79 | */ 80 | fun expand(v: View, duration: Int, targetWidth: Int) { 81 | 82 | //int prevWidth = v.getWidth(); 83 | val prevWidth = 0 84 | v.visibility = VISIBLE 85 | val valueAnimator = ValueAnimator.ofInt(prevWidth, targetWidth) 86 | valueAnimator.addUpdateListener { animation -> 87 | v.layoutParams.width = animation.animatedValue as Int 88 | //v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; 89 | v.requestLayout() 90 | } 91 | valueAnimator.interpolator = DecelerateInterpolator() 92 | valueAnimator.duration = duration.toLong() 93 | valueAnimator.start() 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | ### Submitting Feedback, Requests, and Bugs 4 | 5 | The process for submitting feedback, feature requests, and reporting bugs usually begins by discussion on [the community chat](https://gitter.im/barview-android/community) and, after initial clarification, through [GitHub issues](https://help.github.com/articles/about-issues/). 6 | 7 | ### Submitting Code and Documentation Changes 8 | 9 | The process for accepting changes operates by [Pull Request (PR)](https://help.github.com/articles/about-pull-requests/) and has a few steps: 10 | 11 | 1. If you haven't submitted anything before, and you aren't (yet!) a collaborator on the project, **fork and clone** the repo: 12 | 13 | $ git clone https://github.com//barview-android.git 14 | 15 | 2. Create a **new branch** for the changes you want to work on. Choose a topic for your branch name that reflects the change: 16 | 17 | $ git checkout -b 18 | 19 | 3. **Create or modify the files** with your changes. If you want to show other people work that isn't ready to merge in, commit your changes then create a pull request (PR) with _WIP_ or _Work In Progress_ in the title. 20 | 21 | https://github.com/krharsh17/barview-android/pull/new/master 22 | 23 | 4. Once your changes are ready for final review, commit your changes then modify or **create your pull request (PR)**, assign as a reviewer or ping (using "`@`") a mentor/maintainer (someone able to merge in PRs) active on the project 24 | 25 | 5. Allow others sufficient **time for review and comments** before merging. We make use of GitHub's review feature to comment in-line on PRs when possible. There may be some fixes or adjustments you'll have to make based on feedback. 26 | 27 | 6. Once you have integrated comments, or waited for feedback, a maintainer should merge your changes in! 28 | 29 | ### Branching 30 | 31 | Our branching strategy is based on [this article](https://nvie.com/posts/a-successful-git-branching-model/) which I suggest you read. 32 | 33 | + **master** a history of releases, once merged to from develop and tagged we create a release on the play store & GitHub releases. 34 | 35 | + **develop** the actively worked on next release of the app, what we branch off of while working on new features and what we merge into upon feature completion 36 | 37 | + **feature/** or feature/\/ any branch under this directory is an actively developed feature, feature branches culminate in a PR, are merged and deleted. 38 | Typically a feature branch is off of develop and into develop but in rare scenarios if there is an issue in production a branch may be made off master to fix this issue, this type of feature branch must be merged to develop and master before being deleted. 39 | Branch names should be in the format **\-kebab-case-title** 40 | 41 | All branches should have distinct history and should be visually easy to follow, for this reason only perform merge commits when merging code either by PR or when synchronising. 42 | 43 | If you wish to rebase you should be following the [Golden Rule](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) and ahere to the advice in the heading [Aside: Rebase as cleanup is awesome in the coding lifecycle](https://www.atlassian.com/git/articles/git-team-workflows-merge-or-rebase). 44 | 45 | ### Building 46 | 47 | The BarView project is split into 2 modules 48 | 1. `app` - a sample app to test the barview library during development 49 | 1. `library` - the main library barview, which gets deployed to end user applications 50 | 51 | The default build is `debug`, with this variant you can use a debugger while developing. To install the application click the `run` button in Android Studio with the `app` configuration selected while you have a device connected. 52 | 53 | ### Linting 54 | 55 | PR should be linted properly locally. There is no system restriction applied for this, however, PRs will not be merged until they contain properly formatted code. 56 | 57 | ### Continous Integration 58 | 59 | All PRs will have all these tests run and a combined coverage report will be attached, if coverage is to go down the PR will be marked failed. On Travis CI the automated tests are run on an emulator. To 60 | learn more about the commands run on the CI please refer to [.travis.yml](https://github.com/krharsh17/barview-android/blob/develop/.travis.yml) 61 | 62 | ### Hope you have a wonderful experience contributing to the project 🎉 63 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /library/src/main/java/in/krharsh17/barview/BarView.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import android.content.Context 4 | import android.graphics.Color 5 | import android.graphics.drawable.GradientDrawable 6 | import android.util.AttributeSet 7 | import android.util.Log 8 | import android.view.MotionEvent 9 | import android.view.View 10 | import android.view.ViewGroup 11 | import android.widget.LinearLayout 12 | import android.widget.ScrollView 13 | import java.util.* 14 | 15 | /** 16 | * This is the custom view which is the cumulation of various individual barGroups 17 | * extends from a ScrollView and implementing Constant interface 18 | */ 19 | class BarView : ScrollView, Constants { 20 | private var containerLayout: LinearLayout 21 | private var mcontext: Context 22 | /** 23 | * Returns a reference to the attached Listener 24 | */ 25 | /** 26 | * Attaches a onBarClickListener 27 | */ 28 | var onBarClickListener: OnBarClickListener? = null 29 | private var barGroups: MutableList 30 | private var data: List? = null 31 | private var isDataPopulated = false 32 | var barMargin = 6 33 | var verticalSpacing = 48 34 | var barHeight = 20 35 | var labelFontSize = 18 36 | var valueFontSize = 9 37 | var valueTooltipCornerRadius = 0 38 | 39 | /** 40 | * setters and getters 41 | */ 42 | var animationType: Int = Constants.Companion.DEFAULT_INTRO_ANIMATION 43 | var animationDuration: Int = Constants.Companion.DEFAULT_ANIMATION_DURATION 44 | private var backgroundColor: String? = null 45 | private var gradientStart: String? = null 46 | private var gradientEnd: String? = null 47 | private var gradientDirection: String? = null 48 | private var cornerRadius = 0 49 | var labelTextColor: String? = Constants.Companion.LABEL_TEXT_COLOR 50 | var valueTextColor: String? = Constants.Companion.VALUE_TEXT_COLOR 51 | private var LABEL_FONT: String? = null 52 | private var VALUE_FONT: String? = null 53 | var rippleColor: String? = Constants.Companion.RIPPLE_COLOR 54 | 55 | /** 56 | * parameterized constructors 57 | * It can be called by a anyone directly from code to create a new instance of the view. 58 | * This constructor doesn’t have access to XML attributes, so you have to fill the parameters manually, using setters. 59 | * 60 | * @param context of the activity 61 | */ 62 | constructor(context: Context) : super(context) { 63 | this.mcontext = context 64 | barGroups = ArrayList() 65 | containerLayout = LinearLayout(context) 66 | containerLayout.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 67 | containerLayout.orientation = LinearLayout.VERTICAL 68 | this.addView(containerLayout) 69 | } 70 | 71 | /** 72 | * parameterized constructors 73 | * This is the basic XML constructor. Without it, the layout inflater will crash. 74 | * The AttributeSet parameter contains all attribute values provided via XML. 75 | * 76 | * @param context is the context of the activity 77 | * @param attrs are the attribute values which are saved as an AttributeSet 78 | */ 79 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { 80 | this.mcontext = context 81 | barGroups = ArrayList() 82 | containerLayout = LinearLayout(context) 83 | containerLayout.layoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) 84 | containerLayout.orientation = LinearLayout.VERTICAL 85 | this.addView(containerLayout) 86 | if (attrs != null) { 87 | val a = context.obtainStyledAttributes(attrs, 88 | R.styleable.BarView, 0, 0) 89 | valueTooltipCornerRadius = a.getInteger(R.styleable.BarView_valueTooltipCornerRadius, valueTooltipCornerRadius) 90 | animationType = a.getInteger(R.styleable.BarView_introAnimationType, animationType) 91 | animationDuration = a.getInteger(R.styleable.BarView_introAnimationDuration, animationDuration) 92 | verticalSpacing = a.getInteger(R.styleable.BarView_barGroupSpacing, verticalSpacing) 93 | barHeight = a.getInteger(R.styleable.BarView_barHeight, barHeight) 94 | labelFontSize = a.getInteger(R.styleable.BarView_labelTextSize, labelFontSize) 95 | valueFontSize = a.getInteger(R.styleable.BarView_valueTextSize, valueFontSize) 96 | VALUE_FONT = a.getString(R.styleable.BarView_labelFont) 97 | LABEL_FONT = a.getString(R.styleable.BarView_labelFont) 98 | labelTextColor = a.getString(R.styleable.BarView_labelTextColor) 99 | valueTextColor = a.getString(R.styleable.BarView_valueTextColor) 100 | rippleColor = a.getString(R.styleable.BarView_rippleColor) 101 | backgroundColor = a.getString(R.styleable.BarView_backgroundColor) 102 | gradientStart = a.getString(R.styleable.BarView_gradientStart) 103 | gradientEnd = a.getString(R.styleable.BarView_gradientEnd) 104 | gradientDirection = a.getString(R.styleable.BarView_gradientDirection) 105 | if (labelTextColor == null) { 106 | labelTextColor = Constants.Companion.LABEL_TEXT_COLOR 107 | } 108 | if (valueTextColor == null) { 109 | valueTextColor = Constants.Companion.VALUE_TEXT_COLOR 110 | } 111 | if (rippleColor == null) { 112 | rippleColor = Constants.Companion.RIPPLE_COLOR 113 | } 114 | if (gradientDirection == null) { 115 | gradientDirection = "horizontal" 116 | } 117 | if (backgroundColor != null) { 118 | setBackgroundColor(backgroundColor) 119 | } 120 | if (gradientStart != null && gradientEnd != null) { 121 | setBackgroundGradient(gradientStart, gradientEnd, gradientDirection) 122 | } 123 | a.recycle() 124 | } 125 | } 126 | 127 | interface OnBarClickListener { 128 | fun onBarClicked(pos: Int) 129 | } 130 | 131 | fun setData(data: List?) { 132 | this.data = data 133 | if (animationType == INTRO_ANIM_NONE) { 134 | populateBarView(INTRO_ANIM_NONE, animationDuration) 135 | } else if (animationType == INTRO_ANIM_EXPAND) { 136 | populateBarView(INTRO_ANIM_EXPAND, animationDuration) 137 | } 138 | isDataPopulated = true 139 | } 140 | 141 | fun setData(data: List?, isAnimationEnabled: Boolean) { 142 | this.data = data 143 | if (isAnimationEnabled) { 144 | if (animationType == INTRO_ANIM_NONE) { 145 | populateBarView(INTRO_ANIM_NONE, animationDuration) 146 | } else if (animationType == INTRO_ANIM_EXPAND) { 147 | populateBarView(INTRO_ANIM_EXPAND, animationDuration) 148 | } 149 | } else { 150 | populateBarView(INTRO_ANIM_NONE, animationDuration) 151 | } 152 | } 153 | 154 | /** 155 | * This method iterates over various BarModels and adds a BarGroup for each 156 | * of the BarModels inside private member data 157 | */ 158 | private fun populateBarView(animationType: Int, animationDuration: Int) { 159 | for (b in data!!) { 160 | addBar(b, animationType, animationDuration) 161 | } 162 | } 163 | 164 | /** 165 | * This method actuall instanciates BarGroups based on the BarModel passed in as 166 | * a param and cumulates it into barGroups. 167 | * 168 | * @param data is a BarModel that contains all the required to 169 | * construct a BarGroup instance. 170 | */ 171 | private fun addBar(data: BarModel, animationType: Int, animationDuration: Int) { 172 | val barGroup = BarGroup( 173 | mcontext, 174 | data.label, 175 | data.color, 176 | data.value, 177 | data.fillRatio, 178 | animationType, 179 | animationDuration, 180 | barMargin, 181 | verticalSpacing, 182 | barHeight, 183 | labelFontSize, 184 | valueFontSize, 185 | labelTextColor, 186 | valueTextColor, 187 | rippleColor, 188 | cornerRadius, 189 | valueTooltipCornerRadius, 190 | LABEL_FONT, 191 | VALUE_FONT, 192 | data.elevation, 193 | data.radius 194 | ) 195 | barGroup.setOnTouchListener(object : OnTouchListener { 196 | private val CLICK_ACTION_THRESHOLD = 200 197 | private var startX = 0f 198 | private var startY = 0f 199 | override fun onTouch(v: View, event: MotionEvent): Boolean { 200 | when (event.action) { 201 | MotionEvent.ACTION_DOWN -> { 202 | startX = event.x 203 | startY = event.y 204 | } 205 | MotionEvent.ACTION_UP -> { 206 | val endX = event.x 207 | val endY = event.y 208 | if (isAClick(startX, endX, startY, endY)) { 209 | Log.d("BarView", "you clicked!") 210 | onBarClickListener!!.onBarClicked(barGroups.indexOf(v)) 211 | } 212 | } 213 | else -> Log.d("BarView", "onTouch:Unknown Event ") 214 | } 215 | return true 216 | } 217 | 218 | private fun isAClick(startX: Float, endX: Float, startY: Float, endY: Float): Boolean { 219 | val differenceX = Math.abs(startX - endX) 220 | val differenceY = Math.abs(startY - endY) 221 | return !(differenceX > CLICK_ACTION_THRESHOLD /* =5 */ || differenceY > CLICK_ACTION_THRESHOLD) 222 | } 223 | }) 224 | barGroups.add(barGroup) 225 | containerLayout.addView(barGroup) 226 | invalidate() 227 | requestLayout() 228 | } 229 | 230 | fun setBackgroundColor(color: String?) { 231 | containerLayout.setBackgroundColor(Color.parseColor(color)) 232 | } 233 | 234 | fun setBackgroundGradient(startColor: String?, endColor: String?, direction: String?) { 235 | val gd: GradientDrawable? 236 | gd = when (direction) { 237 | "horizontal" -> GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, intArrayOf(Color.parseColor(startColor), Color.parseColor(endColor))) 238 | "vertical" -> GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, intArrayOf(Color.parseColor(startColor), Color.parseColor(endColor))) 239 | else -> null 240 | } 241 | if (gd != null) { 242 | containerLayout.background = gd 243 | } 244 | } 245 | 246 | fun setCornerRadius(radius: Int) { 247 | cornerRadius = radius 248 | if (isDataPopulated) { 249 | containerLayout.removeAllViews() 250 | populateBarView(animationType, animationDuration) 251 | } 252 | } 253 | 254 | companion object { 255 | const val INTRO_ANIM_NONE = 0 256 | const val INTRO_ANIM_EXPAND = 1 257 | 258 | /** 259 | * This function returns a random color based on a constant {@value #CHAR_ARRAY} 260 | * It builds up the random hex value by randomly choosing between any of the 16 261 | * literals in the char array and appending them one after another 262 | * 263 | * @return a random color as a randomized hex val 264 | */ 265 | @JvmStatic 266 | val randomColor: String 267 | get() { 268 | val letters: CharArray = Constants.Companion.CHAR_ARRAY.toCharArray() 269 | val color = StringBuilder("#") 270 | for (i in 0..5) { 271 | color.append(letters[Math.round(Math.floor(Math.random() * 16)).toInt()]) 272 | } 273 | return color.toString() 274 | } 275 | 276 | /** 277 | * This function approximates the passed in color based on the tolerance value defined in 278 | * the method . It first deconstructs the passed in @ColorInt into its components and then 279 | * randomly adding or subtracting integers in the range of tolerance and then finally 280 | * constructing them all up together and returning a hex literal of the format #XXXXXX 281 | * 282 | * @param approximateColor is the color user wants the bar to be approximately like 283 | * @return 284 | */ 285 | fun getRandomColor(approximateColor: Int): String { 286 | val tolerance = 5 287 | var blue = approximateColor and 0x000000ff 288 | var green = approximateColor and 0x0000ff00 shr 8 289 | var red = approximateColor and 0x00ff0000 shr 16 290 | blue = Math.min(Math.max(0, blue + getRandomNumberInRange(-tolerance, tolerance)), 255) 291 | green = Math.min(Math.max(0, green + getRandomNumberInRange(-tolerance, tolerance)), 255) 292 | red = Math.min(Math.max(0, red + getRandomNumberInRange(-tolerance, tolerance)), 255) 293 | val newApproximateColor = -0x1000000 or (red shl 16) or (green shl 8) or blue 294 | val approximateColorHexLiteral = Integer.toHexString(newApproximateColor) 295 | return "#" + approximateColorHexLiteral.substring(2) 296 | } 297 | 298 | /** 299 | * Helper function returns any random integer between the specified bounds 300 | * both inclusive 301 | * 302 | * @param min variance the user wants in the approximate color 303 | * @param max variance the user wants in the approximate color 304 | * @return 305 | */ 306 | private fun getRandomNumberInRange(min: Int, max: Int): Int { 307 | val r = Random() 308 | return r.nextInt(max - min + 1) + min 309 | } 310 | } 311 | } -------------------------------------------------------------------------------- /library/src/main/java/in/krharsh17/barview/BarGroup.kt: -------------------------------------------------------------------------------- 1 | package `in`.krharsh17.barview 2 | 3 | import android.animation.ValueAnimator 4 | import android.content.Context 5 | import android.graphics.* 6 | import android.graphics.drawable.* 7 | import android.graphics.drawable.shapes.RoundRectShape 8 | import android.util.TypedValue 9 | import android.view.Gravity 10 | import android.view.LayoutInflater 11 | import android.view.View 12 | import android.view.ViewGroup 13 | import android.view.animation.Animation 14 | import android.view.animation.DecelerateInterpolator 15 | import android.view.animation.Transformation 16 | import android.widget.* 17 | import androidx.appcompat.app.AlertDialog 18 | import androidx.constraintlayout.widget.ConstraintLayout 19 | import androidx.constraintlayout.widget.ConstraintSet 20 | import androidx.constraintlayout.widget.Constraints 21 | import java.util.* 22 | 23 | /** 24 | * this class is the custom view which appears as bars in the BarView 25 | * extends ConstraintLayout and implements Constants interface 26 | */ 27 | internal class BarGroup : ConstraintLayout, Constants { 28 | private var mcontext: Context 29 | private var label: TextView 30 | private var initial: View 31 | private var bar: Bar 32 | private var value: TextView 33 | private var increaseHeight = 0f 34 | private var increaseWidth = 0 35 | private var labelText: String? 36 | private var color: String? 37 | private var valueText: String? 38 | private var progress: Float 39 | var elevation = 0 40 | var radius = 0 41 | var numberOfLayers = 0 42 | private var animationType = 0 43 | private var animationDuration: Int = Constants.Companion.DEFAULT_ANIMATION_DURATION 44 | private var BAR_MARGIN = 6 45 | private var VERTICAL_SPACING = 48 46 | private var BAR_HEIGHT = 20 47 | private var LABEL_FONT_SIZE = 18 48 | private var VALUE_FONT_SIZE = 9 49 | private var labelTextColor: String? = Constants.Companion.LABEL_TEXT_COLOR 50 | private var valueTextColor: String? = Constants.Companion.VALUE_TEXT_COLOR 51 | private var VALUE_FONT: String? = null 52 | private var LABEL_FONT: String? = null 53 | private var rippleColor: String? = Constants.Companion.RIPPLE_COLOR 54 | private var CORNER_RADIUS = 0 55 | private var VALUE_TOOLTIP_CORNER_RADIUS = 0 56 | 57 | /** 58 | * one bar has different drawable stacked together with same solid color but different alpha value 59 | * this array of string defined different alpha value from 0 to 1 60 | * we will use maximum of 18 layers for shadow 61 | * numbers of layers can very depending on elevation value 62 | */ 63 | var alphaSet = arrayOf( 64 | "#00", 65 | "#02", 66 | "#04", 67 | "#06", 68 | "#08", 69 | "#10", 70 | "#12", 71 | "#14", 72 | "#16", 73 | "#18", 74 | "#20", 75 | "#22", 76 | "#24", 77 | "#26", 78 | "#28", 79 | "#30", 80 | "#32", 81 | "#35", 82 | "#" 83 | ) 84 | 85 | /** 86 | * parameterized constructor 87 | * 88 | * @param context of the activity 89 | * @param labelText for the barGroup instance 90 | * @param color hex color value for the fill of barGroup instance 91 | * @param valueText for approximating the length of Bargroup instance 92 | * @param progress marking the progress of the bar 93 | */ 94 | constructor(context: Context, labelText: String?, color: String?, valueText: String?, progress: Float) : super(context) { 95 | this.mcontext = context 96 | this.labelText = labelText 97 | this.color = color 98 | this.valueText = valueText 99 | this.progress = progress 100 | label = TextView(context) 101 | initial = View(context) 102 | bar = Bar(context) 103 | bar.visibility = View.GONE 104 | value = TextView(context) 105 | } 106 | 107 | /** 108 | * parameterized constructor 109 | * 110 | * @param context of the activity 111 | * @param labelText for the barGroup instance 112 | * @param color hex color value for the fill of barGroup instance 113 | * @param valueText for approximating the length of Bargroup instance 114 | * @param progress marking the progress of the bar 115 | * self explanatory constants 116 | * @param BAR_MARGIN 117 | * @param VERTICAL_SPACING 118 | * @param BAR_HEIGHT 119 | * @param LABEL_FONT_SIZE 120 | * @param VALUE_FONT_SIZE 121 | * @param labelTextColor 122 | * @param VALUE_TEXT_COLOR 123 | * @param RIPPLE_COLOUR 124 | * @param CORNER_RADIUS 125 | * @param LABEL_FONT 126 | * @param VALUE_FONT 127 | */ 128 | constructor( 129 | context: Context, 130 | labelText: String?, 131 | color: String?, 132 | valueText: String?, 133 | progress: Float, 134 | animationType: Int, 135 | animationDuration: Int, 136 | BAR_MARGIN: Int, 137 | VERTICAL_SPACING: Int, 138 | BAR_HEIGHT: Int, 139 | LABEL_FONT_SIZE: Int, 140 | VALUE_FONT_SIZE: Int, 141 | labelTextColor: String?, 142 | VALUE_TEXT_COLOR: String?, 143 | RIPPLE_COLOUR: String?, 144 | CORNER_RADIUS: Int, 145 | VALUE_TOOLTIP_CORNER_RADIUS: Int, 146 | LABEL_FONT: String?, 147 | VALUE_FONT: String?, 148 | elevation: Int, 149 | radius: Int) : super(context) { 150 | this.mcontext = context 151 | this.labelText = labelText 152 | this.color = color 153 | this.valueText = valueText 154 | this.progress = progress 155 | this.animationType = animationType 156 | this.animationDuration = animationDuration 157 | this.BAR_MARGIN = BAR_MARGIN 158 | this.VERTICAL_SPACING = VERTICAL_SPACING 159 | this.BAR_HEIGHT = BAR_HEIGHT 160 | this.LABEL_FONT_SIZE = LABEL_FONT_SIZE 161 | this.VALUE_FONT_SIZE = VALUE_FONT_SIZE 162 | this.labelTextColor = labelTextColor 163 | valueTextColor = VALUE_TEXT_COLOR 164 | rippleColor = RIPPLE_COLOUR 165 | this.LABEL_FONT = LABEL_FONT 166 | this.VALUE_FONT = VALUE_FONT 167 | this.CORNER_RADIUS = CORNER_RADIUS 168 | this.VALUE_TOOLTIP_CORNER_RADIUS = VALUE_TOOLTIP_CORNER_RADIUS 169 | label = TextView(context) 170 | initial = View(context) 171 | bar = Bar(context) 172 | value = TextView(context) 173 | this.elevation = elevation 174 | this.radius = radius 175 | } 176 | 177 | override fun onAttachedToWindow() { 178 | super.onAttachedToWindow() 179 | label.id = View.generateViewId() 180 | initial.id = View.generateViewId() 181 | bar.id = View.generateViewId() 182 | value.id = View.generateViewId() 183 | if (elevation > 0) { 184 | when (elevation) { 185 | 1, 2, 3 -> numberOfLayers = 5 186 | 4 -> numberOfLayers = 6 187 | 5 -> numberOfLayers = 7 188 | 6 -> numberOfLayers = 8 189 | 7 -> numberOfLayers = 9 190 | 8 -> numberOfLayers = 10 191 | 9 -> numberOfLayers = 11 192 | 10 -> numberOfLayers = 12 193 | 11, 12, 13 -> numberOfLayers = 14 194 | 14, 15, 16 -> numberOfLayers = 16 195 | else -> numberOfLayers = 18 196 | } 197 | } 198 | setupLabel() 199 | setupInitial() 200 | setupBar() 201 | setupValue() 202 | applyConstraints() 203 | } 204 | 205 | /** 206 | * Initializer function for the label segment 207 | */ 208 | private fun setupLabel() { 209 | val labelParams: LayoutParams = Constraints.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT) 210 | labelParams.setMargins( 211 | dp(8f), 212 | dp(VERTICAL_SPACING / 2.toFloat()), 213 | dp(8f), 214 | dp(VERTICAL_SPACING / 2.toFloat()) 215 | ) 216 | label.text = parseLabel(labelText) 217 | label.setTextColor(Color.parseColor(labelTextColor)) 218 | label.setTextSize(TypedValue.COMPLEX_UNIT_SP, LABEL_FONT_SIZE.toFloat()) 219 | if (LABEL_FONT != null) { 220 | label.typeface = Typeface.createFromAsset(mcontext.assets, LABEL_FONT) 221 | } 222 | label.layoutParams = labelParams 223 | label.textAlignment = View.TEXT_ALIGNMENT_CENTER 224 | label.gravity = Gravity.CENTER_VERTICAL 225 | this.addView(label) 226 | } 227 | 228 | /** 229 | * Initializer function for the initial block 230 | */ 231 | fun setupInitial() { 232 | val layers = arrayOfNulls(numberOfLayers + 1) 233 | setLayerForInitial(numberOfLayers, layers) 234 | var initialParams = LayoutParams(dp(12f) + increaseWidth, (dp(BAR_HEIGHT.toFloat()) * increaseHeight).toInt()) 235 | initialParams.rightMargin = dp(12f) 236 | initial.layoutParams = initialParams 237 | val splash_test = LayerDrawable(layers) 238 | initial.background = splash_test 239 | initial.visibility = View.GONE 240 | Bar.setRippleDrawable(initial, Color.parseColor(color), Color.parseColor(rippleColor)) 241 | initial.isClickable = true 242 | initial.isFocusable = true 243 | this.addView(initial) 244 | if (animationType == BarView.Companion.INTRO_ANIM_NONE) { 245 | initial.visibility = View.VISIBLE 246 | initialParams = LayoutParams(dp(12f), dp(BAR_HEIGHT.toFloat())) 247 | initialParams.rightMargin = dp(12f) 248 | initial.layoutParams = initialParams 249 | } else if (animationType == BarView.Companion.INTRO_ANIM_EXPAND) { 250 | val screen_width = Math.round(160 * mcontext.resources.displayMetrics.widthPixels / mcontext.resources.displayMetrics.xdpi) 251 | initialParams = LayoutParams(screen_width, dp(BAR_HEIGHT.toFloat())) 252 | initialParams.rightMargin = dp(12f) 253 | initial.layoutParams = initialParams 254 | expand(initial, animationDuration, dp(12f)) 255 | } 256 | } 257 | 258 | /** 259 | * Initializer function for the main bar 260 | */ 261 | fun setupBar() { 262 | val layers = arrayOfNulls(numberOfLayers + 1) 263 | setLayerForBar(numberOfLayers, layers) 264 | val screen_width = Math.round(160 * mcontext.resources.displayMetrics.widthPixels / mcontext.resources.displayMetrics.xdpi) 265 | bar.layoutParams = LinearLayout.LayoutParams( 266 | screen_width, (dp(BAR_HEIGHT.toFloat()) * increaseHeight).toInt() 267 | ) 268 | val splash_test = LayerDrawable(layers) 269 | bar.background = splash_test 270 | this.addView(bar) 271 | bar.visibility = View.GONE 272 | Bar.setRippleDrawable(bar, Color.parseColor(color), Color.parseColor(rippleColor)) 273 | bar.setProgress(progress, increaseWidth, animationType, animationDuration) 274 | bar.setOnLongClickListener { 275 | addOptions() 276 | true 277 | } 278 | } 279 | 280 | /** 281 | * Initializer function for the value tooltip. By default the corner radius of tooltips is zero 282 | * and if user specifies a value for corner radius then the changes ar applied in the tooltips. 283 | * 284 | * 285 | */ 286 | private fun setupValue() { 287 | value.text = valueText 288 | //value.setBackground(context.getResources().getDrawable(R.drawable.label_background)); 289 | val bitmap = Bitmap.createBitmap( 290 | 110, // Width 291 | 60, // Height 292 | Bitmap.Config.ARGB_8888 // Config 293 | ) 294 | val canvas = Canvas(bitmap) 295 | canvas.drawColor(Color.WHITE) 296 | val paint = Paint() 297 | paint.style = Paint.Style.FILL 298 | paint.color = Color.BLACK 299 | paint.isAntiAlias = true 300 | val offset = 5 301 | val rectF = RectF( 302 | offset.toFloat(), // left 303 | offset.toFloat(), // top 304 | (canvas.width - offset).toFloat(), // right 305 | (canvas.height - offset).toFloat() // bottom 306 | ) 307 | val cornersRadius = VALUE_TOOLTIP_CORNER_RADIUS 308 | canvas.drawRoundRect( 309 | rectF, // rect 310 | cornersRadius.toFloat(), // rx 311 | cornersRadius.toFloat(), // ry 312 | paint // Paint 313 | ) // method to draw rectangular tooltip with specified corner radius 314 | val d: Drawable = BitmapDrawable(resources, bitmap) // conversion of bitmap into drawable 315 | value.background = d 316 | value.rotation = 90f 317 | value.gravity = Gravity.CENTER 318 | value.setPadding(0, dp(8f), 0, dp(8f)) 319 | value.setTextColor(Color.parseColor(valueTextColor)) 320 | value.setTextSize(TypedValue.COMPLEX_UNIT_SP, VALUE_FONT_SIZE.toFloat()) 321 | value.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) 322 | if (VALUE_FONT != null) { 323 | val tf = get(VALUE_FONT!!, mcontext) 324 | value.typeface = tf 325 | } 326 | value.layoutParams = LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) 327 | value.isClickable = true 328 | value.isFocusable = true 329 | Bar.setRippleDrawable(value, Color.parseColor(color), Color.parseColor(rippleColor)) 330 | this.addView(value) 331 | } 332 | 333 | /** 334 | * Sets constraints for all pieces of a BarGroup instance 335 | */ 336 | private fun applyConstraints() { 337 | val constraintSet = ConstraintSet() 338 | constraintSet.clone(this) 339 | constraintSet.setHorizontalBias(initial.id, 0.30f) 340 | constraintSet.connect(initial.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 0) 341 | constraintSet.connect(initial.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, 0) 342 | constraintSet.connect(initial.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP, dp(BAR_MARGIN.toFloat())) 343 | constraintSet.connect(initial.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, dp(BAR_MARGIN.toFloat())) 344 | constraintSet.connect(bar.id, ConstraintSet.START, initial.id, ConstraintSet.END, dp(BAR_MARGIN.toFloat())) 345 | constraintSet.connect(bar.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP) 346 | constraintSet.connect(bar.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM) 347 | constraintSet.connect(value.id, ConstraintSet.START, bar.id, ConstraintSet.END, dp(BAR_MARGIN.toFloat())) 348 | constraintSet.connect(value.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP) 349 | constraintSet.connect(value.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM) 350 | constraintSet.connect(label.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, 0) 351 | constraintSet.connect(label.id, ConstraintSet.END, initial.id, ConstraintSet.END, 0) 352 | constraintSet.connect(label.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP) 353 | constraintSet.connect(label.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM) 354 | constraintSet.applyTo(this) 355 | } 356 | 357 | /** 358 | * Converts density independent pixel units (dp) to pixel units (px) 359 | * 360 | * @param dp 361 | */ 362 | private fun dp(dp: Float): Int { 363 | return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mcontext.resources.displayMetrics)) 364 | } 365 | 366 | /** 367 | * elevation 368 | * Function for creating drawable of with solid color and with specific alpha 369 | * 370 | * @param color 371 | * @param currentLayer 372 | * @param totalLayer 373 | * @param radius 374 | */ 375 | fun getRoundRect(color: String, currentLayer: Int, totalLayer: Int, radius: Int): Drawable { 376 | var localRadius = radius 377 | var leftTopPadding = 1 378 | if (currentLayer % 3 == 0) { 379 | leftTopPadding = 2 380 | } 381 | val rightPadding = 3 382 | val bottomPadding = 3 383 | var shadowalpha: String? = null 384 | val increment = 16 / (totalLayer - 2) 385 | var layernumber = 0 386 | if (radius < 0) { 387 | localRadius = 0 388 | } 389 | if (radius > 20) { 390 | localRadius = 20 391 | } 392 | if (currentLayer % 3 == 0) { 393 | leftTopPadding = 2 394 | } 395 | if (currentLayer == totalLayer) { 396 | shadowalpha = "#" 397 | } else { 398 | layernumber = increment * currentLayer 399 | if (layernumber >= 17) { 400 | layernumber = 17 401 | } 402 | shadowalpha = alphaSet[layernumber] 403 | } 404 | var rectShape = RoundRectShape(floatArrayOf( 405 | localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), 406 | localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2 407 | .toFloat()), null, null) 408 | if (totalLayer == currentLayer) { 409 | if (localRadius == 0) { 410 | localRadius = 2 411 | } 412 | rectShape = RoundRectShape(floatArrayOf( 413 | localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), 414 | localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2.toFloat(), localRadius * 2 415 | .toFloat()), null, null) 416 | } 417 | val shapeDrawable = ShapeDrawable(rectShape) 418 | shapeDrawable.setPadding(leftTopPadding, leftTopPadding, rightPadding, bottomPadding) 419 | shapeDrawable.paint.color = Color.parseColor(shadowalpha + color) 420 | shapeDrawable.paint.style = Paint.Style.FILL 421 | shapeDrawable.paint.isAntiAlias = true 422 | shapeDrawable.paint.flags = Paint.ANTI_ALIAS_FLAG 423 | return shapeDrawable 424 | } 425 | 426 | /** 427 | * Parses the label text to truncate or hyphenize the string to fit in the given space 428 | * 429 | * @param labelText 430 | */ 431 | private fun parseLabel(labelText: String?): String { 432 | val tokens = labelText!!.split(" ".toRegex()).toTypedArray() 433 | val finalizedString = StringBuilder() 434 | for (s in tokens) { 435 | if (s.length < 8) { 436 | finalizedString.append(""" 437 | $s 438 | 439 | """.trimIndent()) 440 | } else if (s.length >= 8 && s.length < 12) { 441 | finalizedString.append(""" 442 | ${s.substring(0, 7)} 443 | 444 | """.trimIndent()) 445 | finalizedString.append(""" 446 | -${s.substring(7)} 447 | 448 | """.trimIndent()) 449 | } else if (s.length >= 12 && s.length < 15) { 450 | finalizedString.append(""" 451 | ${s.substring(0, 7)} 452 | 453 | """.trimIndent()) 454 | finalizedString.append(""" 455 | -${s.substring(7, 12)} 456 | 457 | """.trimIndent()) 458 | if (s.length > 13) { 459 | finalizedString.append(""" 460 | -${s.substring(13)} 461 | 462 | """.trimIndent()) 463 | } 464 | } else { 465 | finalizedString.append(""" 466 | ${s.substring(0, 5)}.. 467 | 468 | """.trimIndent()) 469 | } 470 | } 471 | finalizedString.deleteCharAt(finalizedString.length - 1) 472 | return finalizedString.toString() 473 | } 474 | 475 | /** 476 | * The animation function takes the actual view-group, animation duration and target width in dp as it's arguments 477 | * and takes initial width as 0 dp. After this, using ValueAnimator, the barview is made to expand to provided width 478 | * in the specified time duration and it's visibility is set to visible during animation. 479 | */ 480 | class ResizeAnimation(var view: View, val targetHeight: Int, var startHeight: Int) : Animation() { 481 | override fun applyTransformation(interpolatedTime: Float, t: Transformation) { 482 | val newHeight = (startHeight + targetHeight * interpolatedTime).toInt() 483 | //to support decent animation, change new heigt as Nico S. recommended in comments 484 | //int newHeight = (int) (startHeight+(targetHeight - startHeight) * interpolatedTime); 485 | view.layoutParams.height = newHeight 486 | view.requestLayout() 487 | } 488 | 489 | override fun initialize(width: Int, height: Int, parentWidth: Int, parentHeight: Int) { 490 | super.initialize(width, height, parentWidth, parentHeight) 491 | } 492 | 493 | override fun willChangeBounds(): Boolean { 494 | return true 495 | } 496 | 497 | } 498 | 499 | /** 500 | * This creates a gradient drawable background for the bars - sets a shape, a color and radius for the corners. 501 | * 502 | * @param color is the color in int which is used as the background color. 503 | */ 504 | fun setUpRoundBars(color: Int): GradientDrawable { 505 | val gradientDrawable = GradientDrawable() 506 | gradientDrawable.shape = GradientDrawable.RECTANGLE 507 | gradientDrawable.setColor(color) 508 | gradientDrawable.cornerRadius = CORNER_RADIUS.toFloat() 509 | return gradientDrawable 510 | } 511 | 512 | fun setUpRoundBars(color: Int, highlightColor: Int): GradientDrawable { 513 | /** 514 | * This creates a gradient drawable background for the bars - sets a shape, a color and radius for the corners. 515 | * @param color is the color in int which is used as the background color. 516 | */ 517 | val gradientDrawable = GradientDrawable() 518 | gradientDrawable.shape = GradientDrawable.RECTANGLE 519 | gradientDrawable.setColor(color) 520 | gradientDrawable.setStroke(5, highlightColor) 521 | gradientDrawable.cornerRadius = CORNER_RADIUS.toFloat() 522 | return gradientDrawable 523 | } 524 | 525 | /** 526 | * Generates a modified color for highlighting. 527 | * 528 | * @param backColor is the backcolor which will be used to highlight. 529 | * @param factor factor by which backcolor is to be changed. 530 | * @return modified color which is the color used as the backgroundcolor. 531 | */ 532 | fun changeColor(backColor: Int, factor: Double): String { 533 | val modifiedColor: String 534 | val hsv = FloatArray(3) 535 | Color.colorToHSV(backColor, hsv) 536 | hsv[2] = hsv[2] * factor.toFloat() 537 | modifiedColor = String.format("#%06X", 0xFFFFFF and Color.HSVToColor(hsv)) 538 | return modifiedColor 539 | } 540 | 541 | /** 542 | * to add shadow. 543 | * 544 | * @param numberOfLayers param to add shadow behind the bars. 545 | * @param layers param to add shadow behind the bars. 546 | */ 547 | fun setLayerForBar(numberOfLayers: Int, layers: Array) { 548 | for (i in 0..numberOfLayers) { 549 | layers[i] = null 550 | } 551 | for (i in 0..numberOfLayers) { 552 | layers[i] = getRoundRect(color!!.substring(1), i, numberOfLayers, radius) 553 | } 554 | increaseHeight = 1f 555 | increaseWidth = 0 556 | if (this.numberOfLayers > 0) { 557 | increaseHeight = 1.2f + (numberOfLayers - 5) * 0.1f 558 | increaseWidth = 20 + (numberOfLayers - 5) * 4 559 | } 560 | } 561 | 562 | /** 563 | * to add shadow 564 | * 565 | * @param numberOfLayers param to add shadow behind the bars. 566 | * @param layers param to add shadow behind the bars. 567 | */ 568 | fun setLayerForInitial(numberOfLayers: Int, layers: Array) { 569 | for (i in 0..numberOfLayers) { 570 | layers[i] = null 571 | } 572 | for (i in 0..numberOfLayers) { 573 | layers[i] = getRoundRect(color!!.substring(1), i, numberOfLayers, radius) 574 | } 575 | increaseHeight = 1f //To give some extra height of bar for shadow 576 | increaseWidth = 0 //To give some extra width of bar for shadow 577 | if (this.numberOfLayers > 0) { 578 | increaseHeight = 1.2f + (numberOfLayers - 5) * 0.1f 579 | increaseWidth = 15 + (numberOfLayers - 5) * 4 580 | } 581 | } 582 | 583 | /** 584 | * adds highlight, fade to the bars or deletes a bar completely after showing an alert dialogue. 585 | */ 586 | fun addOptions() { 587 | val alertDialog = AlertDialog.Builder(mcontext) 588 | val layoutInflater = LayoutInflater.from(mcontext) 589 | val dialogueView = layoutInflater.inflate(R.layout.alert_dialogue, null) 590 | alertDialog.setView(dialogueView) 591 | val highlight = dialogueView.findViewById(R.id.highlight) 592 | val highlightColor = dialogueView.findViewById(R.id.highlightColor) 593 | val fade = dialogueView.findViewById(R.id.fade) 594 | val delete = dialogueView.findViewById(R.id.delete) 595 | highlight.setOnClickListener { highlightColor.visibility = View.VISIBLE } 596 | fade.setOnClickListener { highlightColor.visibility = View.GONE } 597 | delete.setOnClickListener { highlightColor.visibility = View.GONE } 598 | val green = dialogueView.findViewById(R.id.green) 599 | val blue = dialogueView.findViewById(R.id.blue) 600 | val pink = dialogueView.findViewById(R.id.pink) 601 | val yellow = dialogueView.findViewById(R.id.yellow) 602 | alertDialog.setPositiveButton("okay") { dialogInterface, i -> 603 | val colorOfHighlight: Int 604 | if (highlight.isChecked) { 605 | colorOfHighlight = assignColor(green, blue, pink, yellow) 606 | if (colorOfHighlight == 0) { 607 | Toast.makeText(mcontext, "Please Choose a Color", Toast.LENGTH_SHORT).show() 608 | } else { 609 | val myColor = changeColor(Color.parseColor(color), 0.7) 610 | bar.background = setUpRoundBars(Color.parseColor(myColor), colorOfHighlight) 611 | initial.background = setUpRoundBars(Color.parseColor(myColor), colorOfHighlight) 612 | bar.setOnLongClickListener { 613 | removeOptions(highlight, fade) 614 | true 615 | } 616 | } 617 | } 618 | if (fade.isChecked) { 619 | setAlphaValue(0.13.toFloat()) 620 | bar.setOnLongClickListener { 621 | removeOptions(highlight, fade) 622 | true 623 | } 624 | } 625 | if (delete.isChecked) { 626 | removeViews() 627 | } 628 | }.setNegativeButton("cancel") { dialogInterface, i -> 629 | //Do nothing 630 | }.show() 631 | } 632 | 633 | /** 634 | * assigns a color which will be used as the highlight color. 635 | * 636 | * @param green Radio Button of the Alert Dialogue view which sets green color as highlight color if checked. 637 | * @param blue Radio Button of the Alert Dialogue view which sets blue color as highlight color if checked. 638 | * @param pink Radio Button of the Alert Dialogue view which sets pink color as highlight color if checked. 639 | * @param yellow Radio Button of the Alert Dialogue view which sets yellow color as highlight color if checked. 640 | * @return color which will be used to highlight. 641 | */ 642 | fun assignColor(green: RadioButton, blue: RadioButton, pink: RadioButton, yellow: RadioButton): Int { 643 | var colorOfHighlight = 0 644 | if (green.isChecked) { 645 | colorOfHighlight = resources.getColor(R.color.greenHighlight) 646 | } 647 | if (blue.isChecked) { 648 | colorOfHighlight = resources.getColor(R.color.blueHighlight) 649 | } 650 | if (pink.isChecked) { 651 | colorOfHighlight = resources.getColor(R.color.pinkHighlight) 652 | } 653 | if (yellow.isChecked) { 654 | colorOfHighlight = resources.getColor(R.color.yellowHighlight) 655 | } 656 | return colorOfHighlight 657 | } 658 | 659 | /** 660 | * changes the alpha value so that the views are only slightly visible. 661 | * 662 | * @param alphaValue is used to assign an Alpha value. 663 | */ 664 | fun setAlphaValue(alphaValue: Float) { 665 | bar.alpha = alphaValue 666 | initial.alpha = alphaValue 667 | label.alpha = alphaValue 668 | value.alpha = alphaValue 669 | } 670 | 671 | /** 672 | * sets the original background for bars - after highlight is removed. 673 | */ 674 | fun setOriginalBackground() { 675 | val layers = arrayOfNulls(numberOfLayers + 1) 676 | setLayerForBar(numberOfLayers, layers) 677 | val splash_test_bar = LayerDrawable(layers) 678 | bar.background = splash_test_bar 679 | setLayerForInitial(numberOfLayers, layers) 680 | val splash_test_initial = LayerDrawable(layers) 681 | initial.background = splash_test_initial 682 | } 683 | 684 | /** 685 | * Removes all the views. 686 | */ 687 | fun removeViews() { 688 | removeView(bar) 689 | removeView(initial) 690 | removeView(label) 691 | removeView(value) 692 | } 693 | 694 | /** 695 | * Generates an alert dialogue to remove the selected option. 696 | * 697 | * @param highlight Radio Button in dialogue view which highlights the bar if selected. 698 | * @param fade Radio Button in dialogue view which fades the bar if selected. 699 | */ 700 | fun removeOptions(highlight: RadioButton, fade: RadioButton) { 701 | var message: String? = null 702 | if (highlight.isChecked) { 703 | message = resources.getString(R.string.removeHighlight) 704 | } 705 | if (fade.isChecked) { 706 | message = resources.getString(R.string.removeFade) 707 | } 708 | AlertDialog.Builder(mcontext).setMessage(message).setPositiveButton("yes") { dialogInterface, i -> 709 | if (highlight.isChecked) { 710 | setOriginalBackground() 711 | } 712 | if (fade.isChecked) { 713 | setAlphaValue(1f) 714 | } 715 | bar.setOnLongClickListener { 716 | addOptions() 717 | true 718 | } 719 | }.setNegativeButton("cancel") { dialogInterface, i -> 720 | //Do nothing 721 | }.show() 722 | } 723 | 724 | companion object { 725 | var fontCache = Hashtable() 726 | 727 | /** 728 | * Loads font from assets 729 | * 730 | * @param name 731 | * @param context 732 | */ 733 | operator fun get(name: String, context: Context): Typeface? { 734 | var tf = fontCache[name] 735 | if (tf == null) { 736 | tf = try { 737 | Typeface.createFromAsset(context.assets, name) 738 | } catch (e: Exception) { 739 | return null 740 | } 741 | fontCache[name] = tf 742 | } 743 | return tf 744 | } 745 | 746 | /** 747 | * Animator function for the 'expand' intro animation 748 | * 749 | * @param v 750 | * @param duration 751 | * @param targetWidth 752 | */ 753 | fun expand(v: View, duration: Int, targetWidth: Int) { 754 | 755 | //int prevWidth = v.getWidth(); 756 | val prevWidth = 0 757 | v.visibility = View.VISIBLE 758 | val valueAnimator = ValueAnimator.ofInt(prevWidth, targetWidth) 759 | valueAnimator.addUpdateListener { animation -> 760 | v.layoutParams.width = animation.animatedValue as Int 761 | //v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; 762 | v.requestLayout() 763 | } 764 | valueAnimator.interpolator = DecelerateInterpolator() 765 | valueAnimator.duration = duration.toLong() 766 | valueAnimator.start() 767 | } 768 | } 769 | } --------------------------------------------------------------------------------