diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..0a213d6792 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: mpandroidchart +open_collective: philippjahoda +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 49ed0dfc1d..b75838b907 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -28,10 +28,10 @@ cannot answer support questions here. We will close your issue without a respons **Device (please complete the following information):** - Device: [e.g. Google Pixel] - Android Version [e.g. 7.0] - - Library Version (e.g. 3.0.3) + - Library Version (e.g. 3.1.0-alpha) **Additional Context** diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 496d0a0d8d..3a5938eee9 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -33,10 +33,12 @@ support questions here. We will close your issue without a response. **Device (please complete the following information):** - Device: [e.g. Google Pixel] - Android Version [e.g. 7.0] - - Library Version (e.g. 3.0.3) + - Library Version (e.g. 3.1.0-alpha) **Additional Context** + +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 823b940961..54b30c983b 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -31,3 +31,4 @@ support questions here. We will close your issue without a response. **Additional context** +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. diff --git a/.github/ISSUE_TEMPLATE/Support_help.md b/.github/ISSUE_TEMPLATE/Support_help.md index 64c87763df..70a086d3d7 100644 --- a/.github/ISSUE_TEMPLATE/Support_help.md +++ b/.github/ISSUE_TEMPLATE/Support_help.md @@ -14,7 +14,7 @@ Instead, do the following: 1. Download the [Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) and check out the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample). 90% of the time there is an example that does exactly what you are trying to do. -1. Look at the [Wiki](https://github.com/PhilJay/MPAndroidChart/wiki) for the official documentation for MPAndroidChart. You can also browse the [javadoc](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for a more detailed tutorial of the API. +1. Look at the [Wiki](https://github.com/PhilJay/MPAndroidChart/wiki) for the official documentation for MPAndroidChart. You can also browse the [javadoc](https://jitpack.io/com/github/philjay/mpandroidchart/v3.1.0-alpha/javadoc/) for a more detailed tutorial of the API. 1. Go to [StackOverflow](https://stackoverflow.com/questions/tagged/mpandroidchart) and ask your questions there. The community will be much more helpful and willing to offer guidance. @@ -22,3 +22,6 @@ Instead, do the following: ### You have been warned! From now on, any issues asking for help will get closed with a link to this file. + +### Additional Context +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. diff --git a/.gitignore b/.gitignore index a340b1d6b3..feed37b27d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ gen/ generated/ docs/ finalOutput/ +projectFilesBackup/ build.xml diff --git a/.idea/runConfigurations/MPChartExample.xml b/.idea/runConfigurations/MPChartExample.xml new file mode 100644 index 0000000000..e6bcf50331 --- /dev/null +++ b/.idea/runConfigurations/MPChartExample.xml @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index 9383f623c6..0000000000 --- a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -build.family.org.gradle.tooling.model.eclipse.HierarchicalEclipseProject=;MPChartExample;MPChartLib; -org.springsource.ide.eclipse.gradle.rootprojectloc= diff --git a/LICENSE b/LICENSE index 8dada3edaf..c1551a9dce 100644 --- a/LICENSE +++ b/LICENSE @@ -1,195 +1,7 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. + you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 diff --git a/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index be975eb2db..0000000000 --- a/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml deleted file mode 100644 index 3fa15cd69c..0000000000 --- a/MPChartExample/AndroidManifest.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8e6fe137b8..2d607e9991 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,24 +1,14 @@ apply plugin: 'com.android.application' -apply plugin: 'realm-android' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 28 defaultConfig { + applicationId "com.xxmassdeveloper.mpchartexample" minSdkVersion 16 - targetSdkVersion 27 - versionCode 56 - versionName '3.0.3' - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - - sourceSets { - main { - java.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - manifest.srcFile 'AndroidManifest.xml' - } - } + targetSdkVersion 28 + versionCode 57 + versionName '3.1.0' + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -27,39 +17,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - - lintOptions { - abortOnError false - } -} - -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' - //classpath 'io.realm:realm-gradle-plugin:0.88.2' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -repositories { - maven { url "https://jitpack.io/" } - maven { // this is for realm-db - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } } dependencies { - //compile fileTree(dir: 'libs', include: ['*.jar']) - //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' - + implementation "androidx.appcompat:appcompat:1.0.2" + implementation 'com.google.android.material:material:1.0.0' implementation project(':MPChartLib') - implementation 'com.android.support:appcompat-v7:27.1.1' - //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) - //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } diff --git a/MPChartExample/proguard-project.txt b/MPChartExample/proguard-project.txt deleted file mode 100644 index f2fe1559a2..0000000000 --- a/MPChartExample/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/MPChartExample/proguard-rules.pro b/MPChartExample/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/MPChartExample/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties deleted file mode 100644 index b32d807be6..0000000000 --- a/MPChartExample/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-23 -android.library.reference.1=../MPChartLib diff --git a/MPChartExample/res/drawable-nodpi/marker.png b/MPChartExample/res/drawable-nodpi/marker.png deleted file mode 100644 index 616cdd7b31..0000000000 Binary files a/MPChartExample/res/drawable-nodpi/marker.png and /dev/null differ diff --git a/MPChartExample/res/drawable/new_background.xml b/MPChartExample/res/drawable/new_background.xml deleted file mode 100644 index c2d3b9cfc5..0000000000 --- a/MPChartExample/res/drawable/new_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml b/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml deleted file mode 100644 index 6d7a7763df..0000000000 --- a/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_candlechart_noseekbar.xml b/MPChartExample/res/layout/activity_candlechart_noseekbar.xml deleted file mode 100644 index 8e5d4bc26e..0000000000 --- a/MPChartExample/res/layout/activity_candlechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml b/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml deleted file mode 100644 index a48307987e..0000000000 --- a/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_piechart_noseekbar.xml b/MPChartExample/res/layout/activity_piechart_noseekbar.xml deleted file mode 100644 index 52c62806b0..0000000000 --- a/MPChartExample/res/layout/activity_piechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml b/MPChartExample/res/layout/activity_radarchart_noseekbar.xml deleted file mode 100644 index d8e3b35aab..0000000000 --- a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_realm_wiki.xml b/MPChartExample/res/layout/activity_realm_wiki.xml deleted file mode 100644 index d4e27933cf..0000000000 --- a/MPChartExample/res/layout/activity_realm_wiki.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml b/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml deleted file mode 100644 index 548a0c7a66..0000000000 --- a/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/menu/candle.xml b/MPChartExample/res/menu/candle.xml deleted file mode 100644 index cdf1c4e4dd..0000000000 --- a/MPChartExample/res/menu/candle.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/menu/dynamical.xml b/MPChartExample/res/menu/dynamical.xml deleted file mode 100644 index c43a3a0ae6..0000000000 --- a/MPChartExample/res/menu/dynamical.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/res/menu/pie.xml deleted file mode 100644 index 0e5323a590..0000000000 --- a/MPChartExample/res/menu/pie.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/res/menu/realtime.xml deleted file mode 100644 index a4b2d22a78..0000000000 --- a/MPChartExample/res/menu/realtime.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/values-sw600dp/dimens.xml b/MPChartExample/res/values-sw600dp/dimens.xml deleted file mode 100644 index 44f01db75f..0000000000 --- a/MPChartExample/res/values-sw600dp/dimens.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/MPChartExample/res/values-sw720dp-land/dimens.xml b/MPChartExample/res/values-sw720dp-land/dimens.xml deleted file mode 100644 index 61e3fa8fbc..0000000000 --- a/MPChartExample/res/values-sw720dp-land/dimens.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 128dp - - diff --git a/MPChartExample/res/values-v11/styles.xml b/MPChartExample/res/values-v11/styles.xml deleted file mode 100644 index 3c02242ad0..0000000000 --- a/MPChartExample/res/values-v11/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/values-v14/styles.xml b/MPChartExample/res/values-v14/styles.xml deleted file mode 100644 index a91fd0372b..0000000000 --- a/MPChartExample/res/values-v14/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/values/dimens.xml b/MPChartExample/res/values/dimens.xml deleted file mode 100644 index 55c1e5908c..0000000000 --- a/MPChartExample/res/values/dimens.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - 16dp - 16dp - - diff --git a/MPChartExample/res/values/strings.xml b/MPChartExample/res/values/strings.xml deleted file mode 100644 index 7f59af64bb..0000000000 --- a/MPChartExample/res/values/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - MPAndroidChart Example - Settings - Hello world! - - diff --git a/MPChartExample/res/values/styles.xml b/MPChartExample/res/values/styles.xml deleted file mode 100644 index 6ce89c7ba4..0000000000 --- a/MPChartExample/res/values/styles.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java deleted file mode 100644 index f6cffddcbe..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ /dev/null @@ -1,200 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample; - -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; -import android.widget.Toast; - -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import java.util.ArrayList; - -public class AnotherBarActivity extends DemoBase implements OnSeekBarChangeListener { - - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart); - - tvX = findViewById(R.id.tvXMax); - tvY = findViewById(R.id.tvYMax); - - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = findViewById(R.id.chart1); - - mChart.getDescription().setEnabled(false); - - // if more than 60 entries are displayed in the chart, no values will be - // drawn - mChart.setMaxVisibleValueCount(60); - - // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setDrawGridLines(false); - - mChart.getAxisLeft().setDrawGridLines(false); - - // setting data - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(100); - - // add a nice and smooth animation - mChart.animateY(2500); - - mChart.getLegend().setEnabled(false); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.bar, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - - for (IDataSet set : mChart.getData().getDataSets()) - set.setDrawValues(!set.isDrawValuesEnabled()); - - mChart.invalidate(); - break; - } - case R.id.actionToggleHighlight: { - - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); - } - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) - ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - - mChart.invalidate(); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000); - break; - } - case R.id.animateXY: { - - mChart.animateXY(3000, 3000); - break; - } - case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val = (float) (Math.random() * mult) + mult / 3; - yVals1.add(new BarEntry(i, val)); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "Data Set"); - set1.setColors(ColorTemplate.VORDIPLOM_COLORS); - set1.setDrawValues(false); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(dataSets); - mChart.setData(data); - mChart.setFitBars(true); - } - - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java deleted file mode 100644 index 85d213e351..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ /dev/null @@ -1,464 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample; - -import android.graphics.Color; -import android.graphics.DashPathEffect; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.support.v4.content.ContextCompat; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; -import android.widget.Toast; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.listener.ChartTouchListener; -import com.github.mikephil.charting.listener.OnChartGestureListener; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.Utils; -import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import java.util.ArrayList; -import java.util.List; - -public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, - OnChartGestureListener, OnChartValueSelectedListener { - - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart); - - tvX = findViewById(R.id.tvXMax); - tvY = findViewById(R.id.tvYMax); - - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - - mChart = findViewById(R.id.chart1); - mChart.setOnChartGestureListener(this); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - - // no description text - mChart.getDescription().setEnabled(false); - - // enable touch gestures - mChart.setTouchEnabled(true); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - // mChart.setScaleXEnabled(true); - // mChart.setScaleYEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); - - // set an alternative background color - // mChart.setBackgroundColor(Color.GRAY); - - // create a custom MarkerView (extend MarkerView) and specify the layout - // to use for it - MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart - - // x-axis limit line - LimitLine llXAxis = new LimitLine(10f, "Index 10"); - llXAxis.setLineWidth(4f); - llXAxis.enableDashedLine(10f, 10f, 0f); - llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); - llXAxis.setTextSize(10f); - - XAxis xAxis = mChart.getXAxis(); - xAxis.enableGridDashedLine(10f, 10f, 0f); - //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); - //xAxis.addLimitLine(llXAxis); // add x-axis limit line - - - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - LimitLine ll1 = new LimitLine(150f, "Upper Limit"); - ll1.setLineWidth(4f); - ll1.enableDashedLine(10f, 10f, 0f); - ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); - ll1.setTextSize(10f); - ll1.setTypeface(tf); - - LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); - ll2.setLineWidth(4f); - ll2.enableDashedLine(10f, 10f, 0f); - ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); - ll2.setTextSize(10f); - ll2.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.addLimitLine(ll1); - leftAxis.addLimitLine(ll2); - leftAxis.setAxisMaximum(200f); - leftAxis.setAxisMinimum(-50f); - //leftAxis.setYOffset(20f); - leftAxis.enableGridDashedLine(10f, 10f, 0f); - leftAxis.setDrawZeroLine(false); - - // limit lines are drawn behind data (and not on top) - leftAxis.setDrawLimitLinesBehindData(true); - - mChart.getAxisRight().setEnabled(false); - - //mChart.getViewPortHandler().setMaximumScaleY(2f); - //mChart.getViewPortHandler().setMaximumScaleX(2f); - - // add data - setData(45, 100); - -// mChart.setVisibleXRange(20); -// mChart.setVisibleYRange(20f, AxisDependency.LEFT); -// mChart.centerViewTo(20, 50, AxisDependency.LEFT); - - mChart.animateX(2500); - //mChart.invalidate(); - - // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); - - // modify the legend ... - l.setForm(LegendForm.LINE); - - // // dont forget to refresh the drawing - // mChart.invalidate(); - } - - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.line, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); - } - - mChart.invalidate(); - break; - } - case R.id.actionToggleIcons: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setDrawIcons(!set.isDrawIconsEnabled()); - } - - mChart.invalidate(); - break; - } - case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); - } - break; - } - case R.id.actionToggleFilled: { - - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - if (set.isDrawFilledEnabled()) - set.setDrawFilled(false); - else - set.setDrawFilled(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleCircles: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCirclesEnabled()) - set.setDrawCircles(false); - else - set.setDrawCircles(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleCubic: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER - ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.CUBIC_BEZIER); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleStepped: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setMode(set.getMode() == LineDataSet.Mode.STEPPED - ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.STEPPED); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER - ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.HORIZONTAL_BEZIER); - } - mChart.invalidate(); - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000, Easing.EaseInCubic); - break; - } - case R.id.animateXY: { - mChart.animateXY(3000, 3000); - break; - } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - - // redraw - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList values = new ArrayList(); - - for (int i = 0; i < count; i++) { - - float val = (float) (Math.random() * range) + 3; - values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); - } - - LineDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(values); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(values, "DataSet 1"); - - set1.setDrawIcons(false); - - // set the line to be drawn like this "- - - - - -" - set1.enableDashedLine(10f, 5f, 0f); - set1.enableDashedHighlightLine(10f, 5f, 0f); - set1.setColor(Color.BLACK); - set1.setCircleColor(Color.BLACK); - set1.setLineWidth(1f); - set1.setCircleRadius(3f); - set1.setDrawCircleHole(false); - set1.setValueTextSize(9f); - set1.setDrawFilled(true); - set1.setFormLineWidth(1f); - set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); - set1.setFormSize(15.f); - - if (Utils.getSDKInt() >= 18) { - // fill drawable only supported on api level 18 and above - Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); - set1.setFillDrawable(drawable); - } - else { - set1.setFillColor(Color.BLACK); - } - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - - // create a data object with the datasets - LineData data = new LineData(dataSets); - - // set data - mChart.setData(data); - } - } - - @Override - public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); - } - - @Override - public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); - - // un-highlight values after the gesture is finished and no single-tap - if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) - mChart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) - } - - @Override - public void onChartLongPressed(MotionEvent me) { - Log.i("LongPress", "Chart longpressed."); - } - - @Override - public void onChartDoubleTapped(MotionEvent me) { - Log.i("DoubleTap", "Chart double-tapped."); - } - - @Override - public void onChartSingleTapped(MotionEvent me) { - Log.i("SingleTap", "Chart single-tapped."); - } - - @Override - public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY); - } - - @Override - public void onChartScale(MotionEvent me, float scaleX, float scaleY) { - Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); - } - - @Override - public void onChartTranslate(MotionEvent me, float dX, float dY) { - Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); - } - - @Override - public void onValueSelected(Entry e, Highlight h) { - Log.i("Entry selected", e.toString()); - Log.i("LOWHIGH", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); - Log.i("MIN MAX", "xmin: " + mChart.getXChartMin() + ", xmax: " + mChart.getXChartMax() + ", ymin: " + mChart.getYChartMin() + ", ymax: " + mChart.getYChartMax()); - } - - @Override - public void onNothingSelected() { - Log.i("Nothing selected", "Nothing selected."); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java deleted file mode 100644 index e6acf01670..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ /dev/null @@ -1,245 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample; - -import android.os.Bundle; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; - -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import java.util.ArrayList; -import java.util.List; - -public class MultiLineChartActivity extends DemoBase implements OnSeekBarChangeListener, - OnChartValueSelectedListener { - - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart); - - tvX = findViewById(R.id.tvXMax); - tvY = findViewById(R.id.tvYMax); - - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); - mChart.setDrawBorders(false); - - mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setDrawAxisLine(false); - mChart.getAxisRight().setDrawGridLines(false); - mChart.getXAxis().setDrawAxisLine(false); - mChart.getXAxis().setDrawGridLines(false); - - // enable touch gestures - mChart.setTouchEnabled(true); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mSeekBarX.setProgress(20); - mSeekBarY.setProgress(100); - - Legend l = mChart.getLegend(); - l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); - l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); - l.setOrientation(Legend.LegendOrientation.VERTICAL); - l.setDrawInside(false); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.line, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); - } - - mChart.invalidate(); - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); - } - break; - } - case R.id.actionToggleFilled: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - if (set.isDrawFilledEnabled()) - set.setDrawFilled(false); - else - set.setDrawFilled(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleCircles: { - List sets = mChart.getData() - .getDataSets(); - - for (ILineDataSet iSet : sets) { - - LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCirclesEnabled()) - set.setDrawCircles(false); - else - set.setDrawCircles(true); - } - mChart.invalidate(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000); - break; - } - case R.id.animateXY: { - - mChart.animateXY(3000, 3000); - break; - } - } - return true; - } - - private int[] mColors = new int[] { - ColorTemplate.VORDIPLOM_COLORS[0], - ColorTemplate.VORDIPLOM_COLORS[1], - ColorTemplate.VORDIPLOM_COLORS[2] - }; - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - mChart.resetTracking(); - - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList dataSets = new ArrayList(); - - for (int z = 0; z < 3; z++) { - - ArrayList values = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - double val = (Math.random() * mSeekBarY.getProgress()) + 3; - values.add(new Entry(i, (float) val)); - } - - LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); - d.setLineWidth(2.5f); - d.setCircleRadius(4f); - - int color = mColors[z % mColors.length]; - d.setColor(color); - d.setCircleColor(color); - dataSets.add(d); - } - - // make the first DataSet dashed - ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); - ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); - ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); - - LineData data = new LineData(dataSets); - mChart.setData(data); - mChart.invalidate(); - } - - @Override - public void onValueSelected(Entry e, Highlight h) { - Log.i("VAL SELECTED", - "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + h.getDataSetIndex()); - } - - @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java deleted file mode 100644 index a2d4becadc..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ /dev/null @@ -1,124 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; - -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import java.util.ArrayList; - -public class PerformanceLineChart extends DemoBase implements OnSeekBarChangeListener { - - private LineChart mChart; - private SeekBar mSeekBarValues; - private TextView mTvCount; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_performance_linechart); - - mTvCount = findViewById(R.id.tvValueCount); - mSeekBarValues = findViewById(R.id.seekbarValues); - mTvCount.setText("500"); - - mSeekBarValues.setProgress(500); - - mSeekBarValues.setOnSeekBarChangeListener(this); - - mChart = findViewById(R.id.chart1); - mChart.setDrawGridBackground(false); - - // no description text - mChart.getDescription().setEnabled(false); - - // enable touch gestures - mChart.setTouchEnabled(true); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getAxisRight().setEnabled(false); - mChart.getXAxis().setDrawGridLines(true); - mChart.getXAxis().setDrawAxisLine(false); - - // dont forget to refresh the drawing - mChart.invalidate(); - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int count = mSeekBarValues.getProgress() + 1000; - mTvCount.setText("" + count); - - mChart.resetTracking(); - - setData(count, 500f); - - // redraw - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList yVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10); - yVals.add(new Entry(i * 0.001f, val)); - } - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); - - set1.setColor(Color.BLACK); - set1.setLineWidth(0.5f); - set1.setDrawValues(false); - set1.setDrawCircles(false); - set1.setMode(LineDataSet.Mode.LINEAR); - set1.setDrawFilled(false); - - // create a data object with the datasets - LineData data = new LineData(set1); - - // set data - mChart.setData(data); - - // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); - l.setEnabled(false); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java deleted file mode 100644 index 1aeb7f0f0c..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ /dev/null @@ -1,70 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import java.util.ArrayList; - -public class ScrollViewActivity extends DemoBase { - - private BarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_scrollview); - - mChart = findViewById(R.id.chart1); - - mChart.getDescription().setEnabled(false); - - // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setDrawGridLines(false); - - mChart.getAxisLeft().setDrawGridLines(false); - - mChart.getLegend().setEnabled(false); - - setData(10); - mChart.setFitBars(true); - } - - private void setData(int count) { - - ArrayList yVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * count) + 15; - yVals.add(new BarEntry(i, (int) val)); - } - - BarDataSet set = new BarDataSet(yVals, "Data Set"); - set.setColors(ColorTemplate.VORDIPLOM_COLORS); - set.setDrawValues(false); - - BarData data = new BarData(set); - - mChart.setData(data); - mChart.invalidate(); - mChart.animateY(800); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java deleted file mode 100644 index 7becc88c90..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - - -import io.realm.RealmList; -import io.realm.RealmObject; - -/** - * Demo class that encapsulates data stored in realm.io database. - * This class represents data suitable for all chart-types. - */ -public class RealmDemoData extends RealmObject { - - private float yValue; - private float xValue; - - private float open, close, high, low; - - private float bubbleSize; - - private RealmList stackValues; - - private String someStringField; - - /** - * label for pie entries - */ - private String label; - - // ofc there could me more fields here... - - public RealmDemoData() { - - } - - public RealmDemoData(float yValue) { - this.yValue = yValue; - } - - public RealmDemoData(float xValue, float yValue) { - this.xValue = xValue; - this.yValue = yValue; - } - - /** - * Constructor for stacked bars. - * - * @param xValue - * @param stackValues - */ - public RealmDemoData(float xValue, float[] stackValues) { - this.xValue = xValue; - this.stackValues = new RealmList(); - - for (float val : stackValues) { - this.stackValues.add(new RealmFloat(val)); - } - } - - /** - * Constructor for candles. - * - * @param xValue - * @param high - * @param low - * @param open - * @param close - */ - public RealmDemoData(float xValue, float high, float low, float open, float close) { - this.yValue = (high + low) / 2f; - this.high = high; - this.low = low; - this.open = open; - this.close = close; - this.xValue = xValue; - } - - /** - * Constructor for bubbles. - * - * @param xValue - * @param yValue - * @param bubbleSize - */ - public RealmDemoData(float xValue, float yValue, float bubbleSize) { - this.xValue = xValue; - this.yValue = yValue; - this.bubbleSize = bubbleSize; - } - - /** - * Constructor for pie chart. - * - * @param yValue - * @param label - */ - public RealmDemoData(float yValue, String label) { - this.yValue = yValue; - this.label = label; - } - - public float getyValue() { - return yValue; - } - - public void setyValue(float yValue) { - this.yValue = yValue; - } - - public float getxValue() { - return xValue; - } - - public void setxValue(float xValue) { - this.xValue = xValue; - } - - public RealmList getStackValues() { - return stackValues; - } - - public void setStackValues(RealmList stackValues) { - this.stackValues = stackValues; - } - - public float getOpen() { - return open; - } - - public void setOpen(float open) { - this.open = open; - } - - public float getClose() { - return close; - } - - public void setClose(float close) { - this.close = close; - } - - public float getHigh() { - return high; - } - - public void setHigh(float high) { - this.high = high; - } - - public float getLow() { - return low; - } - - public void setLow(float low) { - this.low = low; - } - - public float getBubbleSize() { - return bubbleSize; - } - - public void setBubbleSize(float bubbleSize) { - this.bubbleSize = bubbleSize; - } - - public String getSomeStringField() { - return someStringField; - } - - public void setSomeStringField(String someStringField) { - this.someStringField = someStringField; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } -} \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java deleted file mode 100644 index 15b027b3ff..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import io.realm.RealmObject; - -/** - * Created by Philipp Jahoda on 09/11/15. - */ -public class RealmFloat extends RealmObject { - - private float floatValue; - - public RealmFloat() { - - } - - public RealmFloat(float floatValue) { - this.floatValue = floatValue; - } - - public float getFloatValue() { - return floatValue; - } - - public void setFloatValue(float value) { - this.floatValue = value; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java deleted file mode 100644 index 97bb230ec9..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.notimportant; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class ContentItem { - - String name; - String desc; - boolean isNew = false; - - public ContentItem(String n, String d) { - name = n; - desc = d; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java deleted file mode 100644 index 59b73b1ad7..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ /dev/null @@ -1,50 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample.notimportant; - -import android.graphics.Typeface; -import android.os.Bundle; -import android.renderscript.Type; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; - -import com.xxmassdeveloper.mpchartexample.R; - -/** - * Baseclass of all Activities of the Demo Application. - * - * @author Philipp Jahoda - */ -public abstract class DemoBase extends FragmentActivity { - - protected String[] mMonths = new String[] { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" - }; - - protected String[] mParties = new String[] { - "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H", - "Party I", "Party J", "Party K", "Party L", "Party M", "Party N", "Party O", "Party P", - "Party Q", "Party R", "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", - "Party Y", "Party Z" - }; - - protected Typeface mTfRegular; - protected Typeface mTfLight; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mTfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mTfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); - } - - protected float getRandom(float range, float startsfrom) { - return (float) (Math.random() * range) + startsfrom; - } - - @Override - public void onBackPressed() { - super.onBackPressed(); - overridePendingTransition(R.anim.move_left_in_activity, R.anim.move_right_out_activity); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java deleted file mode 100644 index 5b424e88a5..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.notimportant; - -import android.content.Context; -import android.graphics.Typeface; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import com.xxmassdeveloper.mpchartexample.R; - -import java.util.List; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class MyAdapter extends ArrayAdapter { - - private Typeface mTypeFaceLight; - private Typeface mTypeFaceRegular; - - public MyAdapter(Context context, List objects) { - super(context, 0, objects); - - mTypeFaceLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); - mTypeFaceRegular = Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf"); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - - ContentItem c = getItem(position); - - ViewHolder holder = null; - - if (convertView == null) { - - holder = new ViewHolder(); - - convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, null); - holder.tvName = convertView.findViewById(R.id.tvName); - holder.tvDesc = convertView.findViewById(R.id.tvDesc); - holder.tvNew = convertView.findViewById(R.id.tvNew); - - convertView.setTag(holder); - - } else { - holder = (ViewHolder) convertView.getTag(); - } - - holder.tvNew.setTypeface(mTypeFaceRegular); - holder.tvName.setTypeface(mTypeFaceLight); - holder.tvDesc.setTypeface(mTypeFaceLight); - - holder.tvName.setText(c.name); - holder.tvDesc.setText(c.desc); - - if(c.isNew) - holder.tvNew.setVisibility(View.VISIBLE); - else - holder.tvNew.setVisibility(View.GONE); - - return convertView; - } - - private class ViewHolder { - - TextView tvName, tvDesc; - TextView tvNew; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java deleted file mode 100644 index 9b98f00f92..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ /dev/null @@ -1,202 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; - -import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.PercentFormatter; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 05/11/15. - */ -public abstract class RealmBaseActivity extends DemoBase { - - protected Realm mRealm; - - protected Typeface mTf; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("Realm.io Examples"); - } - - protected void setup(Chart chart) { - - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - // no description text - chart.getDescription().setEnabled(false); - - // enable touch gestures - chart.setTouchEnabled(true); - - if (chart instanceof BarLineChartBase) { - - BarLineChartBase mChart = (BarLineChartBase) chart; - - mChart.setDrawGridBackground(false); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setTypeface(mTf); - leftAxis.setTextSize(8f); - leftAxis.setTextColor(Color.DKGRAY); - leftAxis.setValueFormatter(new PercentFormatter()); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTf); - xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); - xAxis.setTextSize(8f); - xAxis.setTextColor(Color.DKGRAY); - - mChart.getAxisRight().setEnabled(false); - } - } - - protected void styleData(ChartData data) { - data.setValueTypeface(mTf); - data.setValueTextSize(8f); - data.setValueTextColor(Color.DKGRAY); - data.setValueFormatter(new PercentFormatter()); - } - - @Override - protected void onResume() { - super.onResume(); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); - Realm.setDefaultConfiguration(realmConfig); - - mRealm = Realm.getDefaultInstance(); - } - - @Override - protected void onPause() { - super.onPause(); - mRealm.close(); - } - - protected void writeToDB(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 40f + (float) (Math.random() * 60f); - - RealmDemoData d = new RealmDemoData(i, value); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBStack(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float val1 = 34f + (float) (Math.random() * 12.0f); - float val2 = 34f + (float) (Math.random() * 12.0f); - float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - - RealmDemoData d = new RealmDemoData(i, stack); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBCandle(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float mult = 50; - float val = (float) (Math.random() * 40) + mult; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close); - - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBBubble(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 30f + (float) (Math.random() * 100.0); - float size = 15f + (float) (Math.random() * 20.0); - - RealmDemoData d = new RealmDemoData(i, value, size); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBPie() { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - float value1 = 15f + (float) (Math.random() * 8f); - float value2 = 15f + (float) (Math.random() * 8f); - float value3 = 15f + (float) (Math.random() * 8f); - float value4 = 15f + (float) (Math.random() * 8f); - float value5 = 100f - value1 - value2 - value3 - value4; - - float[] values = new float[]{value1, value2, value3, value4, value5}; - String[] labels = new String[]{"iOS", "Android", "WP 10", "BlackBerry", "Other"}; - - for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], labels[i]); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java deleted file mode 100644 index 1e5d5cb8d5..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBar extends RealmBaseActivity { - - private BarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(20); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries - set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - set.setLabel("Realm BarDataSet"); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.setFitBars(true); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java deleted file mode 100644 index ad65a3de18..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BubbleChart; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBubble extends RealmBaseActivity { - - private BubbleChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_bubblechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getXAxis().setDrawGridLines(false); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBBubble(10); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); - set.setLabel("Realm BubbleDataSet"); - set.setColors(ColorTemplate.COLORFUL_COLORS, 110); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BubbleData data = new BubbleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java deleted file mode 100644 index 96fbade855..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Paint; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.CandleStickChart; -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityCandle extends RealmBaseActivity { - - private CandleStickChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_candlechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBCandle(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); - set.setLabel("Realm CandleDataSet"); - set.setShadowColor(Color.DKGRAY); - set.setShadowWidth(0.7f); - set.setDecreasingColor(Color.RED); - set.setDecreasingPaintStyle(Paint.Style.FILL); - set.setIncreasingColor(Color.rgb(122, 242, 84)); - set.setIncreasingPaintStyle(Paint.Style.STROKE); - set.setNeutralColor(Color.BLUE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - CandleData data = new CandleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java deleted file mode 100644 index b5e3345134..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { - - private HorizontalBarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_horizontalbarchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMinimum(0f); - mChart.setDrawValueAboveBar(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBStack(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries - set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); - set.setLabel("Mobile OS distribution"); - set.setStackLabels(new String[]{"iOS", "Android", "Other"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - data.setValueTextColor(Color.WHITE); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java deleted file mode 100644 index 7d2e49fdff..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityLine extends RealmBaseActivity { - - private LineChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMaximum(150f); - mChart.getAxisLeft().setAxisMinimum(0f); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(40); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); - set.setMode(LineDataSet.Mode.CUBIC_BEZIER); - set.setLabel("Realm LineDataSet"); - set.setDrawCircleHole(false); - set.setColor(ColorTemplate.rgb("#FF5722")); - set.setCircleColor(ColorTemplate.rgb("#FF5722")); - set.setLineWidth(1.8f); - set.setCircleRadius(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - LineData data = new LineData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java deleted file mode 100644 index 9fad49c617..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityPie extends RealmBaseActivity { - - private PieChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_piechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.setCenterText(generateCenterSpannableText()); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBPie(); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); - set.setColors(ColorTemplate.VORDIPLOM_COLORS); - set.setLabel("Example market share"); - set.setSliceSpace(2); - - // create a data object with the dataset list - PieData data = new PieData(set); - styleData(data); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(12f); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } - - private SpannableString generateCenterSpannableText() { - - SpannableString s = new SpannableString("Realm.io\nmobile database"); - s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); - s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); - s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); - s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); - s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); - return s; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java deleted file mode 100644 index 02f3ac0492..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityRadar extends RealmBaseActivity { - - private RadarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getYAxis().setEnabled(false); - mChart.getXAxis().setEnabled(false); - mChart.setWebAlpha(180); - mChart.setWebColorInner(Color.DKGRAY); - mChart.setWebColor(Color.GRAY); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(7); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries - set.setLabel("Realm RadarDataSet"); - set.setDrawFilled(true); - set.setColor(ColorTemplate.rgb("#009688")); - set.setFillColor(ColorTemplate.rgb("#009688")); - set.setFillAlpha(130); - set.setLineWidth(2f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - RadarData data = new RadarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java deleted file mode 100644 index 9da64cbf1d..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityScatter extends RealmBaseActivity { - - private ScatterChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_scatterchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(45); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); - set.setLabel("Realm ScatterDataSet"); - set.setScatterShapeSize(9f); - set.setColor(ColorTemplate.rgb("#CDDC39")); - set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - ScatterData data = new ScatterData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java deleted file mode 100644 index 1776a8bd7e..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ListView; - -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; - -import java.util.ArrayList; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_main); - - setTitle("Realm.io Examples"); - - ArrayList objects = new ArrayList(); - - objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); - objects.add(new ContentItem("Bar Chart", - "Creating a BarChart with Realm.io database")); - objects.add(new ContentItem("Horizontal Bar Chart", - "Creating a HorizontalBarChart with Realm.io database")); - objects.add(new ContentItem("Scatter Chart", - "Creating a ScatterChart with Realm.io database")); - objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); - objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); - objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); - objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); - objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); - - MyAdapter adapter = new MyAdapter(this, objects); - - ListView lv = findViewById(R.id.listView1); - lv.setAdapter(adapter); - - lv.setOnItemClickListener(this); - - Realm.init(this); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); - Realm.setDefaultConfiguration(realmConfig); - - Realm realm = Realm.getDefaultInstance(); - realm.beginTransaction(); - realm.deleteAll(); - realm.commitTransaction(); - } - - @Override - public void onItemClick(AdapterView av, View v, int pos, long arg3) { - - Intent i; - - switch (pos) { - case 0: - i = new Intent(this, RealmDatabaseActivityLine.class); - startActivity(i); - break; - case 1: - i = new Intent(this, RealmDatabaseActivityBar.class); - startActivity(i); - break; - case 2: - i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); - startActivity(i); - break; - case 3: - i = new Intent(this, RealmDatabaseActivityScatter.class); - startActivity(i); - break; - case 4: - i = new Intent(this, RealmDatabaseActivityCandle.class); - startActivity(i); - break; - case 5: - i = new Intent(this, RealmDatabaseActivityBubble.class); - startActivity(i); - break; - case 6: - i = new Intent(this, RealmDatabaseActivityPie.class); - startActivity(i); - break; - case 7: - i = new Intent(this, RealmDatabaseActivityRadar.class); - startActivity(i); - break; - case 8: - i = new Intent(this, RealmWikiExample.class); - startActivity(i); - break; - } - - overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realm, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://realm.io/")); - startActivity(i); - - return super.onOptionsItemSelected(item); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java deleted file mode 100644 index f223be6093..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 18/12/15. - */ -public class RealmWikiExample extends RealmBaseActivity { - - private LineChart lineChart; - private BarChart barChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_realm_wiki); - - lineChart = findViewById(R.id.lineChart); - barChart = findViewById(R.id.barChart); - setup(lineChart); - setup(barChart); - - lineChart.setExtraBottomOffset(5f); - barChart.setExtraBottomOffset(5f); - - lineChart.getAxisLeft().setDrawGridLines(false); - lineChart.getXAxis().setDrawGridLines(false); - lineChart.getXAxis().setLabelCount(5); - lineChart.getXAxis().setGranularity(1f); - barChart.getAxisLeft().setDrawGridLines(false); - barChart.getXAxis().setDrawGridLines(false); - barChart.getXAxis().setLabelCount(5); - barChart.getXAxis().setGranularity(1f); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - mRealm.beginTransaction(); - - // write some demo-data into the realm.io database - Score score1 = new Score(100f, 0f, "Peter"); - mRealm.copyToRealm(score1); - Score score2 = new Score(110f, 1f, "Lisa"); - mRealm.copyToRealm(score2); - Score score3 = new Score(130f, 2f, "Dennis"); - mRealm.copyToRealm(score3); - Score score4 = new Score(70f, 3f, "Luke"); - mRealm.copyToRealm(score4); - Score score5 = new Score(80f, 4f, "Sarah"); - mRealm.copyToRealm(score5); - - mRealm.commitTransaction(); - - // add data to the chart - setData(); - } - - private void setData() { - - // LINE-CHART - final RealmResults results = mRealm.where(Score.class).findAll(); - - - IAxisValueFormatter formatter = new IAxisValueFormatter() { - @Override - public String getFormattedValue(float value, AxisBase axis) { - return results.get((int) value).getPlayerName(); - } - }; - - lineChart.getXAxis().setValueFormatter(formatter); - barChart.getXAxis().setValueFormatter(formatter); - - RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); - lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); - lineDataSet.setLabel("Result Scores"); - lineDataSet.setDrawCircleHole(false); - lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setLineWidth(1.8f); - lineDataSet.setCircleRadius(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(lineDataSet); - - LineData lineData = new LineData(dataSets); - styleData(lineData); - - // set data - lineChart.setData(lineData); - lineChart.animateY(1400, Easing.EaseInOutQuart); - - - // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); - barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - barDataSet.setLabel("Realm BarDataSet"); - - ArrayList barDataSets = new ArrayList(); - barDataSets.add(barDataSet); - - BarData barData = new BarData(barDataSets); - styleData(barData); - - barChart.setData(barData); - barChart.setFitBars(true); - barChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java deleted file mode 100644 index 870e371491..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - - -import io.realm.RealmObject; - -/** - * our data object - */ -public class Score extends RealmObject { - - private float totalScore; - - private float scoreNr; - - private String playerName; - - public Score() { - } - - public Score(float totalScore, float scoreNr, String playerName) { - this.scoreNr = scoreNr; - this.playerName = playerName; - this.totalScore = totalScore; - } - - // all getters and setters... - - public float getTotalScore() { - return totalScore; - } - - public void setTotalScore(float totalScore) { - this.totalScore = totalScore; - } - - public float getScoreNr() { - return scoreNr; - } - - public void setScoreNr(float scoreNr) { - this.scoreNr = scoreNr; - } - - public String getPlayerName() { - return playerName; - } - - public void setPlayerName(String playerName) { - this.playerName = playerName; - } -} \ No newline at end of file diff --git a/MPChartExample/src/main/AndroidManifest.xml b/MPChartExample/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..99334e601a --- /dev/null +++ b/MPChartExample/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MPChartExample/assets/OpenSans-Bold.ttf b/MPChartExample/src/main/assets/OpenSans-Bold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Bold.ttf rename to MPChartExample/src/main/assets/OpenSans-Bold.ttf diff --git a/MPChartExample/assets/OpenSans-BoldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-BoldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-BoldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-BoldItalic.ttf diff --git a/MPChartExample/assets/OpenSans-ExtraBold.ttf b/MPChartExample/src/main/assets/OpenSans-ExtraBold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-ExtraBold.ttf rename to MPChartExample/src/main/assets/OpenSans-ExtraBold.ttf diff --git a/MPChartExample/assets/OpenSans-ExtraBoldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-ExtraBoldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-ExtraBoldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-ExtraBoldItalic.ttf diff --git a/MPChartExample/assets/OpenSans-Italic.ttf b/MPChartExample/src/main/assets/OpenSans-Italic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Italic.ttf rename to MPChartExample/src/main/assets/OpenSans-Italic.ttf diff --git a/MPChartExample/assets/OpenSans-Light.ttf b/MPChartExample/src/main/assets/OpenSans-Light.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Light.ttf rename to MPChartExample/src/main/assets/OpenSans-Light.ttf diff --git a/MPChartExample/assets/OpenSans-LightItalic.ttf b/MPChartExample/src/main/assets/OpenSans-LightItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-LightItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-LightItalic.ttf diff --git a/MPChartExample/assets/OpenSans-Regular.ttf b/MPChartExample/src/main/assets/OpenSans-Regular.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Regular.ttf rename to MPChartExample/src/main/assets/OpenSans-Regular.ttf diff --git a/MPChartExample/assets/OpenSans-Semibold.ttf b/MPChartExample/src/main/assets/OpenSans-Semibold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Semibold.ttf rename to MPChartExample/src/main/assets/OpenSans-Semibold.ttf diff --git a/MPChartExample/assets/OpenSans-SemiboldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-SemiboldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-SemiboldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-SemiboldItalic.ttf diff --git a/MPChartExample/assets/cosine.txt b/MPChartExample/src/main/assets/cosine.txt similarity index 100% rename from MPChartExample/assets/cosine.txt rename to MPChartExample/src/main/assets/cosine.txt diff --git a/MPChartExample/assets/hugecosine.txt b/MPChartExample/src/main/assets/hugecosine.txt similarity index 100% rename from MPChartExample/assets/hugecosine.txt rename to MPChartExample/src/main/assets/hugecosine.txt diff --git a/MPChartExample/assets/hugesine.txt b/MPChartExample/src/main/assets/hugesine.txt similarity index 100% rename from MPChartExample/assets/hugesine.txt rename to MPChartExample/src/main/assets/hugesine.txt diff --git a/MPChartExample/assets/n.txt b/MPChartExample/src/main/assets/n.txt similarity index 100% rename from MPChartExample/assets/n.txt rename to MPChartExample/src/main/assets/n.txt diff --git a/MPChartExample/assets/nlogn.txt b/MPChartExample/src/main/assets/nlogn.txt similarity index 100% rename from MPChartExample/assets/nlogn.txt rename to MPChartExample/src/main/assets/nlogn.txt diff --git a/MPChartExample/assets/othersine.txt b/MPChartExample/src/main/assets/othersine.txt similarity index 100% rename from MPChartExample/assets/othersine.txt rename to MPChartExample/src/main/assets/othersine.txt diff --git a/MPChartExample/assets/sine.txt b/MPChartExample/src/main/assets/sine.txt similarity index 100% rename from MPChartExample/assets/sine.txt rename to MPChartExample/src/main/assets/sine.txt diff --git a/MPChartExample/assets/square.txt b/MPChartExample/src/main/assets/square.txt similarity index 100% rename from MPChartExample/assets/square.txt rename to MPChartExample/src/main/assets/square.txt diff --git a/MPChartExample/assets/stacked_bars.txt b/MPChartExample/src/main/assets/stacked_bars.txt similarity index 100% rename from MPChartExample/assets/stacked_bars.txt rename to MPChartExample/src/main/assets/stacked_bars.txt diff --git a/MPChartExample/assets/three.txt b/MPChartExample/src/main/assets/three.txt similarity index 100% rename from MPChartExample/assets/three.txt rename to MPChartExample/src/main/assets/three.txt diff --git a/MPChartExample/ic_launcher-web.png b/MPChartExample/src/main/ic_launcher-web.png similarity index 100% rename from MPChartExample/ic_launcher-web.png rename to MPChartExample/src/main/ic_launcher-web.png diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java new file mode 100644 index 0000000000..69b5a96c42 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -0,0 +1,214 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import androidx.core.content.ContextCompat; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class AnotherBarActivity extends DemoBase implements OnSeekBarChangeListener { + + private BarChart chart; + private SeekBar seekBarX, seekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart); + + setTitle("AnotherBarActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); + + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + + chart.getDescription().setEnabled(false); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + chart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + chart.setPinchZoom(false); + + chart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); + + XAxis xAxis = chart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setDrawGridLines(false); + + chart.getAxisLeft().setDrawGridLines(false); + + // setting data + seekBarX.setProgress(10); + seekBarY.setProgress(100); + + // add a nice and smooth animation + chart.animateY(1500); + + chart.getLegend().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float multi = (seekBarY.getProgress() + 1); + float val = (float) (Math.random() * multi) + multi / 3; + values.add(new BarEntry(i, val)); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "Data Set"); + set1.setColors(ColorTemplate.VORDIPLOM_COLORS); + set1.setDrawValues(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + chart.setData(data); + chart.setFitBars(true); + } + + chart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + menu.removeItem(R.id.actionToggleIcons); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + + for (IDataSet set : chart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + chart.invalidate(); + break; + } + /* + case R.id.actionToggleIcons: { break; } + */ + case R.id.actionToggleHighlight: { + + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); + } + break; + } + case R.id.actionTogglePinch: { + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); + else + chart.setPinchZoom(true); + + chart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : chart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + chart.invalidate(); + break; + } + case R.id.animateX: { + chart.animateX(2000); + break; + } + case R.id.animateY: { + chart.animateY(2000); + break; + } + case R.id.animateXY: { + + chart.animateXY(2000, 2000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "AnotherBarActivity"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java similarity index 56% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index c0e3405625..0d83e3444a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -1,10 +1,13 @@ package com.xxmassdeveloper.mpchartexample; -import android.annotation.SuppressLint; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.RectF; +import android.net.Uri; import android.os.Bundle; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -12,7 +15,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; @@ -31,8 +33,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.model.GradientColor; -import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; @@ -45,8 +46,8 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - protected BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -56,35 +57,40 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("BarChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - // mChart.setDrawYLabels(false); + chart.setDrawGridBackground(false); + // chart.setDrawYLabels(false); - IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart); + IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day xAxis.setLabelCount(7); @@ -92,23 +98,23 @@ protected void onCreate(Bundle savedInstanceState) { IAxisValueFormatter custom = new MyAxisValueFormatter(); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(8, false); leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); leftAxis.setSpaceTop(15f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -117,25 +123,78 @@ protected void onCreate(Bundle savedInstanceState) { l.setFormSize(9f); l.setTextSize(11f); l.setXEntrySpace(4f); - // l.setExtra(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", - // "def", "ghj", "ikl", "mno" }); - // l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", - // "def", "ghj", "ikl", "mno" }); XYMarkerView mv = new XYMarkerView(this, xAxisFormatter); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart - - setData(12, 50); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart // setting data - mSeekBarY.setProgress(50); - mSeekBarX.setProgress(12); + seekBarY.setProgress(50); + seekBarX.setProgress(12); + + // chart.setDrawLegend(false); + } + + private void setData(int count, float range) { + + float start = 1f; + + ArrayList values = new ArrayList<>(); + + for (int i = (int) start; i < start + count; i++) { + float val = (float) (Math.random() * (range + 1)); + + if (Math.random() * 100 < 25) { + values.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); + } else { + values.add(new BarEntry(i, val)); + } + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + + } else { + set1 = new BarDataSet(values, "The year 2017"); + + set1.setDrawIcons(false); + + int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); + int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); + int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); + int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); + int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); + int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); + int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); + int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); + + List gradientFills = new ArrayList<>(); + gradientFills.add(new Fill(startColor1, endColor1)); + gradientFills.add(new Fill(startColor2, endColor2)); + gradientFills.add(new Fill(startColor3, endColor3)); + gradientFills.add(new Fill(startColor4, endColor4)); + gradientFills.add(new Fill(startColor5, endColor5)); + + set1.setFills(gradientFills); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); - // mChart.setDrawLegend(false); + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(0.9f); + + chart.setData(data); + } } @Override @@ -148,68 +207,72 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -219,110 +282,42 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 2)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1 , mSeekBarY.getProgress()); - mChart.invalidate(); + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + protected void saveToGallery() { + saveToGallery(chart, "BarChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } - - private void setData(int count, float range) { - - float start = 1f; - - ArrayList yVals1 = new ArrayList(); - - for (int i = (int) start; i < start + count + 1; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult); - - if (Math.random() * 100 < 25) { - yVals1.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); - } else { - yVals1.add(new BarEntry(i, val)); - } - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "The year 2017"); - - set1.setDrawIcons(false); - -// set1.setColors(ColorTemplate.MATERIAL_COLORS); - - /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); - set1.setGradientColor(startColor, endColor);*/ + public void onStartTrackingTouch(SeekBar seekBar) {} - int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); - int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); - int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); - int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); - int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); - int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); - int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); - int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); - int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); - - List gradientColors = new ArrayList<>(); - gradientColors.add(new GradientColor(startColor1, endColor1)); - gradientColors.add(new GradientColor(startColor2, endColor2)); - gradientColors.add(new GradientColor(startColor3, endColor3)); - gradientColors.add(new GradientColor(startColor4, endColor4)); - gradientColors.add(new GradientColor(startColor5, endColor5)); - - set1.setGradientColors(gradientColors); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setBarWidth(0.9f); - - mChart.setData(data); - } - } + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - protected RectF mOnValueSelectedRectF = new RectF(); + private final RectF onValueSelectedRectF = new RectF(); - @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { if (e == null) return; - RectF bounds = mOnValueSelectedRectF; - mChart.getBarBounds((BarEntry) e, bounds); - MPPointF position = mChart.getPosition(e, AxisDependency.LEFT); + RectF bounds = onValueSelectedRectF; + chart.getBarBounds((BarEntry) e, bounds); + MPPointF position = chart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); Log.i("x-index", - "low: " + mChart.getLowestVisibleX() + ", high: " - + mChart.getHighestVisibleX()); + "low: " + chart.getLowestVisibleX() + ", high: " + + chart.getHighestVisibleX()); MPPointF.recycleInstance(position); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java similarity index 52% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 204dc1fe64..075af0edbc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -29,12 +34,13 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.Locale; public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,51 +50,54 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("BarChartActivityMultiDataset"); + tvX = findViewById(R.id.tvXMax); tvX.setTextSize(10); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setMax(50); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.getDescription().setEnabled(false); -// mChart.setDrawBorders(true); +// chart.setDrawBorders(true); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawBarShadow(false); + chart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(100); + seekBarX.setProgress(10); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(true); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setYOffset(0f); l.setXOffset(10f); l.setYEntrySpace(0f); l.setTextSize(8f); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); xAxis.setValueFormatter(new IAxisValueFormatter() { @@ -98,14 +107,88 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); leftAxis.setSpaceTop(35f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + float groupSpace = 0.08f; + float barSpace = 0.03f; // x4 DataSet + float barWidth = 0.2f; // x4 DataSet + // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" + + int groupCount = seekBarX.getProgress() + 1; + int startYear = 1980; + int endYear = startYear + groupCount; + + tvX.setText(String.format(Locale.ENGLISH, "%d-%d", startYear, endYear)); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + ArrayList values4 = new ArrayList<>(); + + float randomMultiplier = seekBarY.getProgress() * 100000f; + + for (int i = startYear; i < endYear; i++) { + values1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + } + + BarDataSet set1, set2, set3, set4; + + if (chart.getData() != null && chart.getData().getDataSetCount() > 0) { + + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set2 = (BarDataSet) chart.getData().getDataSetByIndex(1); + set3 = (BarDataSet) chart.getData().getDataSetByIndex(2); + set4 = (BarDataSet) chart.getData().getDataSetByIndex(3); + set1.setValues(values1); + set2.setValues(values2); + set3.setValues(values3); + set4.setValues(values4); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + + } else { + // create 4 DataSets + set1 = new BarDataSet(values1, "Company A"); + set1.setColor(Color.rgb(104, 241, 175)); + set2 = new BarDataSet(values2, "Company B"); + set2.setColor(Color.rgb(164, 228, 251)); + set3 = new BarDataSet(values3, "Company C"); + set3.setColor(Color.rgb(242, 247, 158)); + set4 = new BarDataSet(values4, "Company D"); + set4.setColor(Color.rgb(255, 102, 0)); + + BarData data = new BarData(set1, set2, set3, set4); + data.setValueFormatter(new LargeValueFormatter()); + data.setValueTypeface(tfLight); + + chart.setData(data); + } + + // specify the width each bar should have + chart.getBarData().setBarWidth(barWidth); + + // restrict the x-axis range + chart.getXAxis().setAxisMinimum(startYear); + + // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters + chart.getXAxis().setAxisMaximum(startYear + chart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); + chart.groupBars(startYear, groupSpace, barSpace); + chart.invalidate(); } @Override @@ -118,56 +201,65 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } } @@ -175,88 +267,15 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - float groupSpace = 0.08f; - float barSpace = 0.03f; // x4 DataSet - float barWidth = 0.2f; // x4 DataSet - // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" - - int groupCount = mSeekBarX.getProgress() + 1; - int startYear = 1980; - int endYear = startYear + groupCount; - - tvX.setText(startYear + "-" + endYear); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - ArrayList yVals4 = new ArrayList(); - - float randomMultiplier = mSeekBarY.getProgress() * 100000f; - - for (int i = startYear; i < endYear; i++) { - yVals1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - } - - BarDataSet set1, set2, set3, set4; - - if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { - - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set2 = (BarDataSet) mChart.getData().getDataSetByIndex(1); - set3 = (BarDataSet) mChart.getData().getDataSetByIndex(2); - set4 = (BarDataSet) mChart.getData().getDataSetByIndex(3); - set1.setValues(yVals1); - set2.setValues(yVals2); - set3.setValues(yVals3); - set4.setValues(yVals4); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - - } else { - // create 4 DataSets - set1 = new BarDataSet(yVals1, "Company A"); - set1.setColor(Color.rgb(104, 241, 175)); - set2 = new BarDataSet(yVals2, "Company B"); - set2.setColor(Color.rgb(164, 228, 251)); - set3 = new BarDataSet(yVals3, "Company C"); - set3.setColor(Color.rgb(242, 247, 158)); - set4 = new BarDataSet(yVals4, "Company D"); - set4.setColor(Color.rgb(255, 102, 0)); - - BarData data = new BarData(set1, set2, set3, set4); - data.setValueFormatter(new LargeValueFormatter()); - data.setValueTypeface(mTfLight); - - mChart.setData(data); - } - - // specify the width each bar should have - mChart.getBarData().setBarWidth(barWidth); - - // restrict the x-axis range - mChart.getXAxis().setAxisMinimum(startYear); - - // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters - mChart.getXAxis().setAxisMaximum(startYear + mChart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); - mChart.groupBars(startYear, groupSpace, barSpace); - mChart.invalidate(); + protected void saveToGallery() { + saveToGallery(chart, "BarChartActivityMultiDataset"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } + public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java similarity index 55% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 82b039909f..95443e8214 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -1,20 +1,23 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; @@ -29,11 +32,11 @@ public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeListener { - protected BarChart mChart; - private SeekBar mSeekBarX; + private BarChart chart; + private SeekBar seekBarX; private TextView tvX; - private List mSinusData; + private List data; @Override protected void onCreate(Bundle savedInstanceState) { @@ -42,57 +45,59 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart_sinus); - mSinusData = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); + setTitle("BarChartActivitySinus"); + + data = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); tvX = findViewById(R.id.tvValueCount); - mSeekBarX = findViewById(R.id.seekbarValues); + seekBarX = findViewById(R.id.seekbarValues); - mChart = findViewById(R.id.chart1); + chart = findViewById(R.id.chart1); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); + // chart.setDrawBarShadow(true); - // mChart.setDrawXLabels(false); + // chart.setDrawXLabels(false); - mChart.setDrawGridBackground(false); - // mChart.setDrawYLabels(false); + chart.setDrawGridBackground(false); + // chart.setDrawYLabels(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(6, false); leftAxis.setAxisMinimum(-2.5f); leftAxis.setAxisMaximum(2.5f); leftAxis.setGranularityEnabled(true); leftAxis.setGranularity(0.1f); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(6, false); rightAxis.setAxisMinimum(-2.5f); rightAxis.setAxisMaximum(2.5f); rightAxis.setGranularity(0.1f); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarX.setProgress(150); // set data + seekBarX.setOnSeekBarChangeListener(this); + seekBarX.setProgress(150); // set data - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -102,7 +107,37 @@ protected void onCreate(Bundle savedInstanceState) { l.setTextSize(11f); l.setXEntrySpace(4f); - mChart.animateXY(2000, 2000); + chart.animateXY(1500, 1500); + } + + private void setData(int count) { + + ArrayList entries = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + entries.add(data.get(i)); + } + + BarDataSet set; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set = (BarDataSet) chart.getData().getDataSetByIndex(0); + set.setValues(entries); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set = new BarDataSet(entries, "Sinus Function"); + set.setColor(Color.rgb(240, 120, 124)); + } + + BarData data = new BarData(set); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setDrawValues(false); + data.setBarWidth(0.8f); + + chart.setData(data); } @Override @@ -115,61 +150,66 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(1500); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(1500); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(2000, 2000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -179,51 +219,21 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); - setData(mSeekBarX.getProgress()); - mChart.invalidate(); + setData(seekBarX.getProgress()); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + protected void saveToGallery() { + saveToGallery(chart, "BarChartActivitySinus"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count) { - - ArrayList entries = new ArrayList(); - - for (int i = 0; i < count; i++) { - entries.add(mSinusData.get(i)); - } - - BarDataSet set; + public void onStartTrackingTouch(SeekBar seekBar) {} - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set.setValues(entries); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set = new BarDataSet(entries, "Sinus Function"); - set.setColor(Color.rgb(240, 120, 124)); - } - - BarData data = new BarData(set); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setDrawValues(false); - data.setBarWidth(0.8f); + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - mChart.setData(data); - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java similarity index 64% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 7d6bd44896..4fec7dd6ab 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -1,9 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; @@ -26,8 +29,7 @@ public class BarChartPositiveNegative extends DemoBase { - protected BarChart mChart; - private Typeface mTf; + private BarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,27 +38,28 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart_noseekbar); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); - mChart.setExtraTopOffset(-30f); - mChart.setExtraBottomOffset(10f); - mChart.setExtraLeftOffset(70f); - mChart.setExtraRightOffset(70f); + setTitle("BarChartPositiveNegative"); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); + chart.setExtraTopOffset(-30f); + chart.setExtraBottomOffset(10f); + chart.setExtraLeftOffset(70f); + chart.setExtraRightOffset(70f); - mChart.getDescription().setEnabled(false); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); + + chart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTf); + xAxis.setTypeface(tfRegular); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); xAxis.setTextColor(Color.LTGRAY); @@ -65,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); - YAxis left = mChart.getAxisLeft(); + YAxis left = chart.getAxisLeft(); left.setDrawLabels(false); left.setSpaceTop(25f); left.setSpaceBottom(25f); @@ -74,8 +77,8 @@ protected void onCreate(Bundle savedInstanceState) { left.setDrawZeroLine(true); // draw a zero line left.setZeroLineColor(Color.GRAY); left.setZeroLineWidth(0.7f); - mChart.getAxisRight().setEnabled(false); - mChart.getLegend().setEnabled(false); + chart.getAxisRight().setEnabled(false); + chart.getLegend().setEnabled(false); // THIS IS THE ORIGINAL DATA YOU WANT TO PLOT final List data = new ArrayList<>(); @@ -97,8 +100,8 @@ public String getFormattedValue(float value, AxisBase axis) { private void setData(List dataList) { - ArrayList values = new ArrayList(); - List colors = new ArrayList(); + ArrayList values = new ArrayList<>(); + List colors = new ArrayList<>(); int green = Color.rgb(110, 190, 102); int red = Color.rgb(211, 74, 88); @@ -118,12 +121,12 @@ private void setData(List dataList) { BarDataSet set; - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set = (BarDataSet)mChart.getData().getDataSetByIndex(0); + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set = (BarDataSet) chart.getData().getDataSetByIndex(0); set.setValues(values); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); } else { set = new BarDataSet(values, "Values"); set.setColors(colors); @@ -131,12 +134,12 @@ private void setData(List dataList) { BarData data = new BarData(set); data.setValueTextSize(13f); - data.setValueTypeface(mTf); + data.setValueTypeface(tfRegular); data.setValueFormatter(new ValueFormatter()); data.setBarWidth(0.8f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } } @@ -145,11 +148,11 @@ private void setData(List dataList) { */ private class Data { - public String xAxisValue; - public float yValue; - public float xValue; + final String xAxisValue; + final float yValue; + final float xValue; - public Data(float xValue, float yValue, String xAxisValue) { + Data(float xValue, float yValue, String xAxisValue) { this.xAxisValue = xAxisValue; this.yValue = yValue; this.xValue = xValue; @@ -159,9 +162,9 @@ public Data(float xValue, float yValue, String xAxisValue) { private class ValueFormatter implements IValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; - public ValueFormatter() { + ValueFormatter() { mFormat = new DecimalFormat("######.0"); } @@ -170,4 +173,28 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View return mFormat.format(value); } } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java similarity index 52% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index bc1750381e..6288dda2be 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -13,7 +18,6 @@ import com.github.mikephil.charting.charts.BubbleChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BubbleData; @@ -33,10 +37,10 @@ public class BubbleChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BubbleChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BubbleChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -44,52 +48,106 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_bubblechart); + setTitle("BubbleChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); - mChart.setMaxVisibleValueCount(200); - mChart.setPinchZoom(true); + chart.setMaxVisibleValueCount(200); + chart.setPinchZoom(true); - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(50); + seekBarX.setProgress(10); + seekBarY.setProgress(50); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setSpaceTop(30f); yl.setSpaceBottom(30f); yl.setDrawZeroLine(false); - - mChart.getAxisRight().setEnabled(false); - XAxis xl = mChart.getXAxis(); + chart.getAxisRight().setEnabled(false); + + XAxis xl = chart.getXAxis(); xl.setPosition(XAxis.XAxisPosition.BOTTOM); - xl.setTypeface(mTfLight); + xl.setTypeface(tfLight); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + int count = seekBarX.getProgress(); + int range = seekBarY.getProgress(); + + tvX.setText(String.valueOf(count)); + tvY.setText(String.valueOf(range)); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + values1.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range), getResources().getDrawable(R.drawable.star))); + values2.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range), getResources().getDrawable(R.drawable.star))); + values3.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range))); + } + + // create a dataset and give it a type + BubbleDataSet set1 = new BubbleDataSet(values1, "DS 1"); + set1.setDrawIcons(false); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); + set1.setDrawValues(true); + + BubbleDataSet set2 = new BubbleDataSet(values2, "DS 2"); + set2.setDrawIcons(false); + set2.setIconsOffset(new MPPointF(0, 15)); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); + set2.setDrawValues(true); + + BubbleDataSet set3 = new BubbleDataSet(values3, "DS 3"); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); + set3.setDrawValues(true); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + dataSets.add(set2); + dataSets.add(set3); + + // create a data object with the data sets + BubbleData data = new BubbleData(dataSets); + data.setDrawValues(false); + data.setValueTypeface(tfLight); + data.setValueTextSize(8f); + data.setValueTextColor(Color.WHITE); + data.setHighlightCircleWidth(1.5f); + + chart.setData(data); + chart.invalidate(); } @Override @@ -102,56 +160,65 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } } @@ -159,70 +226,8 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int count = mSeekBarX.getProgress(); - int range = mSeekBarY.getProgress(); - - tvX.setText("" + count); - tvY.setText("" + range); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals1.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); - } - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals2.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); - } - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals3.add(new BubbleEntry(i, val, size)); - } - - // create a dataset and give it a type - BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1"); - set1.setDrawIcons(false); - set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); - set1.setDrawValues(true); - - BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2"); - set2.setDrawIcons(false); - set2.setIconsOffset(new MPPointF(0, 15)); - set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); - set2.setDrawValues(true); - - BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3"); - set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); - set3.setDrawValues(true); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - dataSets.add(set2); - dataSets.add(set3); - - // create a data object with the datasets - BubbleData data = new BubbleData(dataSets); - data.setDrawValues(false); - data.setValueTypeface(mTfLight); - data.setValueTextSize(8f); - data.setValueTextColor(Color.WHITE); - data.setHighlightCircleWidth(1.5f); - - mChart.setData(data); - mChart.invalidate(); + protected void saveToGallery() { + saveToGallery(chart, "BubbleChartActivity"); } @Override @@ -233,20 +238,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java similarity index 57% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 54eb768a7b..ecf7167a62 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -1,16 +1,20 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Paint; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.CandleStickChart; import com.github.mikephil.charting.components.XAxis; @@ -28,8 +32,8 @@ public class CandleStickChartActivity extends DemoBase implements OnSeekBarChangeListener { - private CandleStickChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private CandleStickChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -39,48 +43,103 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_candlechart); + setTitle("CandleStickChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); // leftAxis.setEnabled(false); leftAxis.setLabelCount(7, false); leftAxis.setDrawGridLines(false); leftAxis.setDrawAxisLine(false); - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); // rightAxis.setStartAtZero(false); // setting data - mSeekBarX.setProgress(40); - mSeekBarY.setProgress(100); - - mChart.getLegend().setEnabled(false); + seekBarX.setProgress(40); + seekBarY.setProgress(100); + + chart.getLegend().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + progress = (seekBarX.getProgress()); + + tvX.setText(String.valueOf(progress)); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + chart.resetTracking(); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < progress; i++) { + float multi = (seekBarY.getProgress() + 1); + float val = (float) (Math.random() * 40) + multi; + + float high = (float) (Math.random() * 9) + 8f; + float low = (float) (Math.random() * 9) + 8f; + + float open = (float) (Math.random() * 6) + 1f; + float close = (float) (Math.random() * 6) + 1f; + + boolean even = i % 2 == 0; + + values.add(new CandleEntry( + i, val + high, + val - low, + even ? val + open : val - open, + even ? val - close : val + close, + getResources().getDrawable(R.drawable.star) + )); + } + + CandleDataSet set1 = new CandleDataSet(values, "Data Set"); + + set1.setDrawIcons(false); + set1.setAxisDependency(AxisDependency.LEFT); +// set1.setColor(Color.rgb(80, 80, 80)); + set1.setShadowColor(Color.DKGRAY); + set1.setShadowWidth(0.7f); + set1.setDecreasingColor(Color.RED); + set1.setDecreasingPaintStyle(Paint.Style.FILL); + set1.setIncreasingColor(Color.rgb(122, 242, 84)); + set1.setIncreasingPaintStyle(Paint.Style.STROKE); + set1.setNeutralColor(Color.BLUE); + //set1.setHighlightLineWidth(1f); + + CandleData data = new CandleData(set1); + + chart.setData(data); + chart.invalidate(); } @Override @@ -93,69 +152,73 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleMakeShadowSameColorAsCandle: { - for (ICandleDataSet set : mChart.getData().getDataSets()) { - //TODO: set.setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); + for (ICandleDataSet set : chart.getData().getDataSets()) { + ((CandleDataSet) set).setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -163,67 +226,13 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int prog = (mSeekBarX.getProgress() + 1); - - tvX.setText("" + prog); - tvY.setText("" + (mSeekBarY.getProgress())); - - mChart.resetTracking(); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < prog; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val = (float) (Math.random() * 40) + mult; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - yVals1.add(new CandleEntry( - i, val + high, - val - low, - even ? val + open : val - open, - even ? val - close : val + close, - getResources().getDrawable(R.drawable.star) - )); - } - - CandleDataSet set1 = new CandleDataSet(yVals1, "Data Set"); - - set1.setDrawIcons(false); - set1.setAxisDependency(AxisDependency.LEFT); -// set1.setColor(Color.rgb(80, 80, 80)); - set1.setShadowColor(Color.DKGRAY); - set1.setShadowWidth(0.7f); - set1.setDecreasingColor(Color.RED); - set1.setDecreasingPaintStyle(Paint.Style.FILL); - set1.setIncreasingColor(Color.rgb(122, 242, 84)); - set1.setIncreasingPaintStyle(Paint.Style.STROKE); - set1.setNeutralColor(Color.BLUE); - //set1.setHighlightLineWidth(1f); - - CandleData data = new CandleData(set1); - - mChart.setData(data); - mChart.invalidate(); + protected void saveToGallery() { + saveToGallery(chart, "CandleStickChartActivity"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java similarity index 74% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index e4d8fb2e3b..0308b9a891 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -1,7 +1,9 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -38,8 +40,8 @@ public class CombinedChartActivity extends DemoBase { - private CombinedChart mChart; - private final int itemcount = 12; + private CombinedChart chart; + private final int count = 12; @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,41 +50,43 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_combined); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); - mChart.setBackgroundColor(Color.WHITE); - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - mChart.setHighlightFullBarEnabled(false); + setTitle("CombinedChartActivity"); + + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); + chart.setBackgroundColor(Color.WHITE); + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + chart.setHighlightFullBarEnabled(false); // draw bars behind lines - mChart.setDrawOrder(new DrawOrder[]{ + chart.setDrawOrder(new DrawOrder[]{ DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setWordWrapEnabled(true); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); l.setDrawInside(false); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setDrawGridLines(false); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { - return mMonths[(int) value % mMonths.length]; + return months[(int) value % months.length]; } }); @@ -93,21 +97,21 @@ public String getFormattedValue(float value, AxisBase axis) { data.setData(generateBubbleData()); data.setData(generateScatterData()); data.setData(generateCandleData()); - data.setValueTypeface(mTfLight); + data.setValueTypeface(tfLight); xAxis.setAxisMaximum(data.getXMax() + 0.25f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } private LineData generateLineData() { LineData d = new LineData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) + for (int index = 0; index < count; index++) entries.add(new Entry(index + 0.5f, getRandom(15, 5))); LineDataSet set = new LineDataSet(entries, "Line DataSet"); @@ -129,10 +133,10 @@ private LineData generateLineData() { private BarData generateBarData() { - ArrayList entries1 = new ArrayList(); - ArrayList entries2 = new ArrayList(); + ArrayList entries1 = new ArrayList<>(); + ArrayList entries2 = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) { + for (int index = 0; index < count; index++) { entries1.add(new BarEntry(0, getRandom(25, 25))); // stacked @@ -147,7 +151,7 @@ private BarData generateBarData() { BarDataSet set2 = new BarDataSet(entries2, ""); set2.setStackLabels(new String[]{"Stack 1", "Stack 2"}); - set2.setColors(new int[]{Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)}); + set2.setColors(Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)); set2.setValueTextColor(Color.rgb(61, 165, 255)); set2.setValueTextSize(10f); set2.setAxisDependency(YAxis.AxisDependency.LEFT); @@ -166,13 +170,13 @@ private BarData generateBarData() { return d; } - protected ScatterData generateScatterData() { + private ScatterData generateScatterData() { ScatterData d = new ScatterData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (float index = 0; index < itemcount; index += 0.5f) + for (float index = 0; index < count; index += 0.5f) entries.add(new Entry(index + 0.25f, getRandom(10, 55))); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); @@ -185,13 +189,13 @@ protected ScatterData generateScatterData() { return d; } - protected CandleData generateCandleData() { + private CandleData generateCandleData() { CandleData d = new CandleData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index += 2) + for (int index = 0; index < count; index += 2) entries.add(new CandleEntry(index + 1f, 90, 70, 85, 75f)); CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); @@ -205,13 +209,13 @@ protected CandleData generateCandleData() { return d; } - protected BubbleData generateBubbleData() { + private BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) { + for (int index = 0; index < count; index++) { float y = getRandom(10, 105); float size = getRandom(100, 105); entries.add(new BubbleEntry(index + 0.5f, y, size)); @@ -237,34 +241,42 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleLineValues: { - for (IDataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : chart.getData().getDataSets()) { if (set instanceof LineDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleBarValues: { - for (IDataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : chart.getData().getDataSets()) { if (set instanceof BarDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionRemoveDataSet: { - - int rnd = (int) getRandom(mChart.getData().getDataSetCount(), 0); - mChart.getData().removeDataSet(mChart.getData().getDataSetByIndex(rnd)); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + int rnd = (int) getRandom(chart.getData().getDataSetCount(), 0); + chart.getData().removeDataSet(chart.getData().getDataSetByIndex(rnd)); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + chart.invalidate(); break; } } return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java similarity index 59% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 4a278c398e..996e088f43 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -1,15 +1,19 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.XAxis; @@ -28,8 +32,8 @@ public class CubicLineChartActivity extends DemoBase implements OnSeekBarChangeListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -39,60 +43,114 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("CubicLineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart = findViewById(R.id.chart1); - mChart.setViewPortOffsets(0, 0, 0, 0); - mChart.setBackgroundColor(Color.rgb(104, 241, 175)); + chart = findViewById(R.id.chart1); + chart.setViewPortOffsets(0, 0, 0, 0); + chart.setBackgroundColor(Color.rgb(104, 241, 175)); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - mChart.setMaxHighlightDistance(300); - - XAxis x = mChart.getXAxis(); + chart.setDrawGridBackground(false); + chart.setMaxHighlightDistance(300); + + XAxis x = chart.getXAxis(); x.setEnabled(false); - - YAxis y = mChart.getAxisLeft(); - y.setTypeface(mTfLight); + + YAxis y = chart.getAxisLeft(); + y.setTypeface(tfLight); y.setLabelCount(6, false); y.setTextColor(Color.WHITE); y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); y.setDrawGridLines(false); y.setAxisLineColor(Color.WHITE); - - mChart.getAxisRight().setEnabled(false); + + chart.getAxisRight().setEnabled(false); // add data - setData(45, 100); - - mChart.getLegend().setEnabled(false); - - mChart.animateXY(2000, 2000); - - // dont forget to refresh the drawing - mChart.invalidate(); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + + // lower max, as cubic runs significantly slower than linear + seekBarX.setMax(700); + + seekBarX.setProgress(45); + seekBarY.setProgress(100); + + chart.getLegend().setEnabled(false); + + chart.animateXY(2000, 2000); + + // don't forget to refresh the drawing + chart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * (range + 1)) + 20; + values.add(new Entry(i, val)); + } + + LineDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values, "DataSet 1"); + + set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); + set1.setCubicIntensity(0.2f); + set1.setDrawFilled(true); + set1.setDrawCircles(false); + set1.setLineWidth(1.8f); + set1.setCircleRadius(4f); + set1.setCircleColor(Color.WHITE); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setColor(Color.WHITE); + set1.setFillColor(Color.WHITE); + set1.setFillAlpha(100); + set1.setDrawHorizontalHighlightIndicator(false); + set1.setFillFormatter(new IFillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return chart.getAxisLeft().getAxisMinimum(); + } + }); + + // create a data object with the data sets + LineData data = new LineData(set1); + data.setValueTypeface(tfLight); + data.setValueTextSize(9f); + data.setDrawValues(false); + + // set data + chart.setData(data); + } } @Override @@ -105,23 +163,29 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -133,11 +197,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -148,11 +212,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -162,11 +226,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -176,11 +240,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -190,44 +254,41 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.HORIZONTAL_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -237,78 +298,23 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + protected void saveToGallery() { + saveToGallery(chart, "CubicLineChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList yVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 20;// + (float) - // ((mult * - // 0.1) / 10); - yVals.add(new Entry(i, val)); - } - - LineDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(yVals, "DataSet 1"); - - set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); - set1.setCubicIntensity(0.2f); - //set1.setDrawFilled(true); - set1.setDrawCircles(false); - set1.setLineWidth(1.8f); - set1.setCircleRadius(4f); - set1.setCircleColor(Color.WHITE); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setColor(Color.WHITE); - set1.setFillColor(Color.WHITE); - set1.setFillAlpha(100); - set1.setDrawHorizontalHighlightIndicator(false); - set1.setFillFormatter(new IFillFormatter() { - @Override - public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return -10; - } - }); + public void onStartTrackingTouch(SeekBar seekBar) {} - // create a data object with the datasets - LineData data = new LineData(set1); - data.setValueTypeface(mTfLight); - data.setValueTextSize(9f); - data.setDrawValues(false); - - // set data - mChart.setData(data); - } - } + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java similarity index 65% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index d3551068c1..7a32e5329c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -1,8 +1,10 @@ - +// TODO: Finish and add to main activity list package com.xxmassdeveloper.mpchartexample; -import android.graphics.Typeface; +import android.Manifest; +import android.content.pm.PackageManager; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -28,13 +30,13 @@ /** * This Activity demonstrates drawing into the Chart with the finger. Both line, * bar and scatter charts can be used for drawing. - * + * * @author Philipp Jahoda */ public class DrawChartActivity extends DemoBase implements OnChartValueSelectedListener, OnDrawListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -43,49 +45,49 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_draw_chart); - mChart = findViewById(R.id.chart1); + setTitle("DrawChartActivity"); + + chart = findViewById(R.id.chart1); // listener for selecting and drawing - mChart.setOnChartValueSelectedListener(this); - mChart.setOnDrawListener(this); + chart.setOnChartValueSelectedListener(this); + chart.setOnDrawListener(this); - // if disabled, drawn datasets with the finger will not be automatically + // if disabled, drawn data sets with the finger will not be automatically // finished - // mChart.setAutoFinish(true); - mChart.setDrawGridBackground(false); + // chart.setAutoFinish(true); + chart.setDrawGridBackground(false); // add dummy-data to the chart initWithDummyData(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfRegular); xl.setAvoidFirstLastClipping(true); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfRegular); - mChart.getLegend().setEnabled(false); + chart.getLegend().setEnabled(false); - // mChart.setYRange(-40f, 40f, true); + // chart.setYRange(-40f, 40f, true); // call this to reset the changed y-range - // mChart.resetYRange(true); + // chart.resetYRange(true); } private void initWithDummyData() { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); // create a dataset and give it a type (0) - LineDataSet set1 = new LineDataSet(yVals, "DataSet"); + LineDataSet set1 = new LineDataSet(values, "DataSet"); set1.setLineWidth(3f); set1.setCircleRadius(5f); - // create a data object with the datasets + // create a data object with the data sets LineData data = new LineData(set1); - mChart.setData(data); + chart.setData(data); } @Override @@ -99,7 +101,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -108,39 +110,47 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } return true; } + @Override + protected void saveToGallery() { + saveToGallery(chart, "DrawChartActivity"); + } + @Override public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", @@ -164,7 +174,7 @@ public void onDrawFinished(DataSet dataSet) { Log.i(Chart.LOG_TAG, "DataSet drawn. " + dataSet.toSimpleString()); // prepare the legend again - mChart.getLegendRenderer().computeLegend(mChart.getData()); + chart.getLegendRenderer().computeLegend(chart.getData()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java similarity index 57% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index f8f64c374f..84de449283 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; @@ -23,7 +28,7 @@ public class DynamicalAddingActivity extends DemoBase implements OnChartValueSelectedListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -32,24 +37,30 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); + setTitle("DynamicalAddingActivity"); - // add an empty data object - mChart.setData(new LineData()); -// mChart.getXAxis().setDrawLabels(false); -// mChart.getXAxis().setDrawGridLines(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); + chart.setNoDataText("No chart data available. Use the menu to add entries and data sets!"); - mChart.invalidate(); +// chart.getXAxis().setDrawLabels(false); +// chart.getXAxis().setDrawGridLines(false); + + chart.invalidate(); } - int[] mColors = ColorTemplate.VORDIPLOM_COLORS; + private final int[] colors = ColorTemplate.VORDIPLOM_COLORS; private void addEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); + + if (data == null) { + data = new LineData(); + chart.setData(data); + } ILineDataSet set = data.getDataSetByIndex(0); // set.addEntry(...); // can be called as well @@ -61,25 +72,26 @@ private void addEntry() { // choose a random dataSet int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); - float yValue = (float) (Math.random() * 10) + 50f; + ILineDataSet randomSet = data.getDataSetByIndex(randomDataSetIndex); + float value = (float) (Math.random() * 50) + 50f * (randomDataSetIndex + 1); - data.addEntry(new Entry(data.getDataSetByIndex(randomDataSetIndex).getEntryCount(), yValue), randomDataSetIndex); + data.addEntry(new Entry(randomSet.getEntryCount(), value), randomDataSetIndex); data.notifyDataChanged(); // let the chart know it's data has changed - mChart.notifyDataSetChanged(); + chart.notifyDataSetChanged(); - mChart.setVisibleXRangeMaximum(6); - //mChart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); -// + chart.setVisibleXRangeMaximum(6); + //chart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); +// // // this automatically refreshes the chart (calls invalidate()) - mChart.moveViewTo(data.getEntryCount() - 7, 50f, AxisDependency.LEFT); + chart.moveViewTo(data.getEntryCount() - 7, 50f, AxisDependency.LEFT); } private void removeLastEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { @@ -93,31 +105,33 @@ private void removeLastEntry() { // or remove by index // mData.removeEntryByXValue(xIndex, dataSetIndex); data.notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } } private void addDataSet() { - LineData data = mChart.getData(); - - if (data != null) { + LineData data = chart.getData(); + if (data == null) { + chart.setData(new LineData()); + } else { int count = (data.getDataSetCount() + 1); + int amount = data.getDataSetByIndex(0).getEntryCount(); - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); - for (int i = 0; i < data.getEntryCount(); i++) { - yVals.add(new Entry(i, (float) (Math.random() * 50f) + 50f * count)); + for (int i = 0; i < amount; i++) { + values.add(new Entry(i, (float) (Math.random() * 50f) + 50f * count)); } - LineDataSet set = new LineDataSet(yVals, "DataSet " + count); + LineDataSet set = new LineDataSet(values, "DataSet " + count); set.setLineWidth(2.5f); set.setCircleRadius(4.5f); - int color = mColors[count % mColors.length]; + int color = colors[count % colors.length]; set.setColor(color); set.setCircleColor(color); @@ -127,33 +141,45 @@ private void addDataSet() { data.addDataSet(set); data.notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } private void removeDataSet() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { data.removeDataSet(data.getDataSetByIndex(data.getDataSetCount() - 1)); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } + private LineDataSet createSet() { + + LineDataSet set = new LineDataSet(null, "DataSet 1"); + set.setLineWidth(2.5f); + set.setCircleRadius(4.5f); + set.setColor(Color.rgb(240, 99, 99)); + set.setCircleColor(Color.rgb(240, 99, 99)); + set.setHighLightColor(Color.rgb(190, 190, 190)); + set.setAxisDependency(AxisDependency.LEFT); + set.setValueTextSize(10f); + + return set; + } + @Override public void onValueSelected(Entry e, Highlight h) { Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } @Override - public void onNothingSelected() { - - } + public void onNothingSelected() {} @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -165,47 +191,52 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.actionAddEntry: + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java")); + startActivity(i); + break; + } + case R.id.actionAddEntry: { addEntry(); Toast.makeText(this, "Entry added!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionRemoveEntry: + } + case R.id.actionRemoveEntry: { removeLastEntry(); Toast.makeText(this, "Entry removed!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionAddDataSet: + } + case R.id.actionAddDataSet: { addDataSet(); Toast.makeText(this, "DataSet added!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionRemoveDataSet: + } + case R.id.actionRemoveDataSet: { removeDataSet(); Toast.makeText(this, "DataSet removed!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionAddEmptyLineData: - mChart.setData(new LineData()); - mChart.invalidate(); - Toast.makeText(this, "Empty data added!", Toast.LENGTH_SHORT).show(); - break; - case R.id.actionClear: - mChart.clear(); + } + case R.id.actionClear: { + chart.clear(); Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } } return true; } - private LineDataSet createSet() { - - LineDataSet set = new LineDataSet(null, "DataSet 1"); - set.setLineWidth(2.5f); - set.setCircleRadius(4.5f); - set.setColor(Color.rgb(240, 99, 99)); - set.setCircleColor(Color.rgb(240, 99, 99)); - set.setHighLightColor(Color.rgb(190, 190, 190)); - set.setAxisDependency(AxisDependency.LEFT); - set.setValueTextSize(10f); - - return set; + @Override + protected void saveToGallery() { + saveToGallery(chart, "DynamicalAddingActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java similarity index 50% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index 9109d5d29c..e821a04969 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -1,8 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.LineChart; @@ -19,10 +23,19 @@ import java.util.ArrayList; +/** + * This works by inverting the background and desired "fill" color. First, we draw the fill color + * that we want between the lines as the actual background of the chart. Then, we fill the area + * above the highest line and the area under the lowest line with the desired background color. + * + * This method makes it look like we filled the area between the lines, but really we are filling + * the area OUTSIDE the lines! + */ +@SuppressWarnings("SameParameterValue") public class FilledLineActivity extends DemoBase { - private LineChart mChart; - private int mFillColor = Color.argb(150, 51, 181, 229); + private LineChart chart; + private final int fillColor = Color.argb(150, 51, 181, 229); @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,73 +44,71 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); - mChart.setGridBackgroundColor(mFillColor); - mChart.setDrawGridBackground(true); + setTitle("FilledLineActivity"); - mChart.setDrawBorders(true); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); + chart.setGridBackgroundColor(fillColor); + chart.setDrawGridBackground(true); + + chart.setDrawBorders(true); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setEnabled(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setAxisMaximum(900f); leftAxis.setAxisMinimum(-250f); leftAxis.setDrawAxisLine(false); leftAxis.setDrawZeroLine(false); leftAxis.setDrawGridLines(false); - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); // add data setData(100, 60); - mChart.invalidate(); + chart.invalidate(); } private void setData(int count, float range) { - ArrayList yVals1 = new ArrayList(); + ArrayList values1 = new ArrayList<>(); for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range) + 50;// + (float) - // ((mult * - // 0.1) / 10); - yVals1.add(new Entry(i, val)); + float val = (float) (Math.random() * range) + 50; + values1.add(new Entry(i, val)); } - ArrayList yVals2 = new ArrayList(); + ArrayList values2 = new ArrayList<>(); for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range) + 450;// + (float) - // ((mult * - // 0.1) / 10); - yVals2.add(new Entry(i, val)); + float val = (float) (Math.random() * range) + 450; + values2.add(new Entry(i, val)); } LineDataSet set1, set2; - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); - set1.setValues(yVals1); - set2.setValues(yVals2); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set2 = (LineDataSet) chart.getData().getDataSetByIndex(1); + set1.setValues(values1); + set2.setValues(values2); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); } else { // create a dataset and give it a type - set1 = new LineDataSet(yVals1, "DataSet 1"); + set1 = new LineDataSet(values1, "DataSet 1"); set1.setAxisDependency(YAxis.AxisDependency.LEFT); set1.setColor(Color.rgb(255, 241, 46)); @@ -112,12 +123,14 @@ private void setData(int count, float range) { set1.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return mChart.getAxisLeft().getAxisMinimum(); + // change the return value here to better understand the effect + // return 0; + return chart.getAxisLeft().getAxisMinimum(); } }); // create a dataset and give it a type - set2 = new LineDataSet(yVals2, "DataSet 2"); + set2 = new LineDataSet(values2, "DataSet 2"); set2.setAxisDependency(YAxis.AxisDependency.LEFT); set2.setColor(Color.rgb(255, 241, 46)); set2.setDrawCircles(false); @@ -131,20 +144,46 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv set2.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return mChart.getAxisLeft().getAxisMaximum(); + // change the return value here to better understand the effect + // return 600; + return chart.getAxisLeft().getAxisMaximum(); } }); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets dataSets.add(set2); - // create a data object with the datasets + // create a data object with the data sets LineData data = new LineData(dataSets); data.setDrawValues(false); // set data - mChart.setData(data); + chart.setData(data); } } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java similarity index 55% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 38a228b322..ed2adcc960 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -1,22 +1,24 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Point; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; -import android.view.Display; +import android.util.DisplayMetrics; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import android.widget.RelativeLayout; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -26,9 +28,10 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class HalfPieChartActivity extends DemoBase { - private PieChart mChart; + private PieChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -37,40 +40,42 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart_half); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); + setTitle("HalfPieChartActivity"); + + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); moveOffScreen(); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); - mChart.setCenterTextTypeface(mTfLight); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(tfLight); + chart.setCenterText(generateCenterSpannableText()); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationEnabled(false); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(false); + chart.setHighlightPerTapEnabled(true); - mChart.setMaxAngle(180f); // HALF CHART - mChart.setRotationAngle(180f); - mChart.setCenterTextOffset(0, -20); + chart.setMaxAngle(180f); // HALF CHART + chart.setRotationAngle(180f); + chart.setCenterTextOffset(0, -20); setData(4, 100); - mChart.animateY(1400, Easing.EaseInOutQuad); + chart.animateY(1400, Easing.EaseInOutQuad); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -80,17 +85,17 @@ protected void onCreate(Bundle savedInstanceState) { l.setYOffset(0f); // entry label styling - mChart.setEntryLabelColor(Color.WHITE); - mChart.setEntryLabelTypeface(mTfRegular); - mChart.setEntryLabelTextSize(12f); + chart.setEntryLabelColor(Color.WHITE); + chart.setEntryLabelTypeface(tfRegular); + chart.setEntryLabelTextSize(12f); } private void setData(int count, float range) { - ArrayList values = new ArrayList(); + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { - values.add(new PieEntry((float) ((Math.random() * range) + range / 5), mParties[i % mParties.length])); + values.add(new PieEntry((float) ((Math.random() * range) + range / 5), parties[i % parties.length])); } PieDataSet dataSet = new PieDataSet(values, "Election Results"); @@ -104,10 +109,10 @@ private void setData(int count, float range) { data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); - data.setValueTypeface(mTfLight); - mChart.setData(data); + data.setValueTypeface(tfLight); + chart.setData(data); - mChart.invalidate(); + chart.invalidate(); } private SpannableString generateCenterSpannableText() { @@ -124,14 +129,40 @@ private SpannableString generateCenterSpannableText() { private void moveOffScreen() { - Display display = getWindowManager().getDefaultDisplay(); - int height = display.getHeight(); // deprecated + DisplayMetrics displayMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + + int height = displayMetrics.heightPixels; int offset = (int)(height * 0.65); /* percent to move */ RelativeLayout.LayoutParams rlParams = - (RelativeLayout.LayoutParams)mChart.getLayoutParams(); + (RelativeLayout.LayoutParams) chart.getLayoutParams(); rlParams.setMargins(0, 0, 0, -offset); - mChart.setLayoutParams(rlParams); + chart.setLayoutParams(rlParams); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java")); + startActivity(i); + break; + } + } + + return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java similarity index 55% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 95e138aade..27f7f29627 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -1,9 +1,13 @@ package com.xxmassdeveloper.mpchartexample; -import android.annotation.SuppressLint; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.RectF; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -11,11 +15,9 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -35,8 +37,8 @@ public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - protected HorizontalBarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private HorizontalBarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -46,67 +48,68 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_horizontalbarchart); + setTitle("HorizontalBarChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - // mChart.setHighlightEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); - mChart.setDrawBarShadow(false); + chart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); + // chart.setDrawBarShadow(true); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xl = mChart.getXAxis(); + XAxis xl = chart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(mTfLight); + xl.setTypeface(tfLight); xl.setDrawAxisLine(true); xl.setDrawGridLines(false); xl.setGranularity(10f); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); - YAxis yr = mChart.getAxisRight(); - yr.setTypeface(mTfLight); + YAxis yr = chart.getAxisRight(); + yr.setTypeface(tfLight); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); yr.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yr.setInverted(true); - setData(12, 50); - mChart.setFitBars(true); - mChart.animateY(2500); + chart.setFitBars(true); + chart.animateY(2500); // setting data - mSeekBarY.setProgress(50); - mSeekBarX.setProgress(12); + seekBarY.setProgress(50); + seekBarX.setProgress(12); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -115,6 +118,42 @@ protected void onCreate(Bundle savedInstanceState) { l.setXEntrySpace(4f); } + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + values.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(barWidth); + chart.setData(data); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); @@ -125,80 +164,80 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); + iSet.setDrawValues(!iSet.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawIcons(!set.isDrawIconsEnabled()); + iSet.setDrawIcons(!iSet.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -208,64 +247,27 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - mChart.setFitBars(true); - mChart.invalidate(); + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.setFitBars(true); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + protected void saveToGallery() { + saveToGallery(chart, "HorizontalBarChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { + public void onStartTrackingTouch(SeekBar seekBar) {} - float barWidth = 9f; - float spaceForBar = 10f; - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - yVals1.add(new BarEntry(i * spaceForBar, val, - getResources().getDrawable(R.drawable.star))); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "DataSet 1"); - - set1.setDrawIcons(false); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - BarData data = new BarData(dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setBarWidth(barWidth); - mChart.setData(data); - } - } + private final RectF mOnValueSelectedRectF = new RectF(); - protected RectF mOnValueSelectedRectF = new RectF(); - @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { @@ -273,9 +275,9 @@ public void onValueSelected(Entry e, Highlight h) { return; RectF bounds = mOnValueSelectedRectF; - mChart.getBarBounds((BarEntry) e, bounds); + chart.getBarBounds((BarEntry) e, bounds); - MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); Log.i("bounds", bounds.toString()); @@ -285,6 +287,5 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - }; + public void onNothingSelected() {} } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java new file mode 100644 index 0000000000..86d578cc43 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java @@ -0,0 +1,292 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.RectF; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.core.content.ContextCompat; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.MPPointF; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.List; + +public class HorizontalBarNegativeChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private HorizontalBarChart chart; + private SeekBar seekBarX, seekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart); + + setTitle("HorizontalBarChartActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); + + chart.setDrawBarShadow(false); + + chart.setDrawValueAboveBar(true); + + chart.getDescription().setEnabled(false); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + chart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + chart.setPinchZoom(false); + + // draw shadows for each bar that show the maximum value + // chart.setDrawBarShadow(true); + + chart.setDrawGridBackground(false); + + XAxis xl = chart.getXAxis(); + xl.setPosition(XAxisPosition.BOTTOM); + xl.setTypeface(tfLight); + xl.setDrawAxisLine(true); + xl.setDrawGridLines(false); + xl.setGranularity(10f); + + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); + yl.setDrawAxisLine(true); + yl.setDrawGridLines(true); +// yl.setInverted(true); + + YAxis yr = chart.getAxisRight(); + yr.setTypeface(tfLight); + yr.setDrawAxisLine(true); + yr.setDrawGridLines(false); +// yr.setInverted(true); + + chart.setFitBars(true); + chart.animateY(2500); + + // setting data + seekBarY.setProgress(50); + seekBarX.setProgress(12); + + Legend l = chart.getLegend(); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); + l.setFormSize(8f); + l.setXEntrySpace(4f); + } + + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range - range / 2); + values.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(barWidth); + chart.setData(data); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + List sets = chart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + iSet.setDrawValues(!iSet.isDrawValuesEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleIcons: { + List sets = chart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + iSet.setDrawIcons(!iSet.isDrawIconsEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); + } + break; + } + case R.id.actionTogglePinch: { + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); + else + chart.setPinchZoom(true); + + chart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : chart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + chart.invalidate(); + break; + } + case R.id.animateX: { + chart.animateX(2000); + break; + } + case R.id.animateY: { + chart.animateY(2000); + break; + } + case R.id.animateXY: { + chart.animateXY(2000, 2000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.setFitBars(true); + chart.invalidate(); + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "HorizontalBarChartActivity"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + + private final RectF mOnValueSelectedRectF = new RectF(); + + @Override + public void onValueSelected(Entry e, Highlight h) { + + if (e == null) + return; + + RectF bounds = mOnValueSelectedRectF; + chart.getBarBounds((BarEntry) e, bounds); + + MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex()) + .getAxisDependency()); + + Log.i("bounds", bounds.toString()); + Log.i("position", position.toString()); + + MPPointF.recycleInstance(position); + } + + @Override + public void onNothingSelected() {} +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java similarity index 62% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 4ad4e691ef..08983710f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -9,7 +14,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -33,8 +37,8 @@ public class InvertedLineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,72 +48,98 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("InvertedLineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - // mChart.setBackgroundColor(Color.GRAY); + // chart.setBackgroundColor(Color.GRAY); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart - - XAxis xl = mChart.getXAxis(); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart + + XAxis xl = chart.getXAxis(); xl.setAvoidFirstLastClipping(true); xl.setAxisMinimum(0f); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setInverted(true); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); // add data - setData(25, 50); + seekBarX.setProgress(25); + seekBarY.setProgress(50); // // restrain the maximum scale-out factor - // mChart.setScaleMinima(3f, 3f); + // chart.setScaleMinima(3f, 3f); // // // center the view to a specific position inside the chart - // mChart.centerViewPort(10, 50); + // chart.centerViewPort(10, 50); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - // dont forget to refresh the drawing - mChart.invalidate(); + // don't forget to refresh the drawing + chart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList entries = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float xVal = (float) (Math.random() * range); + float yVal = (float) (Math.random() * range); + entries.add(new Entry(xVal, yVal)); + } + + // sort by x-value + Collections.sort(entries, new EntryXComparator()); + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(entries, "DataSet 1"); + + set1.setLineWidth(1.5f); + set1.setCircleRadius(4f); + + // create a data object with the data sets + LineData data = new LineData(set1); + + // set data + chart.setData(data); } @Override @@ -122,8 +152,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -132,19 +168,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -155,11 +191,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -170,45 +206,42 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -218,13 +251,18 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "InvertedLineChartActivity"); } @Override @@ -235,46 +273,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList entries = new ArrayList(); - - for (int i = 0; i < count; i++) { - float xVal = (float) (Math.random() * range); - float yVal = (float) (Math.random() * range); - entries.add(new Entry(xVal, yVal)); - } - - // sort by x-value - Collections.sort(entries, new EntryXComparator()); - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(entries, "DataSet 1"); - - set1.setLineWidth(1.5f); - set1.setCircleRadius(4f); - - // create a data object with the datasets - LineData data = new LineData(set1); - - // set data - mChart.setData(data); - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java new file mode 100644 index 0000000000..dd43b056eb --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -0,0 +1,454 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Bundle; +import androidx.core.content.ContextCompat; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.IFillFormatter; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Utils; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Example of a heavily customized {@link LineChart} with limit lines, custom line shapes, etc. + * + * @since 1.7.4 + * @version 3.1.0 + */ +public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private LineChart chart; + private SeekBar seekBarX, seekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart); + + setTitle("LineChartActivity1"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); + + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setMax(180); + seekBarY.setOnSeekBarChangeListener(this); + + + { // // Chart Style // // + chart = findViewById(R.id.chart1); + + // background color + chart.setBackgroundColor(Color.WHITE); + + // disable description text + chart.getDescription().setEnabled(false); + + // enable touch gestures + chart.setTouchEnabled(true); + + // set listeners + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); + + // create marker to display box when values are selected + MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); + + // Set the marker to the chart + mv.setChartView(chart); + chart.setMarker(mv); + + // enable scaling and dragging + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + // chart.setScaleXEnabled(true); + // chart.setScaleYEnabled(true); + + // force pinch zoom along both axis + chart.setPinchZoom(true); + } + + XAxis xAxis; + { // // X-Axis Style // // + xAxis = chart.getXAxis(); + + // vertical grid lines + xAxis.enableGridDashedLine(10f, 10f, 0f); + } + + YAxis yAxis; + { // // Y-Axis Style // // + yAxis = chart.getAxisLeft(); + + // disable dual axis (only use LEFT axis) + chart.getAxisRight().setEnabled(false); + + // horizontal grid lines + yAxis.enableGridDashedLine(10f, 10f, 0f); + + // axis range + yAxis.setAxisMaximum(200f); + yAxis.setAxisMinimum(-50f); + } + + + { // // Create Limit Lines // // + LimitLine llXAxis = new LimitLine(9f, "Index 10"); + llXAxis.setLineWidth(4f); + llXAxis.enableDashedLine(10f, 10f, 0f); + llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); + llXAxis.setTextSize(10f); + llXAxis.setTypeface(tfRegular); + + LimitLine ll1 = new LimitLine(150f, "Upper Limit"); + ll1.setLineWidth(4f); + ll1.enableDashedLine(10f, 10f, 0f); + ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); + ll1.setTextSize(10f); + ll1.setTypeface(tfRegular); + + LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); + ll2.setLineWidth(4f); + ll2.enableDashedLine(10f, 10f, 0f); + ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); + ll2.setTextSize(10f); + ll2.setTypeface(tfRegular); + + // draw limit lines behind data instead of on top + yAxis.setDrawLimitLinesBehindData(true); + xAxis.setDrawLimitLinesBehindData(true); + + // add limit lines + yAxis.addLimitLine(ll1); + yAxis.addLimitLine(ll2); + //xAxis.addLimitLine(llXAxis); + } + + // add data + seekBarX.setProgress(45); + seekBarY.setProgress(180); + setData(45, 180); + + // draw points over time + chart.animateX(1500); + + // get the legend (only possible after setting data) + Legend l = chart.getLegend(); + + // draw legend entries as lines + l.setForm(LegendForm.LINE); + } + + private void setData(int count, float range) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + + float val = (float) (Math.random() * range) - 30; + values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); + } + + LineDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + set1.notifyDataSetChanged(); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + // draw dashed line + set1.enableDashedLine(10f, 5f, 0f); + + // black lines and points + set1.setColor(Color.BLACK); + set1.setCircleColor(Color.BLACK); + + // line thickness and point size + set1.setLineWidth(1f); + set1.setCircleRadius(3f); + + // draw points as solid circles + set1.setDrawCircleHole(false); + + // customize legend entry + set1.setFormLineWidth(1f); + set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); + set1.setFormSize(15.f); + + // text size of values + set1.setValueTextSize(9f); + + // draw selection line as dashed + set1.enableDashedHighlightLine(10f, 5f, 0f); + + // set the filled area + set1.setDrawFilled(true); + set1.setFillFormatter(new IFillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return chart.getAxisLeft().getAxisMinimum(); + } + }); + + // set color of filled area + if (Utils.getSDKInt() >= 18) { + // drawables only supported on api level 18 and above + Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); + set1.setFillDrawable(drawable); + } else { + set1.setFillColor(Color.BLACK); + } + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + + // create a data object with the data sets + LineData data = new LineData(dataSets); + + // set data + chart.setData(data); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.line, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleIcons: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + chart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); + } + break; + } + case R.id.actionToggleFilled: { + + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawFilledEnabled()) + set.setDrawFilled(false); + else + set.setDrawFilled(true); + } + chart.invalidate(); + break; + } + case R.id.actionToggleCircles: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawCirclesEnabled()) + set.setDrawCircles(false); + else + set.setDrawCircles(true); + } + chart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); + } + chart.invalidate(); + break; + } + case R.id.actionToggleStepped: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); + } + chart.invalidate(); + break; + } + case R.id.actionToggleHorizontalCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + chart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); + else + chart.setPinchZoom(true); + + chart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); + break; + } + case R.id.animateX: { + chart.animateX(2000); + break; + } + case R.id.animateY: { + chart.animateY(2000, Easing.EaseInCubic); + break; + } + case R.id.animateXY: { + chart.animateXY(2000, 2000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + setData(seekBarX.getProgress(), seekBarY.getProgress()); + + // redraw + chart.invalidate(); + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "LineChartActivity1"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} + + @Override + public void onValueSelected(Entry e, Highlight h) { + Log.i("Entry selected", e.toString()); + Log.i("LOW HIGH", "low: " + chart.getLowestVisibleX() + ", high: " + chart.getHighestVisibleX()); + Log.i("MIN MAX", "xMin: " + chart.getXChartMin() + ", xMax: " + chart.getXChartMax() + ", yMin: " + chart.getYChartMin() + ", yMax: " + chart.getYChartMax()); + } + + @Override + public void onNothingSelected() { + Log.i("Nothing selected", "Nothing selected."); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java similarity index 62% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index e2a381ff91..6b9cbb5f22 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -10,7 +15,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -30,11 +34,17 @@ import java.util.ArrayList; import java.util.List; +/** + * Example of a dual axis {@link LineChart} with multiple data sets. + * + * @since 1.7.4 + * @version 3.1.0 + */ public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,51 +54,52 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("LineChartActivity2"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); - mChart.setDragDecelerationFrictionCoef(0.9f); + chart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); - mChart.setHighlightPerDragEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); + chart.setHighlightPerDragEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + chart.setBackgroundColor(Color.LTGRAY); // add data - setData(20, 30); + seekBarX.setProgress(20); + seekBarY.setProgress(30); - mChart.animateX(2500); + chart.animateX(1500); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setTextSize(11f); l.setTextColor(Color.WHITE); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); @@ -97,23 +108,23 @@ protected void onCreate(Bundle savedInstanceState) { l.setDrawInside(false); // l.setYOffset(11f); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setTextSize(11f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setAxisMaximum(200f); leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); - YAxis rightAxis = mChart.getAxisRight(); - rightAxis.setTypeface(mTfLight); + YAxis rightAxis = chart.getAxisRight(); + rightAxis.setTypeface(tfLight); rightAxis.setTextColor(Color.RED); rightAxis.setAxisMaximum(900); rightAxis.setAxisMinimum(-200); @@ -122,6 +133,93 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setGranularityEnabled(false); } + private void setData(int count, float range) { + + ArrayList values1 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * (range / 2f)) + 50; + values1.add(new Entry(i, val)); + } + + ArrayList values2 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 450; + values2.add(new Entry(i, val)); + } + + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 500; + values3.add(new Entry(i, val)); + } + + LineDataSet set1, set2, set3; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set2 = (LineDataSet) chart.getData().getDataSetByIndex(1); + set3 = (LineDataSet) chart.getData().getDataSetByIndex(2); + set1.setValues(values1); + set2.setValues(values2); + set3.setValues(values3); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values1, "DataSet 1"); + + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(Color.WHITE); + set1.setLineWidth(2f); + set1.setCircleRadius(3f); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + //set1.setFillFormatter(new MyFillFormatter(0f)); + //set1.setDrawHorizontalHighlightIndicator(false); + //set1.setVisible(false); + //set1.setCircleHoleColor(Color.WHITE); + + // create a dataset and give it a type + set2 = new LineDataSet(values2, "DataSet 2"); + set2.setAxisDependency(AxisDependency.RIGHT); + set2.setColor(Color.RED); + set2.setCircleColor(Color.WHITE); + set2.setLineWidth(2f); + set2.setCircleRadius(3f); + set2.setFillAlpha(65); + set2.setFillColor(Color.RED); + set2.setDrawCircleHole(false); + set2.setHighLightColor(Color.rgb(244, 117, 117)); + //set2.setFillFormatter(new MyFillFormatter(900f)); + + set3 = new LineDataSet(values3, "DataSet 3"); + set3.setAxisDependency(AxisDependency.RIGHT); + set3.setColor(Color.YELLOW); + set3.setCircleColor(Color.WHITE); + set3.setLineWidth(2f); + set3.setCircleRadius(3f); + set3.setFillAlpha(65); + set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); + set3.setDrawCircleHole(false); + set3.setHighLightColor(Color.rgb(244, 117, 117)); + + // create a data object with the data sets + LineData data = new LineData(set1, set2, set3); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + chart.setData(data); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); @@ -132,8 +230,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -142,19 +246,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -165,11 +269,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -180,11 +284,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -194,11 +298,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -208,11 +312,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -222,46 +326,41 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.HORIZONTAL_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); - //mChart.highlightValue(9.7f, 1, false); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -271,117 +370,29 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); } - private void setData(int count, float range) { - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = range / 2f; - float val = (float) (Math.random() * mult) + 50; - yVals1.add(new Entry(i, val)); - } - - ArrayList yVals2 = new ArrayList(); - - for (int i = 0; i < count-1; i++) { - float mult = range; - float val = (float) (Math.random() * mult) + 450; - yVals2.add(new Entry(i, val)); -// if(i == 10) { -// yVals2.add(new Entry(i, val + 50)); -// } - } - - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = range; - float val = (float) (Math.random() * mult) + 500; - yVals3.add(new Entry(i, val)); - } - - LineDataSet set1, set2, set3; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet) mChart.getData().getDataSetByIndex(0); - set2 = (LineDataSet) mChart.getData().getDataSetByIndex(1); - set3 = (LineDataSet) mChart.getData().getDataSetByIndex(2); - set1.setValues(yVals1); - set2.setValues(yVals2); - set3.setValues(yVals3); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(yVals1, "DataSet 1"); - - set1.setAxisDependency(AxisDependency.LEFT); - set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(Color.WHITE); - set1.setLineWidth(2f); - set1.setCircleRadius(3f); - set1.setFillAlpha(65); - set1.setFillColor(ColorTemplate.getHoloBlue()); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setDrawCircleHole(false); - //set1.setFillFormatter(new MyFillFormatter(0f)); - //set1.setDrawHorizontalHighlightIndicator(false); - //set1.setVisible(false); - //set1.setCircleHoleColor(Color.WHITE); - - // create a dataset and give it a type - set2 = new LineDataSet(yVals2, "DataSet 2"); - set2.setAxisDependency(AxisDependency.RIGHT); - set2.setColor(Color.RED); - set2.setCircleColor(Color.WHITE); - set2.setLineWidth(2f); - set2.setCircleRadius(3f); - set2.setFillAlpha(65); - set2.setFillColor(Color.RED); - set2.setDrawCircleHole(false); - set2.setHighLightColor(Color.rgb(244, 117, 117)); - //set2.setFillFormatter(new MyFillFormatter(900f)); - - set3 = new LineDataSet(yVals3, "DataSet 3"); - set3.setAxisDependency(AxisDependency.RIGHT); - set3.setColor(Color.YELLOW); - set3.setCircleColor(Color.WHITE); - set3.setLineWidth(2f); - set3.setCircleRadius(3f); - set3.setFillAlpha(65); - set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); - set3.setDrawCircleHole(false); - set3.setHighLightColor(Color.rgb(244, 117, 117)); - - // create a data object with the datasets - LineData data = new LineData(set1, set2, set3); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(9f); - - // set data - mChart.setData(data); - } + @Override + protected void saveToGallery() { + saveToGallery(chart, "LineChartActivity2"); } @Override public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); - mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + chart.centerViewToAnimated(e.getX(), e.getY(), chart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency(), 500); - //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + //chart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) // .getAxisDependency(), 1000); - //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + //chart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) // .getAxisDependency(), 1000); } @@ -391,14 +402,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java similarity index 63% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 39730d55b1..6a12e8f95d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -1,9 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.LineChart; @@ -15,10 +19,10 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class LineChartActivityColored extends DemoBase { - private LineChart[] mCharts = new LineChart[4]; - private Typeface mTf; + private final LineChart[] charts = new LineChart[4]; @Override protected void onCreate(Bundle savedInstanceState) { @@ -27,26 +31,28 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_colored_lines); - mCharts[0] = findViewById(R.id.chart1); - mCharts[1] = findViewById(R.id.chart2); - mCharts[2] = findViewById(R.id.chart3); - mCharts[3] = findViewById(R.id.chart4); + setTitle("LineChartActivityColored"); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); + charts[0] = findViewById(R.id.chart1); + charts[1] = findViewById(R.id.chart2); + charts[2] = findViewById(R.id.chart3); + charts[3] = findViewById(R.id.chart4); - for (int i = 0; i < mCharts.length; i++) { + Typeface mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); + + for (int i = 0; i < charts.length; i++) { LineData data = getData(36, 100); data.setValueTypeface(mTf); // add some transparency to the color with "& 0x90FFFFFF" - setupChart(mCharts[i], data, mColors[i % mColors.length]); + setupChart(charts[i], data, colors[i % colors.length]); } } - private int[] mColors = new int[] { - Color.rgb(137, 230, 81), - Color.rgb(240, 240, 30), + private final int[] colors = new int[] { + Color.rgb(137, 230, 81), + Color.rgb(240, 240, 30), Color.rgb(89, 199, 250), Color.rgb(250, 104, 104) }; @@ -57,8 +63,8 @@ private void setupChart(LineChart chart, LineData data, int color) { // no description text chart.getDescription().setEnabled(false); - - // mChart.setDrawHorizontalGrid(false); + + // chart.setDrawHorizontalGrid(false); // // enable / disable grid background chart.setDrawGridBackground(false); @@ -75,7 +81,7 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setPinchZoom(false); chart.setBackgroundColor(color); - + // set custom chart offsets (automatic offset calculation is hereby disabled) chart.setViewPortOffsets(10, 0, 10, 0); @@ -96,18 +102,18 @@ private void setupChart(LineChart chart, LineData data, int color) { // animate calls invalidate()... chart.animateX(2500); } - + private LineData getData(int count, float range) { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range) + 3; - yVals.add(new Entry(i, val)); + values.add(new Entry(i, val)); } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); // set1.setFillAlpha(110); // set1.setFillColor(Color.RED); @@ -119,9 +125,31 @@ private LineData getData(int count, float range) { set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); - // create a data object with the datasets - LineData data = new LineData(set1); + // create a data object with the data sets + return new LineData(set1); + } - return data; + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java similarity index 67% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 6bf96f02a7..212b90ff87 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -1,15 +1,19 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.AxisBase; @@ -25,17 +29,17 @@ import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import java.sql.Time; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.concurrent.TimeUnit; public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { - private LineChart mChart; - private SeekBar mSeekBarX; + private LineChart chart; + private SeekBar seekBarX; private TextView tvX; @Override @@ -45,44 +49,42 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_time); - tvX = findViewById(R.id.tvXMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setProgress(100); - tvX.setText("100"); + setTitle("LineChartTime"); - mSeekBarX.setOnSeekBarChangeListener(this); + tvX = findViewById(R.id.tvXMax); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); + chart = findViewById(R.id.chart1); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); - mChart.setDragDecelerationFrictionCoef(0.9f); + chart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); - mChart.setHighlightPerDragEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); + chart.setHighlightPerDragEnabled(true); // set an alternative background color - mChart.setBackgroundColor(Color.WHITE); - mChart.setViewPortOffsets(0f, 0f, 0f, 0f); + chart.setBackgroundColor(Color.WHITE); + chart.setViewPortOffsets(0f, 0f, 0f, 0f); // add data - setData(100, 30); - mChart.invalidate(); + seekBarX.setProgress(100); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setEnabled(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setTextSize(10f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); @@ -92,7 +94,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(1f); // one hour xAxis.setValueFormatter(new IAxisValueFormatter() { - private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); + private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override public String getFormattedValue(float value, AxisBase axis) { @@ -102,9 +104,9 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); - leftAxis.setTypeface(mTfLight); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); @@ -113,10 +115,49 @@ public String getFormattedValue(float value, AxisBase axis) { leftAxis.setYOffset(-9f); leftAxis.setTextColor(Color.rgb(255, 192, 56)); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); } + private void setData(int count, float range) { + + // now in hours + long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); + + ArrayList values = new ArrayList<>(); + + // count = hours + float to = now + count; + + // increment by 1 hour + for (float x = now; x < to; x++) { + + float y = getRandom(range, 50); + values.add(new Entry(x, y)); // add one entry per hour + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setValueTextColor(ColorTemplate.getHoloBlue()); + set1.setLineWidth(1.5f); + set1.setDrawCircles(false); + set1.setDrawValues(false); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + + // create a data object with the data sets + LineData data = new LineData(set1); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + chart.setData(data); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); @@ -127,8 +168,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -137,19 +184,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -160,11 +207,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -175,11 +222,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -190,11 +237,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setMode(LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -205,45 +252,42 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setMode(LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -253,64 +297,22 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); - setData(mSeekBarX.getProgress(), 50); + setData(seekBarX.getProgress(), 50); // redraw - mChart.invalidate(); - } - - private void setData(int count, float range) { - - // now in hours - long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); - - ArrayList values = new ArrayList(); - - float from = now; - - // count = hours - float to = now + count; - - // increment by 1 hour - for (float x = from; x < to; x++) { - - float y = getRandom(range, 50); - values.add(new Entry(x, y)); // add one entry per hour - } - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(values, "DataSet 1"); - set1.setAxisDependency(AxisDependency.LEFT); - set1.setColor(ColorTemplate.getHoloBlue()); - set1.setValueTextColor(ColorTemplate.getHoloBlue()); - set1.setLineWidth(1.5f); - set1.setDrawCircles(false); - set1.setDrawValues(false); - set1.setFillAlpha(65); - set1.setFillColor(ColorTemplate.getHoloBlue()); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setDrawCircleHole(false); - - // create a data object with the datasets - LineData data = new LineData(set1); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(9f); - - // set data - mChart.setData(data); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + protected void saveToGallery() { + saveToGallery(chart, "LineChartTime"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + public void onStartTrackingTouch(SeekBar seekBar) {} - } -} \ No newline at end of file + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java similarity index 68% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 54218a53da..1466e5f9de 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -1,11 +1,16 @@ package com.xxmassdeveloper.mpchartexample; +import android.annotation.SuppressLint; import android.content.Context; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.annotation.NonNull; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -28,8 +33,8 @@ /** * Demonstrates the use of charts inside a ListView. IMPORTANT: provide a - * specific height attribute for the chart inside your listview-item - * + * specific height attribute for the chart inside your ListView item + * * @author Philipp Jahoda */ public class ListViewBarChartActivity extends DemoBase { @@ -40,10 +45,12 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - + + setTitle("ListViewBarChartActivity"); + ListView lv = findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); // 20 items for (int i = 0; i < 20; i++) { @@ -56,16 +63,18 @@ protected void onCreate(Bundle savedInstanceState) { private class ChartDataAdapter extends ArrayAdapter { - public ChartDataAdapter(Context context, List objects) { + ChartDataAdapter(Context context, List objects) { super(context, 0, objects); } + @SuppressLint("InflateParams") + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { BarData data = getItem(position); - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -82,30 +91,32 @@ public View getView(int position, View convertView, ViewGroup parent) { } // apply styling - data.setValueTypeface(mTfLight); - data.setValueTextColor(Color.BLACK); + if (data != null) { + data.setValueTypeface(tfLight); + data.setValueTextColor(Color.BLACK); + } holder.chart.getDescription().setEnabled(false); holder.chart.setDrawGridBackground(false); XAxis xAxis = holder.chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setDrawGridLines(false); - + YAxis leftAxis = holder.chart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(15f); - + YAxis rightAxis = holder.chart.getAxisRight(); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(15f); // set data holder.chart.setData(data); holder.chart.setFitBars(true); - + // do not forget to refresh the chart // holder.chart.invalidate(); holder.chart.animateY(700); @@ -121,12 +132,12 @@ private class ViewHolder { /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Bar data */ private BarData generateData(int cnt) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 12; i++) { entries.add(new BarEntry(i, (float) (Math.random() * 70) + 30)); @@ -135,12 +146,36 @@ private BarData generateData(int cnt) { BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setBarShadowColor(Color.rgb(203, 203, 203)); - - ArrayList sets = new ArrayList(); + + ArrayList sets = new ArrayList<>(); sets.add(d); - + BarData cd = new BarData(sets); cd.setBarWidth(0.9f); return cd; } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java similarity index 65% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 0c9f132f03..1455691620 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -2,8 +2,13 @@ package com.xxmassdeveloper.mpchartexample; import android.content.Context; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -32,8 +37,8 @@ /** * Demonstrates the use of charts inside a ListView. IMPORTANT: provide a - * specific height attribute for the chart inside your listview-item - * + * specific height attribute for the chart inside your ListView item + * * @author Philipp Jahoda */ public class ListViewMultiChartActivity extends DemoBase { @@ -44,20 +49,22 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - + + setTitle("ListViewMultiChartActivity"); + ListView lv = findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); // 30 items for (int i = 0; i < 30; i++) { - + if(i % 3 == 0) { list.add(new LineChartItem(generateDataLine(i + 1), getApplicationContext())); } else if(i % 3 == 1) { list.add(new BarChartItem(generateDataBar(i + 1), getApplicationContext())); } else if(i % 3 == 2) { - list.add(new PieChartItem(generateDataPie(i + 1), getApplicationContext())); + list.add(new PieChartItem(generateDataPie(), getApplicationContext())); } } @@ -67,77 +74,79 @@ protected void onCreate(Bundle savedInstanceState) { /** adapter that supports 3 different item types */ private class ChartDataAdapter extends ArrayAdapter { - - public ChartDataAdapter(Context context, List objects) { + + ChartDataAdapter(Context context, List objects) { super(context, 0, objects); } + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + //noinspection ConstantConditions return getItem(position).getView(position, convertView, getContext()); } - + @Override - public int getItemViewType(int position) { + public int getItemViewType(int position) { // return the views type - return getItem(position).getItemType(); + ChartItem ci = getItem(position); + return ci != null ? ci.getItemType() : 0; } - + @Override public int getViewTypeCount() { return 3; // we have 3 different item-types } } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Line data */ private LineData generateDataLine(int cnt) { - ArrayList e1 = new ArrayList(); + ArrayList values1 = new ArrayList<>(); for (int i = 0; i < 12; i++) { - e1.add(new Entry(i, (int) (Math.random() * 65) + 40)); + values1.add(new Entry(i, (int) (Math.random() * 65) + 40)); } - LineDataSet d1 = new LineDataSet(e1, "New DataSet " + cnt + ", (1)"); + LineDataSet d1 = new LineDataSet(values1, "New DataSet " + cnt + ", (1)"); d1.setLineWidth(2.5f); d1.setCircleRadius(4.5f); d1.setHighLightColor(Color.rgb(244, 117, 117)); d1.setDrawValues(false); - - ArrayList e2 = new ArrayList(); + + ArrayList values2 = new ArrayList<>(); for (int i = 0; i < 12; i++) { - e2.add(new Entry(i, e1.get(i).getY() - 30)); + values2.add(new Entry(i, values1.get(i).getY() - 30)); } - LineDataSet d2 = new LineDataSet(e2, "New DataSet " + cnt + ", (2)"); + LineDataSet d2 = new LineDataSet(values2, "New DataSet " + cnt + ", (2)"); d2.setLineWidth(2.5f); d2.setCircleRadius(4.5f); d2.setHighLightColor(Color.rgb(244, 117, 117)); d2.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setDrawValues(false); - - ArrayList sets = new ArrayList(); + + ArrayList sets = new ArrayList<>(); sets.add(d1); sets.add(d2); - - LineData cd = new LineData(sets); - return cd; + + return new LineData(sets); } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Bar data */ private BarData generateDataBar(int cnt) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 12; i++) { entries.add(new BarEntry(i, (int) (Math.random() * 70) + 30)); @@ -146,32 +155,55 @@ private BarData generateDataBar(int cnt) { BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setHighLightAlpha(255); - + BarData cd = new BarData(d); cd.setBarWidth(0.9f); return cd; } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Pie data */ - private PieData generateDataPie(int cnt) { + private PieData generateDataPie() { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 4; i++) { entries.add(new PieEntry((float) ((Math.random() * 70) + 30), "Quarter " + (i+1))); } PieDataSet d = new PieDataSet(entries, ""); - + // space between slices d.setSliceSpace(2f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); - - PieData cd = new PieData(d); - return cd; + + return new PieData(d); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java")); + startActivity(i); + break; + } + } + + return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java new file mode 100644 index 0000000000..11d69d8dae --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -0,0 +1,354 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import androidx.core.content.ContextCompat; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.listener.ChartTouchListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.List; + +public class MultiLineChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartGestureListener, OnChartValueSelectedListener { + + private LineChart chart; + private SeekBar seekBarX, seekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart); + + setTitle("MultiLineChartActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); + + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); + chart.setDrawBorders(false); + + chart.getAxisLeft().setEnabled(false); + chart.getAxisRight().setDrawAxisLine(false); + chart.getAxisRight().setDrawGridLines(false); + chart.getXAxis().setDrawAxisLine(false); + chart.getXAxis().setDrawGridLines(false); + + // enable touch gestures + chart.setTouchEnabled(true); + + // enable scaling and dragging + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + chart.setPinchZoom(false); + + seekBarX.setProgress(20); + seekBarY.setProgress(100); + + Legend l = chart.getLegend(); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); + } + + private final int[] colors = new int[] { + ColorTemplate.VORDIPLOM_COLORS[0], + ColorTemplate.VORDIPLOM_COLORS[1], + ColorTemplate.VORDIPLOM_COLORS[2] + }; + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + chart.resetTracking(); + + progress = seekBarX.getProgress(); + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList dataSets = new ArrayList<>(); + + for (int z = 0; z < 3; z++) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < progress; i++) { + double val = (Math.random() * seekBarY.getProgress()) + 3; + values.add(new Entry(i, (float) val)); + } + + LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); + d.setLineWidth(2.5f); + d.setCircleRadius(4f); + + int color = colors[z % colors.length]; + d.setColor(color); + d.setCircleColor(color); + dataSets.add(d); + } + + // make the first DataSet dashed + ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); + ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); + ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); + + LineData data = new LineData(dataSets); + chart.setData(data); + chart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.line, menu); + menu.removeItem(R.id.actionToggleIcons); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + chart.invalidate(); + break; + } + /* + case R.id.actionToggleIcons: { break; } + */ + case R.id.actionTogglePinch: { + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); + else + chart.setPinchZoom(true); + + chart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleHighlight: { + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); + } + break; + } + case R.id.actionToggleFilled: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawFilledEnabled()) + set.setDrawFilled(false); + else + set.setDrawFilled(true); + } + chart.invalidate(); + break; + } + case R.id.actionToggleCircles: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawCirclesEnabled()) + set.setDrawCircles(false); + else + set.setDrawCircles(true); + } + chart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); + } + chart.invalidate(); + break; + } + case R.id.actionToggleStepped: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); + } + chart.invalidate(); + break; + } + case R.id.actionToggleHorizontalCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + chart.invalidate(); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + case R.id.animateX: { + chart.animateX(2000); + break; + } + case R.id.animateY: { + chart.animateY(2000); + break; + } + case R.id.animateXY: { + chart.animateXY(2000, 2000); + break; + } + } + return true; + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "MultiLineChartActivity"); + } + + @Override + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); + } + + @Override + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); + + // un-highlight values after the gesture is finished and no single-tap + if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) + chart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) + } + + @Override + public void onChartLongPressed(MotionEvent me) { + Log.i("LongPress", "Chart long pressed."); + } + + @Override + public void onChartDoubleTapped(MotionEvent me) { + Log.i("DoubleTap", "Chart double-tapped."); + } + + @Override + public void onChartSingleTapped(MotionEvent me) { + Log.i("SingleTap", "Chart single-tapped."); + } + + @Override + public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { + Log.i("Fling", "Chart fling. VelocityX: " + velocityX + ", VelocityY: " + velocityY); + } + + @Override + public void onChartScale(MotionEvent me, float scaleX, float scaleY) { + Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); + } + + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); + } + + @Override + public void onValueSelected(Entry e, Highlight h) { + Log.i("VAL SELECTED", + "Value: " + e.getY() + ", xIndex: " + e.getX() + + ", DataSet index: " + h.getDataSetIndex()); + } + + @Override + public void onNothingSelected() {} + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} +} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java new file mode 100644 index 0000000000..c557323451 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -0,0 +1,144 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.content.Intent; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +@SuppressWarnings("SameParameterValue") +public class PerformanceLineChart extends DemoBase implements OnSeekBarChangeListener { + + private LineChart chart; + private SeekBar seekBarValues; + private TextView tvCount; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_performance_linechart); + + setTitle("PerformanceLineChart"); + + tvCount = findViewById(R.id.tvValueCount); + seekBarValues = findViewById(R.id.seekbarValues); + seekBarValues.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + chart.setDrawGridBackground(false); + + // no description text + chart.getDescription().setEnabled(false); + + // enable touch gestures + chart.setTouchEnabled(true); + + // enable scaling and dragging + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + chart.setPinchZoom(false); + + chart.getAxisLeft().setDrawGridLines(false); + chart.getAxisRight().setEnabled(false); + chart.getXAxis().setDrawGridLines(true); + chart.getXAxis().setDrawAxisLine(false); + + seekBarValues.setProgress(9000); + + // don't forget to refresh the drawing + chart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * (range + 1)) + 3; + values.add(new Entry(i * 0.001f, val)); + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); + + set1.setColor(Color.BLACK); + set1.setLineWidth(0.5f); + set1.setDrawValues(false); + set1.setDrawCircles(false); + set1.setMode(LineDataSet.Mode.LINEAR); + set1.setDrawFilled(false); + + // create a data object with the data sets + LineData data = new LineData(set1); + + // set data + chart.setData(data); + + // get the legend (only possible after setting data) + Legend l = chart.getLegend(); + l.setEnabled(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + int count = seekBarValues.getProgress() + 1000; + tvCount.setText(String.valueOf(count)); + + chart.resetTracking(); + + setData(count, 500f); + + // redraw + chart.invalidate(); + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java similarity index 54% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 0252ff8ff0..830025fbb1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -1,9 +1,14 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -19,7 +24,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; @@ -37,8 +41,8 @@ public class PieChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private PieChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private PieChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -48,55 +52,56 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); + setTitle("PieChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setProgress(4); - mSeekBarY.setProgress(10); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); - mChart.setExtraOffsets(5, 10, 5, 5); + chart = findViewById(R.id.chart1); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); + chart.setExtraOffsets(5, 10, 5, 5); - mChart.setDragDecelerationFrictionCoef(0.95f); + chart.setDragDecelerationFrictionCoef(0.95f); - mChart.setCenterTextTypeface(mTfLight); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(tfLight); + chart.setCenterText(generateCenterSpannableText()); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationAngle(0); + chart.setRotationAngle(0); // enable rotation of the chart by touch - mChart.setRotationEnabled(true); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(true); + chart.setHighlightPerTapEnabled(true); - // mChart.setUnit(" €"); - // mChart.setDrawUnitsInChart(true); + // chart.setUnit(" €"); + // chart.setDrawUnitsInChart(true); // add a selection listener - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); - setData(4, 100); + seekBarX.setProgress(4); + seekBarY.setProgress(10); - mChart.animateY(1400, Easing.EaseInOutQuad); - // mChart.spin(2000, 0, 360); + chart.animateY(1400, Easing.EaseInOutQuad); + // chart.spin(2000, 0, 360); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); @@ -106,9 +111,65 @@ protected void onCreate(Bundle savedInstanceState) { l.setYOffset(0f); // entry label styling - mChart.setEntryLabelColor(Color.WHITE); - mChart.setEntryLabelTypeface(mTfRegular); - mChart.setEntryLabelTextSize(12f); + chart.setEntryLabelColor(Color.WHITE); + chart.setEntryLabelTypeface(tfRegular); + chart.setEntryLabelTextSize(12f); + } + + private void setData(int count, float range) { + ArrayList entries = new ArrayList<>(); + + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < count ; i++) { + entries.add(new PieEntry((float) ((Math.random() * range) + range / 5), + parties[i % parties.length], + getResources().getDrawable(R.drawable.star))); + } + + PieDataSet dataSet = new PieDataSet(entries, "Election Results"); + + dataSet.setDrawIcons(false); + + dataSet.setSliceSpace(3f); + dataSet.setIconsOffset(new MPPointF(0, 40)); + dataSet.setSelectionShift(5f); + + // add a lot of colors + + ArrayList colors = new ArrayList<>(); + + for (int c : ColorTemplate.VORDIPLOM_COLORS) + colors.add(c); + + for (int c : ColorTemplate.JOYFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.COLORFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.LIBERTY_COLORS) + colors.add(c); + + for (int c : ColorTemplate.PASTEL_COLORS) + colors.add(c); + + colors.add(ColorTemplate.getHoloBlue()); + + dataSet.setColors(colors); + //dataSet.setSelectionShift(0f); + + PieData data = new PieData(dataSet); + data.setValueFormatter(new PercentFormatter()); + data.setValueTextSize(11f); + data.setValueTextColor(Color.WHITE); + data.setValueTypeface(tfLight); + chart.setData(data); + + // undo all highlights + chart.highlightValues(null); + + chart.invalidate(); } @Override @@ -121,65 +182,95 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHole: { - if (mChart.isDrawHoleEnabled()) - mChart.setDrawHoleEnabled(false); + if (chart.isDrawHoleEnabled()) + chart.setDrawHoleEnabled(false); else - mChart.setDrawHoleEnabled(true); - mChart.invalidate(); + chart.setDrawHoleEnabled(true); + chart.invalidate(); break; } - case R.id.actionDrawCenter: { - if (mChart.isDrawCenterTextEnabled()) - mChart.setDrawCenterText(false); + case R.id.actionToggleMinAngles: { + if (chart.getMinAngleForSlices() == 0f) + chart.setMinAngleForSlices(36f); else - mChart.setDrawCenterText(true); - mChart.invalidate(); + chart.setMinAngleForSlices(0f); + chart.notifyDataSetChanged(); + chart.invalidate(); break; } - case R.id.actionToggleXVals: { - - mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); - mChart.invalidate(); + case R.id.actionToggleCurvedSlices: { + boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); + chart.setDrawRoundedSlices(toSet); + if (toSet && !chart.isDrawHoleEnabled()) { + chart.setDrawHoleEnabled(true); + } + if (toSet && chart.isDrawSlicesUnderHoleEnabled()) { + chart.setDrawSlicesUnderHole(false); + } + chart.invalidate(); break; } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + case R.id.actionDrawCenter: { + if (chart.isDrawCenterTextEnabled()) + chart.setDrawCenterText(false); + else + chart.setDrawCenterText(true); + chart.invalidate(); + break; + } + case R.id.actionToggleXValues: { + + chart.setDrawEntryLabels(!chart.isDrawEntryLabelsEnabled()); + chart.invalidate(); break; } case R.id.actionTogglePercent: - mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); - mChart.invalidate(); + chart.setUsePercentValues(!chart.isUsePercentValuesEnabled()); + chart.invalidate(); break; case R.id.animateX: { - mChart.animateX(1400); + chart.animateX(1400); break; } case R.id.animateY: { - mChart.animateY(1400); + chart.animateY(1400); break; } case R.id.animateXY: { - mChart.animateXY(1400, 1400); + chart.animateXY(1400, 1400); break; } case R.id.actionToggleSpin: { - mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); + chart.spin(1000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -189,69 +280,15 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); } - private void setData(int count, float range) { - - float mult = range; - - ArrayList entries = new ArrayList(); - - // NOTE: The order of the entries when being added to the entries array determines their position around the center of - // the chart. - for (int i = 0; i < count ; i++) { - entries.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), - mParties[i % mParties.length], - getResources().getDrawable(R.drawable.star))); - } - - PieDataSet dataSet = new PieDataSet(entries, "Election Results"); - - dataSet.setDrawIcons(false); - - dataSet.setSliceSpace(3f); - dataSet.setIconsOffset(new MPPointF(0, 40)); - dataSet.setSelectionShift(5f); - - // add a lot of colors - - ArrayList colors = new ArrayList(); - - for (int c : ColorTemplate.VORDIPLOM_COLORS) - colors.add(c); - - for (int c : ColorTemplate.JOYFUL_COLORS) - colors.add(c); - - for (int c : ColorTemplate.COLORFUL_COLORS) - colors.add(c); - - for (int c : ColorTemplate.LIBERTY_COLORS) - colors.add(c); - - for (int c : ColorTemplate.PASTEL_COLORS) - colors.add(c); - - colors.add(ColorTemplate.getHoloBlue()); - - dataSet.setColors(colors); - //dataSet.setSelectionShift(0f); - - PieData data = new PieData(dataSet); - data.setValueFormatter(new PercentFormatter()); - data.setValueTextSize(11f); - data.setValueTextColor(Color.WHITE); - data.setValueTypeface(mTfLight); - mChart.setData(data); - - // undo all highlights - mChart.highlightValues(null); - - mChart.invalidate(); + @Override + protected void saveToGallery() { + saveToGallery(chart, "PieChartActivity"); } private SpannableString generateCenterSpannableText() { @@ -282,14 +319,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java similarity index 54% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index c0199723d9..dd3bd575da 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -1,9 +1,14 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -35,8 +40,8 @@ public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private PieChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private PieChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; private Typeface tf; @@ -48,59 +53,60 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); + setTitle("PiePolylineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - - mSeekBarY.setProgress(10); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); - mChart.setExtraOffsets(5, 10, 5, 5); + chart = findViewById(R.id.chart1); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); + chart.setExtraOffsets(5, 10, 5, 5); - mChart.setDragDecelerationFrictionCoef(0.95f); + chart.setDragDecelerationFrictionCoef(0.95f); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); + chart.setCenterText(generateCenterSpannableText()); - mChart.setExtraOffsets(20.f, 0.f, 20.f, 0.f); + chart.setExtraOffsets(20.f, 0.f, 20.f, 0.f); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationAngle(0); + chart.setRotationAngle(0); // enable rotation of the chart by touch - mChart.setRotationEnabled(true); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(true); + chart.setHighlightPerTapEnabled(true); - // mChart.setUnit(" €"); - // mChart.setDrawUnitsInChart(true); + // chart.setUnit(" €"); + // chart.setDrawUnitsInChart(true); // add a selection listener - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); - setData(4, 100); + seekBarX.setProgress(4); + seekBarY.setProgress(100); - mChart.animateY(1400, Easing.EaseInOutQuad); - // mChart.spin(2000, 0, 360); + chart.animateY(1400, Easing.EaseInOutQuad); + // chart.spin(2000, 0, 360); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); @@ -108,89 +114,14 @@ protected void onCreate(Bundle savedInstanceState) { l.setEnabled(false); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.pie, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) - set.setDrawValues(!set.isDrawValuesEnabled()); - - mChart.invalidate(); - break; - } - case R.id.actionToggleHole: { - if (mChart.isDrawHoleEnabled()) - mChart.setDrawHoleEnabled(false); - else - mChart.setDrawHoleEnabled(true); - mChart.invalidate(); - break; - } - case R.id.actionDrawCenter: { - if (mChart.isDrawCenterTextEnabled()) - mChart.setDrawCenterText(false); - else - mChart.setDrawCenterText(true); - mChart.invalidate(); - break; - } - case R.id.actionToggleXVals: { - - mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); - mChart.invalidate(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); - break; - } - case R.id.actionTogglePercent: - mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); - mChart.invalidate(); - break; - case R.id.animateX: { - mChart.animateX(1400); - break; - } - case R.id.animateY: { - mChart.animateY(1400); - break; - } - case R.id.animateXY: { - mChart.animateXY(1400, 1400); - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); - - setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); - } - private void setData(int count, float range) { - float mult = range; - - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); // NOTE: The order of the entries when being added to the entries array determines their position around the center of // the chart. for (int i = 0; i < count; i++) { - entries.add(new PieEntry((float) (Math.random() * mult) + mult / 5, mParties[i % mParties.length])); + entries.add(new PieEntry((float) (Math.random() * range) + range / 5, parties[i % parties.length])); } PieDataSet dataSet = new PieDataSet(entries, "Election Results"); @@ -199,7 +130,7 @@ private void setData(int count, float range) { // add a lot of colors - ArrayList colors = new ArrayList(); + ArrayList colors = new ArrayList<>(); for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c); @@ -225,7 +156,6 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); - //dataSet.setUsingSliceColorAsValueLineColor(true); //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); @@ -235,12 +165,124 @@ private void setData(int count, float range) { data.setValueTextSize(11f); data.setValueTextColor(Color.BLACK); data.setValueTypeface(tf); - mChart.setData(data); + chart.setData(data); // undo all highlights - mChart.highlightValues(null); + chart.highlightValues(null); - mChart.invalidate(); + chart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.pie, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + for (IDataSet set : chart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + chart.invalidate(); + break; + } + case R.id.actionToggleHole: { + if (chart.isDrawHoleEnabled()) + chart.setDrawHoleEnabled(false); + else + chart.setDrawHoleEnabled(true); + chart.invalidate(); + break; + } + case R.id.actionToggleMinAngles: { + if (chart.getMinAngleForSlices() == 0f) + chart.setMinAngleForSlices(36f); + else + chart.setMinAngleForSlices(0f); + chart.notifyDataSetChanged(); + chart.invalidate(); + break; + } + case R.id.actionToggleCurvedSlices: { + boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); + chart.setDrawRoundedSlices(toSet); + if (toSet && !chart.isDrawHoleEnabled()) { + chart.setDrawHoleEnabled(true); + } + if (toSet && chart.isDrawSlicesUnderHoleEnabled()) { + chart.setDrawSlicesUnderHole(false); + } + chart.invalidate(); + break; + } + case R.id.actionDrawCenter: { + if (chart.isDrawCenterTextEnabled()) + chart.setDrawCenterText(false); + else + chart.setDrawCenterText(true); + chart.invalidate(); + break; + } + case R.id.actionToggleXValues: { + + chart.setDrawEntryLabels(!chart.isDrawEntryLabelsEnabled()); + chart.invalidate(); + break; + } + case R.id.actionTogglePercent: + chart.setUsePercentValues(!chart.isUsePercentValuesEnabled()); + chart.invalidate(); + break; + case R.id.animateX: { + chart.animateX(1400); + break; + } + case R.id.animateY: { + chart.animateY(1400); + break; + } + case R.id.animateXY: { + chart.animateXY(1400, 1400); + break; + } + case R.id.actionToggleSpin: { + chart.spin(1000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + setData(seekBarX.getProgress(), seekBarY.getProgress()); + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "PiePolylineChartActivity"); } private SpannableString generateCenterSpannableText() { @@ -271,14 +313,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java similarity index 62% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index d354886f6e..883eb7dfc1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,13 +1,16 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; -import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; @@ -29,49 +32,46 @@ public class RadarChartActivity extends DemoBase { - private RadarChart mChart; + private RadarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); + setContentView(R.layout.activity_radarchart); - TextView tv = findViewById(R.id.textView); - tv.setTypeface(mTfLight); - tv.setTextColor(Color.WHITE); - tv.setBackgroundColor(Color.rgb(60, 65, 82)); + setTitle("RadarChartActivity"); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.rgb(60, 65, 82)); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.rgb(60, 65, 82)); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); - mChart.setWebLineWidth(1f); - mChart.setWebColor(Color.LTGRAY); - mChart.setWebLineWidthInner(1f); - mChart.setWebColorInner(Color.LTGRAY); - mChart.setWebAlpha(100); + chart.setWebLineWidth(1f); + chart.setWebColor(Color.LTGRAY); + chart.setWebLineWidthInner(1f); + chart.setWebColorInner(Color.LTGRAY); + chart.setWebAlpha(100); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MarkerView mv = new RadarMarkerView(this, R.layout.radar_markerview); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart setData(); - mChart.animateXY(1400, 1400, Easing.EaseInOutQuad); + chart.animateXY(1400, 1400, Easing.EaseInOutQuad); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); xAxis.setValueFormatter(new IAxisValueFormatter() { - private String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; + private final String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override public String getFormattedValue(float value, AxisBase axis) { @@ -80,25 +80,76 @@ public String getFormattedValue(float value, AxisBase axis) { }); xAxis.setTextColor(Color.WHITE); - YAxis yAxis = mChart.getYAxis(); - yAxis.setTypeface(mTfLight); + YAxis yAxis = chart.getYAxis(); + yAxis.setTypeface(tfLight); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setAxisMinimum(0f); yAxis.setAxisMaximum(80f); yAxis.setDrawLabels(false); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setXEntrySpace(7f); l.setYEntrySpace(5f); l.setTextColor(Color.WHITE); } + private void setData() { + + float mul = 80; + float min = 20; + int cnt = 5; + + ArrayList entries1 = new ArrayList<>(); + ArrayList entries2 = new ArrayList<>(); + + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < cnt; i++) { + float val1 = (float) (Math.random() * mul) + min; + entries1.add(new RadarEntry(val1)); + + float val2 = (float) (Math.random() * mul) + min; + entries2.add(new RadarEntry(val2)); + } + + RadarDataSet set1 = new RadarDataSet(entries1, "Last Week"); + set1.setColor(Color.rgb(103, 110, 129)); + set1.setFillColor(Color.rgb(103, 110, 129)); + set1.setDrawFilled(true); + set1.setFillAlpha(180); + set1.setLineWidth(2f); + set1.setDrawHighlightCircleEnabled(true); + set1.setDrawHighlightIndicators(false); + + RadarDataSet set2 = new RadarDataSet(entries2, "This Week"); + set2.setColor(Color.rgb(121, 162, 175)); + set2.setFillColor(Color.rgb(121, 162, 175)); + set2.setDrawFilled(true); + set2.setFillAlpha(180); + set2.setLineWidth(2f); + set2.setDrawHighlightCircleEnabled(true); + set2.setDrawHighlightIndicators(false); + + ArrayList sets = new ArrayList<>(); + sets.add(set1); + sets.add(set2); + + RadarData data = new RadarData(sets); + data.setValueTypeface(tfLight); + data.setValueTextSize(8f); + data.setDrawValues(false); + data.setValueTextColor(Color.WHITE); + + chart.setData(data); + chart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.radar, menu); @@ -109,31 +160,37 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleRotate: { - if (mChart.isRotationEnabled()) - mChart.setRotationEnabled(false); + if (chart.isRotationEnabled()) + chart.setRotationEnabled(false); else - mChart.setRotationEnabled(true); - mChart.invalidate(); + chart.setRotationEnabled(true); + chart.invalidate(); break; } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + ArrayList sets = (ArrayList) chart.getData() .getDataSets(); for (IRadarDataSet set : sets) { @@ -142,109 +199,62 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlightCircle: { - ArrayList sets = (ArrayList) mChart.getData() + ArrayList sets = (ArrayList) chart.getData() .getDataSets(); for (IRadarDataSet set : sets) { set.setDrawHighlightCircleEnabled(!set.isDrawHighlightCircleEnabled()); } - mChart.invalidate(); - break; - } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + chart.invalidate(); break; } case R.id.actionToggleXLabels: { - mChart.getXAxis().setEnabled(!mChart.getXAxis().isEnabled()); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.getXAxis().setEnabled(!chart.getXAxis().isEnabled()); + chart.notifyDataSetChanged(); + chart.invalidate(); break; } case R.id.actionToggleYLabels: { - mChart.getYAxis().setEnabled(!mChart.getYAxis().isEnabled()); - mChart.invalidate(); + chart.getYAxis().setEnabled(!chart.getYAxis().isEnabled()); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(1400); + chart.animateX(1400); break; } case R.id.animateY: { - mChart.animateY(1400); + chart.animateY(1400); break; } case R.id.animateXY: { - mChart.animateXY(1400, 1400); + chart.animateXY(1400, 1400); break; } case R.id.actionToggleSpin: { - mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); + chart.spin(2000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } return true; } - public void setData() { - - float mult = 80; - float min = 20; - int cnt = 5; - - ArrayList entries1 = new ArrayList(); - ArrayList entries2 = new ArrayList(); - - // NOTE: The order of the entries when being added to the entries array determines their position around the center of - // the chart. - for (int i = 0; i < cnt; i++) { - float val1 = (float) (Math.random() * mult) + min; - entries1.add(new RadarEntry(val1)); - - float val2 = (float) (Math.random() * mult) + min; - entries2.add(new RadarEntry(val2)); - } - - RadarDataSet set1 = new RadarDataSet(entries1, "Last Week"); - set1.setColor(Color.rgb(103, 110, 129)); - set1.setFillColor(Color.rgb(103, 110, 129)); - set1.setDrawFilled(true); - set1.setFillAlpha(180); - set1.setLineWidth(2f); - set1.setDrawHighlightCircleEnabled(true); - set1.setDrawHighlightIndicators(false); - - RadarDataSet set2 = new RadarDataSet(entries2, "This Week"); - set2.setColor(Color.rgb(121, 162, 175)); - set2.setFillColor(Color.rgb(121, 162, 175)); - set2.setDrawFilled(true); - set2.setFillAlpha(180); - set2.setLineWidth(2f); - set2.setDrawHighlightCircleEnabled(true); - set2.setDrawHighlightIndicators(false); - - ArrayList sets = new ArrayList(); - sets.add(set1); - sets.add(set2); - - RadarData data = new RadarData(sets); - data.setValueTypeface(mTfLight); - data.setValueTextSize(8f); - data.setDrawValues(false); - data.setValueTextColor(Color.WHITE); - - mChart.setData(data); - mChart.invalidate(); + @Override + protected void saveToGallery() { + saveToGallery(chart, "RadarChartActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java similarity index 72% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index f3661628d0..e26c460ffa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -27,7 +32,7 @@ public class RealtimeLineChartActivity extends DemoBase implements OnChartValueSelectedListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,89 +41,64 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_realtime_linechart); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + setTitle("RealtimeLineChartActivity"); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); // enable description text - mChart.getDescription().setEnabled(true); + chart.getDescription().setEnabled(true); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + chart.setBackgroundColor(Color.LTGRAY); LineData data = new LineData(); data.setValueTextColor(Color.WHITE); // add empty data - mChart.setData(data); + chart.setData(data); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setTextColor(Color.WHITE); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(mTfLight); + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfLight); xl.setTextColor(Color.WHITE); xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); xl.setEnabled(true); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(Color.WHITE); leftAxis.setAxisMaximum(100f); leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realtime, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionAdd: { - addEntry(); - break; - } - case R.id.actionClear: { - mChart.clearValues(); - Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); - break; - } - case R.id.actionFeedMultiple: { - feedMultiple(); - break; - } - } - return true; - } - private void addEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { @@ -134,17 +114,17 @@ private void addEntry() { data.notifyDataChanged(); // let the chart know it's data has changed - mChart.notifyDataSetChanged(); + chart.notifyDataSetChanged(); // limit the number of visible entries - mChart.setVisibleXRangeMaximum(120); - // mChart.setVisibleYRange(30, AxisDependency.LEFT); + chart.setVisibleXRangeMaximum(120); + // chart.setVisibleYRange(30, AxisDependency.LEFT); // move to the latest entry - mChart.moveViewToX(data.getEntryCount()); + chart.moveViewToX(data.getEntryCount()); // this automatically refreshes the chart (calls invalidate()) - // mChart.moveViewTo(data.getXValCount()-7, 55f, + // chart.moveViewTo(data.getXValCount()-7, 55f, // AxisDependency.LEFT); } } @@ -193,7 +173,6 @@ public void run() { try { Thread.sleep(25); } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -203,6 +182,52 @@ public void run() { thread.start(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.realtime, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionAdd: { + addEntry(); + break; + } + case R.id.actionClear: { + chart.clearValues(); + Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); + break; + } + case R.id.actionFeedMultiple: { + feedMultiple(); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + protected void saveToGallery() { + saveToGallery(chart, "RealtimeLineChartActivity"); + } + @Override public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java similarity index 52% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index f0f889e194..e51755ad0b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -12,7 +17,6 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; @@ -31,10 +35,10 @@ public class ScatterChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private ScatterChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private ScatterChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -42,52 +46,109 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scatterchart); + setTitle("ScatterChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.setTouchEnabled(true); - mChart.setMaxHighlightDistance(50f); + chart.setDrawGridBackground(false); + chart.setTouchEnabled(true); + chart.setMaxHighlightDistance(50f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); - mChart.setMaxVisibleValueCount(200); - mChart.setPinchZoom(true); + chart.setMaxVisibleValueCount(200); + chart.setPinchZoom(true); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX.setProgress(45); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setXOffset(5f); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) - - mChart.getAxisRight().setEnabled(false); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(mTfLight); + chart.getAxisRight().setEnabled(false); + + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfLight); xl.setDrawGridLines(false); } + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values1.add(new Entry(i, val)); + } + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values2.add(new Entry(i+0.33f, val)); + } + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values3.add(new Entry(i+0.66f, val)); + } + + // create a dataset and give it a type + ScatterDataSet set1 = new ScatterDataSet(values1, "DS 1"); + set1.setScatterShape(ScatterChart.ScatterShape.SQUARE); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); + ScatterDataSet set2 = new ScatterDataSet(values2, "DS 2"); + set2.setScatterShape(ScatterChart.ScatterShape.CIRCLE); + set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); + set2.setScatterShapeHoleRadius(3f); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); + ScatterDataSet set3 = new ScatterDataSet(values3, "DS 3"); + set3.setShapeRenderer(new CustomScatterShapeRenderer()); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); + + set1.setScatterShapeSize(8f); + set2.setScatterShapeSize(8f); + set3.setScatterShapeSize(8f); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + dataSets.add(set2); + dataSets.add(set3); + + // create a data object with the data sets + ScatterData data = new ScatterData(dataSets); + data.setValueTypeface(tfLight); + + chart.setData(data); + chart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.scatter, menu); @@ -98,8 +159,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IScatterDataSet iSet : sets) { @@ -108,46 +175,49 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(3000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(3000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(3000, 3000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -155,58 +225,8 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals1.add(new Entry(i, val)); - } - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals2.add(new Entry(i+0.33f, val)); - } - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals3.add(new Entry(i+0.66f, val)); - } - - // create a dataset and give it a type - ScatterDataSet set1 = new ScatterDataSet(yVals1, "DS 1"); - set1.setScatterShape(ScatterChart.ScatterShape.SQUARE); - set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); - ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); - set2.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); - set2.setScatterShapeHoleRadius(3f); - set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); - ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); - set3.setShapeRenderer(new CustomScatterShapeRenderer()); - set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); - - set1.setScatterShapeSize(8f); - set2.setScatterShapeSize(8f); - set3.setScatterShapeSize(8f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - dataSets.add(set2); - dataSets.add(set3); - - // create a data object with the datasets - ScatterData data = new ScatterData(dataSets); - data.setValueTypeface(mTfLight); - - mChart.setData(data); - mChart.invalidate(); + protected void saveToGallery() { + saveToGallery(chart, "ScatterChartActivity"); } @Override @@ -217,20 +237,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java new file mode 100644 index 0000000000..37de64d728 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -0,0 +1,101 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +@SuppressWarnings("SameParameterValue") +public class ScrollViewActivity extends DemoBase { + + private BarChart chart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_scrollview); + + setTitle("ScrollViewActivity"); + + chart = findViewById(R.id.chart1); + + chart.getDescription().setEnabled(false); + + // scaling can now only be done on x- and y-axis separately + chart.setPinchZoom(false); + + chart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); + + XAxis xAxis = chart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setDrawGridLines(false); + + chart.getAxisLeft().setDrawGridLines(false); + + chart.getLegend().setEnabled(false); + + setData(10); + chart.setFitBars(true); + } + + private void setData(int count) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * count) + 15; + values.add(new BarEntry(i, (int) val)); + } + + BarDataSet set = new BarDataSet(values, "Data Set"); + set.setColors(ColorTemplate.VORDIPLOM_COLORS); + set.setDrawValues(false); + + BarData data = new BarData(set); + + chart.setData(data); + chart.invalidate(); + chart.animateY(800); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java similarity index 56% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 9951060177..676e0e62b0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -9,11 +14,9 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -34,8 +37,8 @@ public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,50 +47,52 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("StackedBarActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(40); + chart.setMaxVisibleValueCount(40); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(false); - mChart.setHighlightFullBarEnabled(false); + chart.setDrawValueAboveBar(false); + chart.setHighlightFullBarEnabled(false); // change the position of the y-labels - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); - XAxis xLabels = mChart.getXAxis(); + XAxis xLabels = chart.getXAxis(); xLabels.setPosition(XAxisPosition.TOP); - // mChart.setDrawXLabels(false); - // mChart.setDrawYLabels(false); + // chart.setDrawXLabels(false); + // chart.setDrawYLabels(false); // setting data - mSeekBarX.setProgress(12); - mSeekBarY.setProgress(100); + seekBarX.setProgress(12); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -96,7 +101,55 @@ protected void onCreate(Bundle savedInstanceState) { l.setFormToTextSpace(4f); l.setXEntrySpace(6f); - // mChart.setDrawLegend(false); + // chart.setDrawLegend(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float mul = (seekBarY.getProgress() + 1); + float val1 = (float) (Math.random() * mul) + mul / 3; + float val2 = (float) (Math.random() * mul) + mul / 3; + float val3 = (float) (Math.random() * mul) + mul / 3; + + values.add(new BarEntry( + i, + new float[]{val1, val2, val3}, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "Statistics Vienna 2014"); + set1.setDrawIcons(false); + set1.setColors(getColors()); + set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueFormatter(new MyValueFormatter()); + data.setValueTextColor(Color.WHITE); + + chart.setData(data); + } + + chart.setFitBars(true); + chart.invalidate(); } @Override @@ -109,8 +162,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -119,11 +178,11 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -132,55 +191,56 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawIcons(!set.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT).show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -188,64 +248,15 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val1 = (float) (Math.random() * mult) + mult / 3; - float val2 = (float) (Math.random() * mult) + mult / 3; - float val3 = (float) (Math.random() * mult) + mult / 3; - - yVals1.add(new BarEntry( - i, - new float[]{val1, val2, val3}, - getResources().getDrawable(R.drawable.star))); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setDrawIcons(false); - set1.setColors(getColors()); - set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(dataSets); - data.setValueFormatter(new MyValueFormatter()); - data.setValueTextColor(Color.WHITE); - - mChart.setData(data); - } - - mChart.setFitBars(true); - mChart.invalidate(); + protected void saveToGallery() { + saveToGallery(chart, "StackedBarActivity"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { @@ -259,21 +270,14 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} private int[] getColors() { - int stacksize = 3; - // have as many colors as stack-values per entry - int[] colors = new int[stacksize]; + int[] colors = new int[3]; - for (int i = 0; i < colors.length; i++) { - colors[i] = ColorTemplate.MATERIAL_COLORS[i]; - } + System.arraycopy(ColorTemplate.MATERIAL_COLORS, 0, colors, 0, 3); return colors; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java similarity index 59% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index c1d64a106b..7af58c85ca 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -1,18 +1,21 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; -import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -35,7 +38,7 @@ public class StackedBarActivityNegative extends DemoBase implements OnChartValueSelectedListener { - private HorizontalBarChart mChart; + private HorizontalBarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -44,30 +47,30 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_age_distribution); - setTitle("Age Distribution Austria"); + setTitle("StackedBarActivityNegative"); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); - mChart.setHighlightFullBarEnabled(false); - - mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setAxisMaximum(25f); - mChart.getAxisRight().setAxisMinimum(-25f); - mChart.getAxisRight().setDrawGridLines(false); - mChart.getAxisRight().setDrawZeroLine(true); - mChart.getAxisRight().setLabelCount(7, false); - mChart.getAxisRight().setValueFormatter(new CustomFormatter()); - mChart.getAxisRight().setTextSize(9f); - - XAxis xAxis = mChart.getXAxis(); + chart.setPinchZoom(false); + + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); + chart.setHighlightFullBarEnabled(false); + + chart.getAxisLeft().setEnabled(false); + chart.getAxisRight().setAxisMaximum(25f); + chart.getAxisRight().setAxisMinimum(-25f); + chart.getAxisRight().setDrawGridLines(false); + chart.getAxisRight().setDrawZeroLine(true); + chart.getAxisRight().setLabelCount(7, false); + chart.getAxisRight().setValueFormatter(new CustomFormatter()); + chart.getAxisRight().setTextSize(9f); + + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); @@ -79,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(10f); xAxis.setValueFormatter(new IAxisValueFormatter() { - private DecimalFormat format = new DecimalFormat("###"); + private final DecimalFormat format = new DecimalFormat("###"); @Override public String getFormattedValue(float value, AxisBase axis) { @@ -87,7 +90,7 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -97,36 +100,34 @@ public String getFormattedValue(float value, AxisBase axis) { l.setXEntrySpace(6f); // IMPORTANT: When using negative values in stacked bars, always make sure the negative values are in the array first - ArrayList yValues = new ArrayList(); - yValues.add(new BarEntry(5, new float[]{ -10, 10 })); - yValues.add(new BarEntry(15, new float[]{ -12, 13 })); - yValues.add(new BarEntry(25, new float[]{ -15, 15 })); - yValues.add(new BarEntry(35, new float[]{ -17, 17 })); - yValues.add(new BarEntry(45, new float[]{ -19, 20 })); - yValues.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); - yValues.add(new BarEntry(55, new float[]{ -19, 19 })); - yValues.add(new BarEntry(65, new float[]{ -16, 16 })); - yValues.add(new BarEntry(75, new float[]{ -13, 14 })); - yValues.add(new BarEntry(85, new float[]{ -10, 11 })); - yValues.add(new BarEntry(95, new float[]{ -5, 6 })); - yValues.add(new BarEntry(105, new float[]{ -1, 2 })); - - BarDataSet set = new BarDataSet(yValues, "Age Distribution"); + ArrayList values = new ArrayList<>(); + values.add(new BarEntry(5, new float[]{ -10, 10 })); + values.add(new BarEntry(15, new float[]{ -12, 13 })); + values.add(new BarEntry(25, new float[]{ -15, 15 })); + values.add(new BarEntry(35, new float[]{ -17, 17 })); + values.add(new BarEntry(45, new float[]{ -19, 20 })); + values.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); + values.add(new BarEntry(55, new float[]{ -19, 19 })); + values.add(new BarEntry(65, new float[]{ -16, 16 })); + values.add(new BarEntry(75, new float[]{ -13, 14 })); + values.add(new BarEntry(85, new float[]{ -10, 11 })); + values.add(new BarEntry(95, new float[]{ -5, 6 })); + values.add(new BarEntry(105, new float[]{ -1, 2 })); + + BarDataSet set = new BarDataSet(values, "Age Distribution"); set.setDrawIcons(false); set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); - set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); + set.setColors(Color.rgb(67,67,72), Color.rgb(124,181,236)); set.setStackLabels(new String[]{ "Men", "Women" }); - String []xLabels = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; - BarData data = new BarData(set); data.setBarWidth(8.5f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } @Override @@ -139,8 +140,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -149,11 +156,11 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -162,57 +169,56 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawIcons(!set.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(3000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(3000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(3000, 3000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -220,8 +226,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onValueSelected(Entry e, Highlight h) { + protected void saveToGallery() { + saveToGallery(chart, "StackedBarActivityNegative"); + } + @Override + public void onValueSelected(Entry e, Highlight h) { BarEntry entry = (BarEntry) e; Log.i("VAL SELECTED", "Value: " + Math.abs(entry.getYVals()[h.getStackIndex()])); @@ -229,16 +239,14 @@ public void onValueSelected(Entry e, Highlight h) { @Override public void onNothingSelected() { - // TODO Auto-generated method stub Log.i("NOTING SELECTED", ""); } - private class CustomFormatter implements IValueFormatter, IAxisValueFormatter - { + private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; - public CustomFormatter() { + CustomFormatter() { mFormat = new DecimalFormat("###"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java similarity index 97% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index b8bc1a41c2..ba4d860d92 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -10,11 +10,11 @@ public class DayAxisValueFormatter implements IAxisValueFormatter { - protected String[] mMonths = new String[]{ + private final String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - private BarLineChartBase chart; + private final BarLineChartBase chart; public DayAxisValueFormatter(BarLineChartBase chart) { this.chart = chart; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java similarity index 92% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index e8456675a9..e7cdbfcd10 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -8,7 +8,7 @@ public class MyAxisValueFormatter implements IAxisValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; public MyAxisValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java similarity index 85% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index c66e5d4569..bea4908ef2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -8,12 +8,15 @@ /** * Created by Philipp Jahoda on 14/09/15. + * + * @deprecated The {@link MyAxisValueFormatter} does exactly the same thing and is more functional. */ +@Deprecated public class MyCustomXAxisValueFormatter implements IAxisValueFormatter { - private DecimalFormat mFormat; - private ViewPortHandler mViewPortHandler; + private final DecimalFormat mFormat; + private final ViewPortHandler mViewPortHandler; public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { mViewPortHandler = viewPortHandler; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java similarity index 77% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index e4b94c331f..2ca87b2f0f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -7,18 +7,19 @@ /** * Created by Philipp Jahoda on 12/09/15. */ +@SuppressWarnings("unused") public class MyFillFormatter implements IFillFormatter { - private float mFillPos = 0f; + private float fillPos; - public MyFillFormatter(float fillpos) { - this.mFillPos = fillpos; + public MyFillFormatter(float fillPos) { + this.fillPos = fillPos; } @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { // your logic could be here - return mFillPos; + return fillPos; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java similarity index 77% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index ef20bda3b7..2c1da9b4e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -14,12 +15,13 @@ /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class MyMarkerView extends MarkerView { - private TextView tvContent; + private final TextView tvContent; public MyMarkerView(Context context, int layoutResource) { super(context, layoutResource); @@ -27,7 +29,7 @@ public MyMarkerView(Context context, int layoutResource) { tvContent = findViewById(R.id.tvContent); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { @@ -36,10 +38,10 @@ public void refreshContent(Entry e, Highlight highlight) { CandleEntry ce = (CandleEntry) e; - tvContent.setText("" + Utils.formatNumber(ce.getHigh(), 0, true)); + tvContent.setText(Utils.formatNumber(ce.getHigh(), 0, true)); } else { - tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(e.getY(), 0, true)); } super.refreshContent(e, highlight); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java similarity index 93% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index cbf5fd56c8..ec1c119818 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -9,8 +9,8 @@ public class MyValueFormatter implements IValueFormatter { - private DecimalFormat mFormat; - + private final DecimalFormat mFormat; + public MyValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java similarity index 76% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 12b473f7d0..ca057a5aa3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -1,29 +1,29 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.widget.TextView; import com.github.mikephil.charting.components.MarkerView; -import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; import java.text.DecimalFormat; /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class RadarMarkerView extends MarkerView { - private TextView tvContent; - private DecimalFormat format = new DecimalFormat("##0"); + private final TextView tvContent; + private final DecimalFormat format = new DecimalFormat("##0"); public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); @@ -32,11 +32,11 @@ public RadarMarkerView(Context context, int layoutResource) { tvContent.setTypeface(Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf")); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(format.format(e.getY()) + " %"); + tvContent.setText(String.format("%s %%", format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java similarity index 76% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 487705bb7d..554ef2fe27 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -14,9 +15,11 @@ /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressWarnings("unused") +@SuppressLint("ViewConstructor") public class StackedBarsMarkerView extends MarkerView { private TextView tvContent; @@ -27,7 +30,7 @@ public StackedBarsMarkerView(Context context, int layoutResource) { tvContent = findViewById(R.id.tvContent); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { @@ -39,13 +42,13 @@ public void refreshContent(Entry e, Highlight highlight) { if(be.getYVals() != null) { // draw the stack value - tvContent.setText("" + Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); + tvContent.setText(Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); } else { - tvContent.setText("" + Utils.formatNumber(be.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(be.getY(), 0, true)); } } else { - tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(e.getY(), 0, true)); } super.refreshContent(e, highlight); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java similarity index 73% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 0475bdd038..51e4247d35 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -18,12 +19,13 @@ * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class XYMarkerView extends MarkerView { - private TextView tvContent; - private IAxisValueFormatter xAxisValueFormatter; + private final TextView tvContent; + private final IAxisValueFormatter xAxisValueFormatter; - private DecimalFormat format; + private final DecimalFormat format; public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); @@ -33,12 +35,12 @@ public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { format = new DecimalFormat("###.0"); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText("x: " + xAxisValueFormatter.getFormattedValue(e.getX(), null) + ", y: " + format.format(e.getY())); + tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX(), null), format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java similarity index 82% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index 34d76c25eb..7122e0d80c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -6,16 +6,16 @@ /** * Created by Philipp Jahoda on 14/09/15. */ +@SuppressWarnings("unused") public class YearXAxisFormatter implements IAxisValueFormatter { - protected String[] mMonths = new String[]{ + private final String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; public YearXAxisFormatter() { - // maybe do something here or provide parameters in constructor - + // take parameters to change behavior of formatter } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java similarity index 68% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 655fc6bb25..4bcc543722 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -21,48 +22,49 @@ public class BarChartFrag extends SimpleFragment implements OnChartGestureListener { + @NonNull public static Fragment newInstance() { return new BarChartFrag(); } - private BarChart mChart; - + private BarChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_bar, container, false); - + // create a new chart object - mChart = new BarChart(getActivity()); - mChart.getDescription().setEnabled(false); - mChart.setOnChartGestureListener(this); - + chart = new BarChart(getActivity()); + chart.getDescription().setEnabled(false); + chart.setOnChartGestureListener(this); + MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); - - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - mChart.setData(generateBarData(1, 20000, 12)); - - Legend l = mChart.getLegend(); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); + + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + chart.setData(generateBarData(1, 20000, 12)); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - - // programatically add the chart + + // programmatically add the chart FrameLayout parent = v.findViewById(R.id.parentLayout); - parent.addView(mChart); - + parent.addView(chart); + return v; } @@ -74,12 +76,12 @@ public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture @Override public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "END"); - mChart.highlightValues(null); + chart.highlightValues(null); } @Override public void onChartLongPressed(MotionEvent me) { - Log.i("LongPress", "Chart longpressed."); + Log.i("LongPress", "Chart long pressed."); } @Override @@ -94,9 +96,9 @@ public void onChartSingleTapped(MotionEvent me) { @Override public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY); + Log.i("Fling", "Chart fling. VelocityX: " + velocityX + ", VelocityY: " + velocityY); } - + @Override public void onChartScale(MotionEvent me, float scaleX, float scaleY) { Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java similarity index 52% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index b960e9ae0c..9edee8bdfb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,38 +16,40 @@ public class ComplexityFragment extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new ComplexityFragment(); } - private LineChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private LineChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - - mChart = v.findViewById(R.id.lineChart1); - - mChart.getDescription().setEnabled(false); - - mChart.setDrawGridBackground(false); - - mChart.setData(getComplexity()); - mChart.animateX(3000); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - Legend l = mChart.getLegend(); + + chart = v.findViewById(R.id.lineChart1); + + chart.getDescription().setEnabled(false); + + chart.setDrawGridBackground(false); + + chart.setData(getComplexity()); + chart.animateX(3000); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); - - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java similarity index 61% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index 946532ac40..5de9a46ea3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -2,7 +2,8 @@ import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -12,44 +13,45 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.xxmassdeveloper.mpchartexample.R; public class PieChartFrag extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new PieChartFrag(); } - private PieChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private PieChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_pie, container, false); - - mChart = v.findViewById(R.id.pieChart1); - mChart.getDescription().setEnabled(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf"); - - mChart.setCenterTextTypeface(tf); - mChart.setCenterText(generateCenterText()); - mChart.setCenterTextSize(10f); - mChart.setCenterTextTypeface(tf); - + + chart = v.findViewById(R.id.pieChart1); + chart.getDescription().setEnabled(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + chart.setCenterTextTypeface(tf); + chart.setCenterText(generateCenterText()); + chart.setCenterTextSize(10f); + chart.setCenterTextTypeface(tf); + // radius of the center hole in percent of maximum radius - mChart.setHoleRadius(45f); - mChart.setTransparentCircleRadius(50f); - - Legend l = mChart.getLegend(); + chart.setHoleRadius(45f); + chart.setTransparentCircleRadius(50f); + + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - - mChart.setData(generatePieData()); - + + chart.setData(generatePieData()); + return v; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java similarity index 59% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index b8a3f0f324..d5d292bf0b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -2,7 +2,8 @@ import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,49 +19,51 @@ public class ScatterChartFrag extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new ScatterChartFrag(); } - private ScatterChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private ScatterChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_scatter, container, false); - - mChart = v.findViewById(R.id.scatterChart1); - mChart.getDescription().setEnabled(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - + + chart = v.findViewById(R.id.scatterChart1); + chart.getDescription().setEnabled(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); + + chart.setDrawGridBackground(false); + chart.setData(generateScatterData(6, 10000, 200)); - mChart.setDrawGridBackground(false); - mChart.setData(generateScatterData(6, 10000, 200)); - - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(true); xAxis.setPosition(XAxisPosition.BOTTOM); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setDrawGridLines(false); - - Legend l = mChart.getLegend(); + + Legend l = chart.getLegend(); l.setWordWrapEnabled(true); l.setTypeface(tf); l.setFormSize(14f); l.setTextSize(9f); - + // increase the space between legend & bottom and legend & content - l.setYOffset(13f); - mChart.setExtraBottomOffset(16f); - + l.setYOffset(13f); + chart.setExtraBottomOffset(16f); + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java similarity index 65% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java index ee64ffdfce..32b78142b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java @@ -4,11 +4,15 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.xxmassdeveloper.mpchartexample.R; @@ -16,7 +20,7 @@ /** * Demonstrates how to keep your charts straight forward, simple and beautiful with the MPAndroidChart library. - * + * * @author Philipp Jahoda */ public class SimpleChartDemo extends DemoBase { @@ -26,21 +30,22 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_awesomedesign); + setTitle("SimpleChartDemo"); + ViewPager pager = findViewById(R.id.pager); pager.setOffscreenPageLimit(3); - + PageAdapter a = new PageAdapter(getSupportFragmentManager()); pager.setAdapter(a); - - + + AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle("This is a ViewPager."); b.setMessage("Swipe left and right for more awesome design examples!"); b.setPositiveButton("OK", new OnClickListener() { - + @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); @@ -48,17 +53,17 @@ public void onClick(DialogInterface dialog, int which) { }); b.show(); } - + private class PageAdapter extends FragmentPagerAdapter { - public PageAdapter(FragmentManager fm) { - super(fm); + PageAdapter(FragmentManager fm) { + super(fm); } @Override - public Fragment getItem(int pos) { + public Fragment getItem(int pos) { Fragment f = null; - + switch(pos) { case 0: f = SineCosineFragment.newInstance(); @@ -83,6 +88,30 @@ public Fragment getItem(int pos) { @Override public int getCount() { return 5; - } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java similarity index 70% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 22b35e4963..ab70041e60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -1,9 +1,11 @@ package com.xxmassdeveloper.mpchartexample.fragments; +import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -28,58 +30,64 @@ import java.util.ArrayList; +@SuppressWarnings({"SameParameterValue", "WeakerAccess"}) public abstract class SimpleFragment extends Fragment { - + private Typeface tf; - + protected Context context; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.context = context; + } + public SimpleFragment() { - + } - + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Regular.ttf"); + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf"); return super.onCreateView(inflater, container, savedInstanceState); } protected BarData generateBarData(int dataSets, float range, int count) { - - ArrayList sets = new ArrayList(); - + + ArrayList sets = new ArrayList<>(); + for(int i = 0; i < dataSets; i++) { - - ArrayList entries = new ArrayList(); - -// entries = FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "stacked_bars.txt"); - - for(int j = 0; j < count; j++) { + + ArrayList entries = new ArrayList<>(); + + for(int j = 0; j < count; j++) { entries.add(new BarEntry(j, (float) (Math.random() * range) + range / 4)); } - + BarDataSet ds = new BarDataSet(entries, getLabel(i)); ds.setColors(ColorTemplate.VORDIPLOM_COLORS); sets.add(ds); } - + BarData d = new BarData(sets); d.setValueTypeface(tf); return d; } - + protected ScatterData generateScatterData(int dataSets, float range, int count) { - - ArrayList sets = new ArrayList(); - + + ArrayList sets = new ArrayList<>(); + ScatterChart.ScatterShape[] shapes = ScatterChart.ScatterShape.getAllDefaultShapes(); - + for(int i = 0; i < dataSets; i++) { - - ArrayList entries = new ArrayList(); - - for(int j = 0; j < count; j++) { + + ArrayList entries = new ArrayList<>(); + + for(int j = 0; j < count; j++) { entries.add(new Entry(j, (float) (Math.random() * range) + range / 4)); } - + ScatterDataSet ds = new ScatterDataSet(entries, getLabel(i)); ds.setScatterShapeSize(12f); ds.setScatterShape(shapes[i % shapes.length]); @@ -87,82 +95,81 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) ds.setScatterShapeSize(9f); sets.add(ds); } - + ScatterData d = new ScatterData(sets); d.setValueTypeface(tf); return d; } - + /** * generates less data (1 DataSet, 4 values) - * @return + * @return PieData */ protected PieData generatePieData() { - + int count = 4; - - ArrayList entries1 = new ArrayList(); - + + ArrayList entries1 = new ArrayList<>(); + for(int i = 0; i < count; i++) { entries1.add(new PieEntry((float) ((Math.random() * 60) + 40), "Quarter " + (i+1))); } - + PieDataSet ds1 = new PieDataSet(entries1, "Quarterly Revenues 2015"); ds1.setColors(ColorTemplate.VORDIPLOM_COLORS); ds1.setSliceSpace(2f); ds1.setValueTextColor(Color.WHITE); ds1.setValueTextSize(12f); - + PieData d = new PieData(ds1); d.setValueTypeface(tf); return d; } - + protected LineData generateLineData() { - - ArrayList sets = new ArrayList(); - - LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "sine.txt"), "Sine function"); - LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "cosine.txt"), "Cosine function"); - + + ArrayList sets = new ArrayList<>(); + LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "sine.txt"), "Sine function"); + LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "cosine.txt"), "Cosine function"); + ds1.setLineWidth(2f); ds2.setLineWidth(2f); - + ds1.setDrawCircles(false); ds2.setDrawCircles(false); - + ds1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setColor(ColorTemplate.VORDIPLOM_COLORS[1]); - - // load DataSets from textfiles in assets folders + + // load DataSets from files in assets folder sets.add(ds1); sets.add(ds2); - + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } - + protected LineData getComplexity() { - - ArrayList sets = new ArrayList(); - - LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "n.txt"), "O(n)"); - LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "nlogn.txt"), "O(nlogn)"); - LineDataSet ds3 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "square.txt"), "O(n\u00B2)"); - LineDataSet ds4 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "three.txt"), "O(n\u00B3)"); - + + ArrayList sets = new ArrayList<>(); + + LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "n.txt"), "O(n)"); + LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "nlogn.txt"), "O(nlogn)"); + LineDataSet ds3 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "square.txt"), "O(n\u00B2)"); + LineDataSet ds4 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "three.txt"), "O(n\u00B3)"); + ds1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setColor(ColorTemplate.VORDIPLOM_COLORS[1]); ds3.setColor(ColorTemplate.VORDIPLOM_COLORS[2]); ds4.setColor(ColorTemplate.VORDIPLOM_COLORS[3]); - + ds1.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[1]); ds3.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[2]); ds4.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[3]); - + ds1.setLineWidth(2.5f); ds1.setCircleRadius(3f); ds2.setLineWidth(2.5f); @@ -171,22 +178,21 @@ protected LineData getComplexity() { ds3.setCircleRadius(3f); ds4.setLineWidth(2.5f); ds4.setCircleRadius(3f); - - - // load DataSets from textfiles in assets folders - sets.add(ds1); + + + // load DataSets from files in assets folder + sets.add(ds1); sets.add(ds2); sets.add(ds3); sets.add(ds4); - + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } - - private String[] mLabels = new String[] { "Company A", "Company B", "Company C", "Company D", "Company E", "Company F" }; -// private String[] mXVals = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; - + + private final String[] mLabels = new String[] { "Company A", "Company B", "Company C", "Company D", "Company E", "Company F" }; + private String getLabel(int i) { return mLabels[i]; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java similarity index 54% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 7e425172fb..0581529308 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,40 +16,42 @@ public class SineCosineFragment extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new SineCosineFragment(); } - private LineChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private LineChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - - mChart = v.findViewById(R.id.lineChart1); - - mChart.getDescription().setEnabled(false); - - mChart.setDrawGridBackground(false); - - mChart.setData(generateLineData()); - mChart.animateX(3000); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - Legend l = mChart.getLegend(); + + chart = v.findViewById(R.id.lineChart1); + + chart.getDescription().setEnabled(false); + + chart.setDrawGridBackground(false); + + chart.setData(generateLineData()); + chart.animateX(3000); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setAxisMaximum(1.2f); leftAxis.setAxisMinimum(-1.2f); - - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java similarity index 94% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index c09297a391..eeb1791fe1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -1,5 +1,6 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; @@ -14,9 +15,9 @@ import com.xxmassdeveloper.mpchartexample.R; public class BarChartItem extends ChartItem { - - private Typeface mTf; - + + private final Typeface mTf; + public BarChartItem(ChartData cd, Context c) { super(cd); @@ -28,10 +29,11 @@ public int getItemType() { return TYPE_BARCHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -57,13 +59,13 @@ public View getView(int position, View convertView, Context c) { xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(true); - + YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(20f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - + YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); @@ -71,18 +73,18 @@ public View getView(int position, View convertView, Context c) { rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChartData.setValueTypeface(mTf); - + // set data holder.chart.setData((BarData) mChartData); holder.chart.setFitBars(true); - + // do not forget to refresh the chart // holder.chart.invalidate(); holder.chart.animateY(700); return convertView; } - + private static class ViewHolder { BarChart chart; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java similarity index 51% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java index 0e6182165c..2a8ed0561d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java @@ -6,23 +6,24 @@ import com.github.mikephil.charting.data.ChartData; /** - * baseclass of the chart-listview items + * Base class of the Chart ListView items * @author philipp * */ +@SuppressWarnings("unused") public abstract class ChartItem { - - protected static final int TYPE_BARCHART = 0; - protected static final int TYPE_LINECHART = 1; - protected static final int TYPE_PIECHART = 2; - - protected ChartData mChartData; - - public ChartItem(ChartData cd) { - this.mChartData = cd; + + static final int TYPE_BARCHART = 0; + static final int TYPE_LINECHART = 1; + static final int TYPE_PIECHART = 2; + + ChartData mChartData; + + ChartItem(ChartData cd) { + this.mChartData = cd; } - + public abstract int getItemType(); - + public abstract View getView(int position, View convertView, Context c); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java similarity index 94% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 107930af2a..d69b010322 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; @@ -16,7 +17,7 @@ public class LineChartItem extends ChartItem { - private Typeface mTf; + private final Typeface mTf; public LineChartItem(ChartData cd, Context c) { super(cd); @@ -29,10 +30,11 @@ public int getItemType() { return TYPE_LINECHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -63,7 +65,7 @@ public View getView(int position, View convertView, Context c) { leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - + YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java similarity index 94% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 5503018792..916f8dc5e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; @@ -12,7 +13,6 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.formatter.PercentFormatter; @@ -21,8 +21,8 @@ public class PieChartItem extends ChartItem { - private Typeface mTf; - private SpannableString mCenterText; + private final Typeface mTf; + private final SpannableString mCenterText; public PieChartItem(ChartData cd, Context c) { super(cd); @@ -36,10 +36,11 @@ public int getItemType() { return TYPE_PIECHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java new file mode 100644 index 0000000000..f322090d72 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java @@ -0,0 +1,22 @@ +package com.xxmassdeveloper.mpchartexample.notimportant; + +/** + * Created by Philipp Jahoda on 07/12/15. + */ +class ContentItem { + + final String name; + final String desc; + boolean isSection = false; + + ContentItem(String n) { + name = n; + desc = ""; + isSection = true; + } + + ContentItem(String n, String d) { + name = n; + desc = d; + } +} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java new file mode 100644 index 0000000000..a963609aff --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -0,0 +1,99 @@ + +package com.xxmassdeveloper.mpchartexample.notimportant; + +import android.Manifest; +import android.content.pm.PackageManager; +import android.graphics.Typeface; +import android.os.Bundle; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.material.snackbar.Snackbar; + +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import android.view.View; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.Chart; +import com.xxmassdeveloper.mpchartexample.R; + +/** + * Base class of all Activities of the Demo Application. + * + * @author Philipp Jahoda + */ +public abstract class DemoBase extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { + + protected final String[] months = new String[] { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + }; + + protected final String[] parties = new String[] { + "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H", + "Party I", "Party J", "Party K", "Party L", "Party M", "Party N", "Party O", "Party P", + "Party Q", "Party R", "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", + "Party Y", "Party Z" + }; + + private static final int PERMISSION_STORAGE = 0; + + protected Typeface tfRegular; + protected Typeface tfLight; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + tfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); + } + + protected float getRandom(float range, float start) { + return (float) (Math.random() * range) + start; + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + overridePendingTransition(R.anim.move_left_in_activity, R.anim.move_right_out_activity); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == PERMISSION_STORAGE) { + if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + } + } + } + + protected void requestStoragePermission(View view) { + if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + Snackbar.make(view, "Write permission is required to save image to gallery", Snackbar.LENGTH_INDEFINITE) + .setAction(android.R.string.ok, new View.OnClickListener() { + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE); + } + }).show(); + } else { + Toast.makeText(getApplicationContext(), "Permission Required!", Toast.LENGTH_SHORT) + .show(); + ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE); + } + } + + protected void saveToGallery(Chart chart, String name) { + if (chart.saveToGallery(name + "_" + System.currentTimeMillis(), 70)) + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + } + + protected abstract void saveToGallery(); +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java similarity index 55% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index d994f87c96..88e5dc8d8b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample.notimportant; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -27,6 +26,7 @@ import com.xxmassdeveloper.mpchartexample.FilledLineActivity; import com.xxmassdeveloper.mpchartexample.HalfPieChartActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; +import com.xxmassdeveloper.mpchartexample.HorizontalBarNegativeChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; import com.xxmassdeveloper.mpchartexample.LineChartActivity2; @@ -46,11 +46,12 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; -import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; -public class MainActivity extends Activity implements OnItemClickListener { +import androidx.appcompat.app.AppCompatActivity; + +public class MainActivity extends AppCompatActivity implements OnItemClickListener { @Override protected void onCreate(Bundle savedInstanceState) { @@ -64,88 +65,64 @@ protected void onCreate(Bundle savedInstanceState) { // initialize the utilities Utils.init(this); - ArrayList objects = new ArrayList(); - - objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); - objects.add(new ContentItem("Line Chart (Dual YAxis)", - "Demonstration of the linechart with dual y-axis.")); - objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); - objects.add(new ContentItem("Horizontal Bar Chart", - "A simple demonstration of the horizontal bar chart.")); - objects.add(new ContentItem("Combined Chart", - "Demonstrates how to create a combined chart (bar and line in this case).")); - objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); - objects.add(new ContentItem("Pie Chart with value lines", "A simple demonstration of the pie chart with polyline notes.")); - objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); - objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); - objects.add(new ContentItem("Stacked Bar Chart", - "A simple demonstration of a bar chart with stacked bars.")); - objects.add(new ContentItem("Stacked Bar Chart Negative", - "A simple demonstration of stacked bars with negative and positive values.")); - objects.add(new ContentItem("Another Bar Chart", - "Implementation of a BarChart that only shows values at the bottom.")); - objects.add(new ContentItem("Multiple Lines Chart", - "A line chart with multiple DataSet objects. One color per DataSet.")); - objects.add(new ContentItem("Multiple Bars Chart", - "A bar chart with multiple DataSet objects. One multiple colors per DataSet.")); - objects.add(new ContentItem( - "Charts in ViewPager Fragments", - "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the" + - " chart.")); - objects.add(new ContentItem( - "BarChart inside ListView", - "Demonstrates the usage of a BarChart inside a ListView item.")); - objects.add(new ContentItem( - "Multiple charts inside ListView", - "Demonstrates the usage of different chart types inside a ListView.")); - objects.add(new ContentItem( - "Inverted Line Chart", - "Demonstrates the feature of inverting the y-axis.")); - objects.add(new ContentItem( - "Candle Stick Chart", - "Demonstrates usage of the CandleStickChart.")); - objects.add(new ContentItem( - "Cubic Line Chart", - "Demonstrates cubic lines in a LineChart.")); - objects.add(new ContentItem( - "Radar Chart", - "Demonstrates the use of a spider-web like (net) chart.")); - objects.add(new ContentItem( - "Colored Line Chart", - "Shows a LineChart with different background and line color.")); - objects.add(new ContentItem( - "Realtime Chart", - "This chart is fed with new data in realtime. It also restrains the view on the x-axis.")); - objects.add(new ContentItem( - "Dynamical data adding", - "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); - objects.add(new ContentItem( - "Performance Line Chart", - "Renders up to 30.000 objects smoothly.")); - objects.add(new ContentItem( - "Sinus Bar Chart", - "A Bar Chart plotting the sinus function with 8.000 values.")); - objects.add(new ContentItem( - "Chart in ScrollView", - "This demonstrates how to use a chart inside a ScrollView.")); - objects.add(new ContentItem( - "BarChart positive / negative", - "This demonstrates how to create a BarChart with positive and negative values in different colors.")); - - ContentItem realm = new ContentItem( - "Realm.io Database", - "This demonstrates how to use this library with Realm.io mobile database."); - objects.add(realm); - objects.add(new ContentItem( - "Time Chart", - "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in " + - "milliseconds.")); - objects.add(new ContentItem( - "Filled LineChart", - "This demonstrates how to fill an area between two LineDataSets.")); - objects.add(new ContentItem( - "Half PieChart", - "This demonstrates how to create a 180 degree PieChart.")); + ArrayList objects = new ArrayList<>(); + + //// + objects.add(0, new ContentItem("Line Charts")); + + objects.add(1, new ContentItem("Basic", "Simple line chart.")); + objects.add(2, new ContentItem("Multiple", "Show multiple data sets.")); + objects.add(3, new ContentItem("Dual Axis", "Line chart with dual y-axes.")); + objects.add(4, new ContentItem("Inverted Axis", "Inverted y-axis.")); + objects.add(5, new ContentItem("Cubic", "Line chart with a cubic line shape.")); + objects.add(6, new ContentItem("Colorful", "Colorful line chart.")); + objects.add(7, new ContentItem("Performance", "Render 30.000 data points smoothly.")); + objects.add(8, new ContentItem("Filled", "Colored area between two lines.")); + + //// + objects.add(9, new ContentItem("Bar Charts")); + + objects.add(10, new ContentItem("Basic", "Simple bar chart.")); + objects.add(11, new ContentItem("Basic 2", "Variation of the simple bar chart.")); + objects.add(12, new ContentItem("Multiple", "Show multiple data sets.")); + objects.add(13, new ContentItem("Horizontal", "Render bar chart horizontally.")); + objects.add(14, new ContentItem("Stacked", "Stacked bar chart.")); + objects.add(15, new ContentItem("Negative", "Positive and negative values with unique colors.")); + objects.add(16, new ContentItem("Negative Horizontal", "demonstrates how to create a HorizontalBarChart with positive and negative values.")); + objects.add(17, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); + objects.add(18, new ContentItem("Sine", "Sine function in bar chart format.")); + + //// + objects.add(19, new ContentItem("Pie Charts")); + + objects.add(20, new ContentItem("Basic", "Simple pie chart.")); + objects.add(21, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); + objects.add(22, new ContentItem("Half Pie", "180° (half) pie chart.")); + + //// + objects.add(23, new ContentItem("Other Charts")); + + objects.add(24, new ContentItem("Combined Chart", "Bar and line chart together.")); + objects.add(25, new ContentItem("Scatter Plot", "Simple scatter plot.")); + objects.add(26, new ContentItem("Bubble Chart", "Simple bubble chart.")); + objects.add(27, new ContentItem("Candlestick", "Simple financial chart.")); + objects.add(28, new ContentItem("Radar Chart", "Simple web chart.")); + + //// + objects.add(29, new ContentItem("Scrolling Charts")); + + objects.add(30, new ContentItem("Multiple", "Various types of charts as fragments.")); + objects.add(31, new ContentItem("View Pager", "Swipe through different charts.")); + objects.add(32, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); + objects.add(33, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); + + //// + objects.add(34, new ContentItem("Even More Line Charts")); + + objects.add(35, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); + objects.add(36, new ContentItem("Realtime", "Add data points in realtime.")); + objects.add(37, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); + //objects.add(38, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -158,140 +135,112 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onItemClick(AdapterView av, View v, int pos, long arg3) { - Intent i; + Intent i = null; switch (pos) { - case 0: - i = new Intent(this, LineChartActivity1.class); - startActivity(i); - break; case 1: - i = new Intent(this, LineChartActivity2.class); - startActivity(i); + i = new Intent(this, LineChartActivity1.class); break; case 2: - i = new Intent(this, BarChartActivity.class); - startActivity(i); + i = new Intent(this, MultiLineChartActivity.class); break; case 3: - i = new Intent(this, HorizontalBarChartActivity.class); - startActivity(i); + i = new Intent(this, LineChartActivity2.class); break; case 4: - i = new Intent(this, CombinedChartActivity.class); - startActivity(i); + i = new Intent(this, InvertedLineChartActivity.class); break; case 5: - i = new Intent(this, PieChartActivity.class); - startActivity(i); + i = new Intent(this, CubicLineChartActivity.class); break; case 6: - i = new Intent(this, PiePolylineChartActivity.class); - startActivity(i); + i = new Intent(this, LineChartActivityColored.class); break; case 7: - i = new Intent(this, ScatterChartActivity.class); - startActivity(i); + i = new Intent(this, PerformanceLineChart.class); break; case 8: - i = new Intent(this, BubbleChartActivity.class); - startActivity(i); - break; - case 9: - i = new Intent(this, StackedBarActivity.class); - startActivity(i); + i = new Intent(this, FilledLineActivity.class); break; case 10: - i = new Intent(this, StackedBarActivityNegative.class); - startActivity(i); + i = new Intent(this, BarChartActivity.class); break; case 11: i = new Intent(this, AnotherBarActivity.class); - startActivity(i); break; case 12: - i = new Intent(this, MultiLineChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartActivityMultiDataset.class); break; case 13: - i = new Intent(this, BarChartActivityMultiDataset.class); - startActivity(i); + i = new Intent(this, HorizontalBarChartActivity.class); break; case 14: - i = new Intent(this, SimpleChartDemo.class); - startActivity(i); + i = new Intent(this, StackedBarActivity.class); break; case 15: - i = new Intent(this, ListViewBarChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartPositiveNegative.class); break; case 16: - i = new Intent(this, ListViewMultiChartActivity.class); - startActivity(i); + i = new Intent(this, HorizontalBarNegativeChartActivity.class); break; case 17: - i = new Intent(this, InvertedLineChartActivity.class); - startActivity(i); + i = new Intent(this, StackedBarActivityNegative.class); break; case 18: - i = new Intent(this, CandleStickChartActivity.class); - startActivity(i); - break; - case 19: - i = new Intent(this, CubicLineChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartActivitySinus.class); break; case 20: - i = new Intent(this, RadarChartActivity.class); - startActivity(i); + i = new Intent(this, PieChartActivity.class); break; case 21: - i = new Intent(this, LineChartActivityColored.class); - startActivity(i); + i = new Intent(this, PiePolylineChartActivity.class); break; case 22: - i = new Intent(this, RealtimeLineChartActivity.class); - startActivity(i); - break; - case 23: - i = new Intent(this, DynamicalAddingActivity.class); - startActivity(i); + i = new Intent(this, HalfPieChartActivity.class); break; case 24: - i = new Intent(this, PerformanceLineChart.class); - startActivity(i); + i = new Intent(this, CombinedChartActivity.class); break; case 25: - i = new Intent(this, BarChartActivitySinus.class); - startActivity(i); + i = new Intent(this, ScatterChartActivity.class); break; case 26: - i = new Intent(this, ScrollViewActivity.class); - startActivity(i); + i = new Intent(this, BubbleChartActivity.class); break; case 27: - i = new Intent(this, BarChartPositiveNegative.class); - startActivity(i); + i = new Intent(this, CandleStickChartActivity.class); break; case 28: - i = new Intent(this, RealmMainActivity.class); - startActivity(i); - break; - case 29: - i = new Intent(this, LineChartTime.class); - startActivity(i); + i = new Intent(this, RadarChartActivity.class); break; case 30: - i = new Intent(this, FilledLineActivity.class); - startActivity(i); + i = new Intent(this, ListViewMultiChartActivity.class); break; case 31: - i = new Intent(this, HalfPieChartActivity.class); - startActivity(i); + i = new Intent(this, SimpleChartDemo.class); break; - + case 32: + i = new Intent(this, ScrollViewActivity.class); + break; + case 33: + i = new Intent(this, ListViewBarChartActivity.class); + break; + case 35: + i = new Intent(this, DynamicalAddingActivity.class); + break; + case 36: + i = new Intent(this, RealtimeLineChartActivity.class); + break; + case 37: + i = new Intent(this, LineChartTime.class); + break; + /*case 38: + i = new Intent(this, RealmMainActivity.class); + break;*/ } + if (i != null) startActivity(i); + overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); } @@ -304,7 +253,7 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { - Intent i = null; + Intent i; switch (item.getItemId()) { case R.id.viewGithub: @@ -319,11 +268,6 @@ public boolean onOptionsItemSelected(MenuItem item) { i.putExtra(Intent.EXTRA_TEXT, "Your error report here..."); startActivity(Intent.createChooser(i, "Report Problem")); break; - case R.id.blog: - i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("http://www.xxmassdeveloper.com/")); - startActivity(i); - break; case R.id.website: i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse("http://at.linkedin.com/in/philippjahoda")); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java new file mode 100644 index 0000000000..9a22b51c9a --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java @@ -0,0 +1,71 @@ +package com.xxmassdeveloper.mpchartexample.notimportant; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Typeface; +import androidx.annotation.NonNull; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +import com.xxmassdeveloper.mpchartexample.R; + +import java.util.List; + +/** + * Created by Philipp Jahoda on 07/12/15. + */ +class MyAdapter extends ArrayAdapter { + + private final Typeface mTypeFaceLight; + private final Typeface mTypeFaceRegular; + + MyAdapter(Context context, List objects) { + super(context, 0, objects); + + mTypeFaceLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + mTypeFaceRegular = Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf"); + } + + @SuppressLint("InflateParams") + @NonNull + @Override + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + + ContentItem c = getItem(position); + + ViewHolder holder; + + holder = new ViewHolder(); + + if (c != null && c.isSection) { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_section, null); + } else { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, null); + } + + holder.tvName = convertView.findViewById(R.id.tvName); + holder.tvDesc = convertView.findViewById(R.id.tvDesc); + + convertView.setTag(holder); + + if (c != null && c.isSection) + holder.tvName.setTypeface(mTypeFaceRegular); + else + holder.tvName.setTypeface(mTypeFaceLight); + holder.tvDesc.setTypeface(mTypeFaceLight); + + holder.tvName.setText(c != null ? c.name : null); + holder.tvDesc.setText(c != null ? c.desc : null); + + return convertView; + } + + private class ViewHolder { + + TextView tvName, tvDesc; + } +} diff --git a/MPChartExample/res/anim/move_left_in_activity.xml b/MPChartExample/src/main/res/anim/move_left_in_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_left_in_activity.xml rename to MPChartExample/src/main/res/anim/move_left_in_activity.xml diff --git a/MPChartExample/res/anim/move_left_out_activity.xml b/MPChartExample/src/main/res/anim/move_left_out_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_left_out_activity.xml rename to MPChartExample/src/main/res/anim/move_left_out_activity.xml diff --git a/MPChartExample/res/anim/move_right_in_activity.xml b/MPChartExample/src/main/res/anim/move_right_in_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_right_in_activity.xml rename to MPChartExample/src/main/res/anim/move_right_in_activity.xml diff --git a/MPChartExample/res/anim/move_right_out_activity.xml b/MPChartExample/src/main/res/anim/move_right_out_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_right_out_activity.xml rename to MPChartExample/src/main/res/anim/move_right_out_activity.xml diff --git a/MPChartExample/res/drawable-hdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-hdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-hdpi/star.png b/MPChartExample/src/main/res/drawable-hdpi/star.png similarity index 100% rename from MPChartExample/res/drawable-hdpi/star.png rename to MPChartExample/src/main/res/drawable-hdpi/star.png diff --git a/MPChartExample/res/drawable-mdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-mdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-nodpi/marker2.png b/MPChartExample/src/main/res/drawable-nodpi/marker2.png similarity index 100% rename from MPChartExample/res/drawable-nodpi/marker2.png rename to MPChartExample/src/main/res/drawable-nodpi/marker2.png diff --git a/MPChartExample/res/drawable-nodpi/radar_marker.png b/MPChartExample/src/main/res/drawable-nodpi/radar_marker.png similarity index 100% rename from MPChartExample/res/drawable-nodpi/radar_marker.png rename to MPChartExample/src/main/res/drawable-nodpi/radar_marker.png diff --git a/MPChartExample/res/drawable-xhdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-xhdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-xxhdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-xxhdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable/fade_red.xml b/MPChartExample/src/main/res/drawable/fade_red.xml similarity index 100% rename from MPChartExample/res/drawable/fade_red.xml rename to MPChartExample/src/main/res/drawable/fade_red.xml diff --git a/MPChartExample/res/layout/activity_age_distribution.xml b/MPChartExample/src/main/res/layout/activity_age_distribution.xml similarity index 90% rename from MPChartExample/res/layout/activity_age_distribution.xml rename to MPChartExample/src/main/res/layout/activity_age_distribution.xml index b023d3ab2d..574510fa0b 100644 --- a/MPChartExample/res/layout/activity_age_distribution.xml +++ b/MPChartExample/src/main/res/layout/activity_age_distribution.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - - + + + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_barchart_sinus.xml b/MPChartExample/src/main/res/layout/activity_barchart_sinus.xml similarity index 97% rename from MPChartExample/res/layout/activity_barchart_sinus.xml rename to MPChartExample/src/main/res/layout/activity_barchart_sinus.xml index 78b849081f..f39f2c7739 100644 --- a/MPChartExample/res/layout/activity_barchart_sinus.xml +++ b/MPChartExample/src/main/res/layout/activity_barchart_sinus.xml @@ -28,7 +28,7 @@ android:layout_height="wrap_content" android:layout_alignBottom="@+id/seekbarValues" android:layout_alignParentRight="true" - android:text="0" + android:text="@string/dash" android:layout_marginBottom="15dp" android:layout_marginRight="10dp" android:gravity="right" diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/src/main/res/layout/activity_bubblechart.xml similarity index 94% rename from MPChartExample/res/layout/activity_bubblechart.xml rename to MPChartExample/src/main/res/layout/activity_bubblechart.xml index 1cc55dfb42..d3df042fd0 100644 --- a/MPChartExample/res/layout/activity_bubblechart.xml +++ b/MPChartExample/src/main/res/layout/activity_bubblechart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - + + android:orientation="vertical"> - + diff --git a/MPChartExample/res/layout/activity_draw_chart.xml b/MPChartExample/src/main/res/layout/activity_draw_chart.xml similarity index 89% rename from MPChartExample/res/layout/activity_draw_chart.xml rename to MPChartExample/src/main/res/layout/activity_draw_chart.xml index 5b3792395b..5e2f1a21fc 100644 --- a/MPChartExample/res/layout/activity_draw_chart.xml +++ b/MPChartExample/src/main/res/layout/activity_draw_chart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> + android:layout_height="match_parent"> - + - @@ -8,7 +9,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/seekBar1" /> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_linechart_time.xml b/MPChartExample/src/main/res/layout/activity_linechart_time.xml similarity index 97% rename from MPChartExample/res/layout/activity_linechart_time.xml rename to MPChartExample/src/main/res/layout/activity_linechart_time.xml index 27f70f8ba3..c63d3e6f41 100644 --- a/MPChartExample/res/layout/activity_linechart_time.xml +++ b/MPChartExample/src/main/res/layout/activity_linechart_time.xml @@ -25,7 +25,7 @@ android:layout_width="50dp" android:layout_height="wrap_content" android:layout_alignParentRight="true" - android:text="500" + android:text="@string/dash" android:layout_marginBottom="15dp" android:layout_marginRight="10dp" android:gravity="right" diff --git a/MPChartExample/res/layout/activity_listview_chart.xml b/MPChartExample/src/main/res/layout/activity_listview_chart.xml similarity index 90% rename from MPChartExample/res/layout/activity_listview_chart.xml rename to MPChartExample/src/main/res/layout/activity_listview_chart.xml index b11c3d1ef8..12aa2f8500 100644 --- a/MPChartExample/res/layout/activity_listview_chart.xml +++ b/MPChartExample/src/main/res/layout/activity_listview_chart.xml @@ -2,7 +2,7 @@ + android:orientation="vertical"> + android:layout_height="fill_parent" + android:scrollbarFadeDuration="0"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_performance_linechart.xml b/MPChartExample/src/main/res/layout/activity_performance_linechart.xml similarity index 92% rename from MPChartExample/res/layout/activity_performance_linechart.xml rename to MPChartExample/src/main/res/layout/activity_performance_linechart.xml index d7cd5747fe..515321e1de 100644 --- a/MPChartExample/res/layout/activity_performance_linechart.xml +++ b/MPChartExample/src/main/res/layout/activity_performance_linechart.xml @@ -1,8 +1,7 @@ + android:layout_height="match_parent"> + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_radarchart.xml b/MPChartExample/src/main/res/layout/activity_radarchart.xml similarity index 89% rename from MPChartExample/res/layout/activity_radarchart.xml rename to MPChartExample/src/main/res/layout/activity_radarchart.xml index a197875bb8..aff98010c8 100644 --- a/MPChartExample/res/layout/activity_radarchart.xml +++ b/MPChartExample/src/main/res/layout/activity_radarchart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - + diff --git a/MPChartExample/res/layout/activity_scatterchart.xml b/MPChartExample/src/main/res/layout/activity_scatterchart.xml similarity index 94% rename from MPChartExample/res/layout/activity_scatterchart.xml rename to MPChartExample/src/main/res/layout/activity_scatterchart.xml index 947f8ce56d..41df167e5a 100644 --- a/MPChartExample/res/layout/activity_scatterchart.xml +++ b/MPChartExample/src/main/res/layout/activity_scatterchart.xml @@ -1,14 +1,14 @@ + android:layout_height="match_parent"> - + + android:layout_height="wrap_content"> - + + android:text="@string/scrollViewStart" /> @@ -30,13 +30,13 @@ - + - + android:text="@string/scrollViewEnd" /> + - \ No newline at end of file + diff --git a/MPChartExample/res/layout/custom_marker_view.xml b/MPChartExample/src/main/res/layout/custom_marker_view.xml similarity index 82% rename from MPChartExample/res/layout/custom_marker_view.xml rename to MPChartExample/src/main/res/layout/custom_marker_view.xml index 12cb53c2e2..f8444bf8c4 100644 --- a/MPChartExample/res/layout/custom_marker_view.xml +++ b/MPChartExample/src/main/res/layout/custom_marker_view.xml @@ -1,8 +1,10 @@ + android:background="@drawable/marker2" + tools:ignore="Overdraw"> - - + diff --git a/MPChartExample/res/layout/frag_simple_line.xml b/MPChartExample/src/main/res/layout/frag_simple_line.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_line.xml rename to MPChartExample/src/main/res/layout/frag_simple_line.xml diff --git a/MPChartExample/res/layout/frag_simple_pie.xml b/MPChartExample/src/main/res/layout/frag_simple_pie.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_pie.xml rename to MPChartExample/src/main/res/layout/frag_simple_pie.xml diff --git a/MPChartExample/res/layout/frag_simple_scatter.xml b/MPChartExample/src/main/res/layout/frag_simple_scatter.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_scatter.xml rename to MPChartExample/src/main/res/layout/frag_simple_scatter.xml diff --git a/MPChartExample/res/layout/list_item.xml b/MPChartExample/src/main/res/layout/list_item.xml similarity index 52% rename from MPChartExample/res/layout/list_item.xml rename to MPChartExample/src/main/res/layout/list_item.xml index c9c11e93ba..420add1193 100644 --- a/MPChartExample/res/layout/list_item.xml +++ b/MPChartExample/src/main/res/layout/list_item.xml @@ -12,7 +12,8 @@ android:layout_alignParentTop="true" android:layout_marginLeft="4dp" android:text="Medium Text" - android:textSize="16dp"/> + android:textColor="@android:color/black" + android:textSize="16sp"/> - - + android:textSize="12sp" + android:layout_marginRight="10dp" /> diff --git a/MPChartExample/res/layout/list_item_barchart.xml b/MPChartExample/src/main/res/layout/list_item_barchart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_barchart.xml rename to MPChartExample/src/main/res/layout/list_item_barchart.xml diff --git a/MPChartExample/res/layout/list_item_linechart.xml b/MPChartExample/src/main/res/layout/list_item_linechart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_linechart.xml rename to MPChartExample/src/main/res/layout/list_item_linechart.xml diff --git a/MPChartExample/res/layout/list_item_piechart.xml b/MPChartExample/src/main/res/layout/list_item_piechart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_piechart.xml rename to MPChartExample/src/main/res/layout/list_item_piechart.xml diff --git a/MPChartExample/src/main/res/layout/list_item_section.xml b/MPChartExample/src/main/res/layout/list_item_section.xml new file mode 100644 index 0000000000..19707f1777 --- /dev/null +++ b/MPChartExample/src/main/res/layout/list_item_section.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/MPChartExample/res/layout/radar_markerview.xml b/MPChartExample/src/main/res/layout/radar_markerview.xml similarity index 79% rename from MPChartExample/res/layout/radar_markerview.xml rename to MPChartExample/src/main/res/layout/radar_markerview.xml index 9ab1b84121..d94768dd67 100644 --- a/MPChartExample/res/layout/radar_markerview.xml +++ b/MPChartExample/src/main/res/layout/radar_markerview.xml @@ -1,8 +1,10 @@ + android:background="@drawable/radar_marker" + tools:ignore="Overdraw"> + android:textAppearance="?android:attr/textAppearanceSmall" + tools:ignore="SmallSp" /> diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/src/main/res/menu/bar.xml similarity index 57% rename from MPChartExample/res/menu/bar.xml rename to MPChartExample/src/main/res/menu/bar.xml index 4bbfedd4db..e05fc59797 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/src/main/res/menu/bar.xml @@ -2,48 +2,48 @@ + android:id="@+id/viewGithub" + android:title="@string/viewGithub"> + android:id="@+id/actionToggleBarBorders" + android:title="@string/actionToggleBarBorders"> + android:id="@+id/actionToggleValues" + android:title="@string/actionToggleValues"> + android:id="@+id/actionToggleIcons" + android:title="@string/actionToggleIcons"> + android:id="@+id/actionToggleHighlight" + android:title="@string/actionToggleHighlight"> + android:id="@+id/actionTogglePinch" + android:title="@string/actionTogglePinch"> + android:id="@+id/actionToggleAutoScaleMinMax" + android:title="@string/actionToggleAutoScale"> + android:id="@+id/animateX" + android:title="@string/animateX"> + android:id="@+id/animateY" + android:title="@string/animateY"> + android:id="@+id/animateXY" + android:title="@string/animateXY"> + android:id="@+id/actionSave" + android:title="@string/actionSave"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/src/main/res/menu/bubble.xml similarity index 57% rename from MPChartExample/res/menu/bubble.xml rename to MPChartExample/src/main/res/menu/bubble.xml index b7950291e9..7b9ab5cd11 100644 --- a/MPChartExample/res/menu/bubble.xml +++ b/MPChartExample/src/main/res/menu/bubble.xml @@ -1,45 +1,45 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleHighlight"> + + + android:id="@+id/actionToggleAutoScaleMinMax" + android:title="@string/actionToggleAutoScale"> + android:title="@string/animateX"> + android:title="@string/animateY"> + android:title="@string/animateXY"> - - - - + android:title="@string/actionSave"> - \ No newline at end of file + diff --git a/MPChartExample/src/main/res/menu/candle.xml b/MPChartExample/src/main/res/menu/candle.xml new file mode 100644 index 0000000000..42a1a7e050 --- /dev/null +++ b/MPChartExample/src/main/res/menu/candle.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/src/main/res/menu/combined.xml similarity index 53% rename from MPChartExample/res/menu/combined.xml rename to MPChartExample/src/main/res/menu/combined.xml index 7e37ba0d83..c7def2509c 100644 --- a/MPChartExample/res/menu/combined.xml +++ b/MPChartExample/src/main/res/menu/combined.xml @@ -1,16 +1,21 @@ + + + android:title="@string/actionToggleLineValues"> + android:title="@string/actionToggleBarValues"> + android:title="@string/actionRemoveDataSet"> - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/draw.xml b/MPChartExample/src/main/res/menu/draw.xml similarity index 57% rename from MPChartExample/res/menu/draw.xml rename to MPChartExample/src/main/res/menu/draw.xml index 50f35239e7..36383db54f 100644 --- a/MPChartExample/res/menu/draw.xml +++ b/MPChartExample/src/main/res/menu/draw.xml @@ -3,34 +3,30 @@ + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleCircles"> - - - - + android:title="@string/actionToggleHighlight"> + android:title="@string/actionTogglePinch"> + android:title="@string/actionToggleAutoScale"> + + - \ No newline at end of file + diff --git a/MPChartExample/src/main/res/menu/dynamical.xml b/MPChartExample/src/main/res/menu/dynamical.xml new file mode 100644 index 0000000000..68d4fab0c9 --- /dev/null +++ b/MPChartExample/src/main/res/menu/dynamical.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/src/main/res/menu/line.xml similarity index 57% rename from MPChartExample/res/menu/line.xml rename to MPChartExample/src/main/res/menu/line.xml index f9f5be9615..a812b91b5a 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/src/main/res/menu/line.xml @@ -1,64 +1,65 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleCircles"> + android:title="@string/actionToggleCubic"> + android:title="@string/actionToggleStepped"> + android:title="@string/actionToggleHorizontalCubic"> + + + + + android:title="@string/actionToggleHighlight"> + android:title="@string/animateX"> + android:title="@string/animateY"> - - + android:title="@string/animateXY"> - - + android:title="@string/actionSave"> - - - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/main.xml b/MPChartExample/src/main/res/menu/main.xml similarity index 55% rename from MPChartExample/res/menu/main.xml rename to MPChartExample/src/main/res/menu/main.xml index b45d3bbb9f..9ac13dbbae 100644 --- a/MPChartExample/res/menu/main.xml +++ b/MPChartExample/src/main/res/menu/main.xml @@ -3,19 +3,15 @@ + android:title="@string/viewGithub"> - - + android:title="@string/reportProblem"> + android:title="@string/viewWebsite"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/realm.xml b/MPChartExample/src/main/res/menu/only_github.xml similarity index 57% rename from MPChartExample/res/menu/realm.xml rename to MPChartExample/src/main/res/menu/only_github.xml index f954443b30..c0a9b66934 100644 --- a/MPChartExample/res/menu/realm.xml +++ b/MPChartExample/src/main/res/menu/only_github.xml @@ -1,8 +1,7 @@ - - + + android:id="@+id/viewGithub" + android:title="@string/viewGithub"> - \ No newline at end of file + diff --git a/MPChartExample/src/main/res/menu/pie.xml b/MPChartExample/src/main/res/menu/pie.xml new file mode 100644 index 0000000000..09a05a9ccd --- /dev/null +++ b/MPChartExample/src/main/res/menu/pie.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/src/main/res/menu/radar.xml similarity index 55% rename from MPChartExample/res/menu/radar.xml rename to MPChartExample/src/main/res/menu/radar.xml index 14690f446c..2a5c19cf81 100644 --- a/MPChartExample/res/menu/radar.xml +++ b/MPChartExample/src/main/res/menu/radar.xml @@ -1,57 +1,62 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleHighlight"> + android:title="@string/actionToggleHighlightCircle"> + android:id="@+id/actionToggleRotate" + android:title="@string/actionToggleRotation"> + android:id="@+id/actionToggleYLabels" + android:title="@string/actionToggleYValues"> + android:id="@+id/actionToggleXLabels" + android:title="@string/actionToggleXValues"> + android:id="@+id/actionToggleSpin" + android:title="@string/actionToggleSpin"> + android:id="@+id/animateX" + android:title="@string/animateX"> + android:id="@+id/animateY" + android:title="@string/animateY"> + android:id="@+id/animateXY" + android:title="@string/animateXY"> + android:id="@+id/actionSave" + android:title="@string/actionSave"> - \ No newline at end of file + + diff --git a/MPChartExample/src/main/res/menu/realtime.xml b/MPChartExample/src/main/res/menu/realtime.xml new file mode 100644 index 0000000000..48cc7ccd0a --- /dev/null +++ b/MPChartExample/src/main/res/menu/realtime.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/src/main/res/menu/scatter.xml similarity index 57% rename from MPChartExample/res/menu/scatter.xml rename to MPChartExample/src/main/res/menu/scatter.xml index b7950291e9..eb8e0efa67 100644 --- a/MPChartExample/res/menu/scatter.xml +++ b/MPChartExample/src/main/res/menu/scatter.xml @@ -1,45 +1,45 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> - - + android:title="@string/actionToggleHighlight"> + android:title="@string/animateX"> + android:title="@string/animateY"> - - + android:title="@string/animateXY"> + android:title="@string/actionTogglePinch"> + android:title="@string/actionToggleAutoScale"> + + - \ No newline at end of file + diff --git a/MPChartExample/src/main/res/values/strings.xml b/MPChartExample/src/main/res/values/strings.xml new file mode 100644 index 0000000000..91a25bb89e --- /dev/null +++ b/MPChartExample/src/main/res/values/strings.xml @@ -0,0 +1,55 @@ + + + + MPAndroidChart Example + + View on GitHub + Problem Report + Developer Website + Save to Gallery + + Animate X + Animate Y + Animate XY + + Toggle Values + Toggle Y-Values + Toggle X-Values + + Toggle Icons + Toggle Highlight + Toggle PinchZoom + Toggle Auto Scale + + Toggle Line Values + Toggle Bar Values + Toggle Bar Borders + Toggle Filled + Toggle Circles + Toggle Shadow Color + + Toggle Cubic + Toggle Stepped + Toggle Horizontal Cubic + + Add Entry + Add Multiple + Remove Entry + Add Data Set + Remove Data Set + Clear chart + + Toggle Percent + Toggle Minimum Angles + Toggle Hole + Toggle Curved Slices + Draw Center Text + Toggle Highlight Circle + Toggle Rotation + Spin Animation + + - + START OF SCROLLVIEW + END OF SCROLLVIEW + + diff --git a/MPChartExample/src/main/res/values/styles.xml b/MPChartExample/src/main/res/values/styles.xml new file mode 100644 index 0000000000..9d5b53bd6c --- /dev/null +++ b/MPChartExample/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index 77dc3a2d85..0000000000 --- a/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -org.springsource.ide.eclipse.gradle.linkedresources= -org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 19c06befb3..16d3e3ce10 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,18 +1,15 @@ apply plugin: 'com.android.library' -apply plugin: 'maven' -//apply plugin: 'com.github.dcendents.android-maven' -//apply plugin: 'realm-android' + +group='com.github.philjay' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' - // resourcePrefix 'mpcht' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { - //noinspection MinSdkTooLow - minSdkVersion 9 - targetSdkVersion 27 + minSdkVersion 14 + targetSdkVersion 28 versionCode 3 - versionName '3.0.3' + versionName '3.1.0' } buildTypes { release { @@ -20,33 +17,14 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - lintOptions { - abortOnError false - } testOptions { unitTests.returnDefaultValues = true // this prevents "not mocked" error } } -repositories { - maven { - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } -} - dependencies { - //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API - implementation 'com.android.support:support-annotations:27.1.1' + implementation 'androidx.annotation:annotation:1.0.0' testImplementation 'junit:junit:4.12' - testImplementation "org.mockito:mockito-core:1.10.19" -} - -android.libraryVariants.all { variant -> - def name = variant.buildType.name - def task = project.tasks.create "jar${name.capitalize()}", Jar - task.dependsOn variant.javaCompiler - task.from variant.javaCompiler.destinationDir - artifacts.add('archives', task) } task sourcesJar(type: Jar) { diff --git a/MPChartLib/proguard-project.txt b/MPChartLib/proguard-project.txt deleted file mode 100644 index f2fe1559a2..0000000000 --- a/MPChartLib/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/MPChartLib/project.properties b/MPChartLib/project.properties deleted file mode 100644 index b2ef7dccc5..0000000000 --- a/MPChartLib/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-23 -android.library=true diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index 026a1b30d3..e5b82db0b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -1,9 +1,8 @@ - package com.github.mikephil.charting.animation; import android.animation.ObjectAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; import com.github.mikephil.charting.animation.Easing.EasingFunction; @@ -160,98 +159,6 @@ public void animateY(int durationMillis, EasingFunction easing) { animatorY.start(); } - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. - * - * @param durationMillisX animation duration along the X axis - * @param durationMillisY animation duration along the Y axis - * @param easingX EasingFunction for the X axis - * @param easingY EasingFunction for the Y axis - * - * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} - * @see #animateXY(int, int, EasingFunction, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easingY)); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easingX)); - animatorX.setDuration( - durationMillisX); - - // make sure only one animator produces update-callbacks (which then - // call invalidate()) - if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); - } else { - animatorY.addUpdateListener(mListener); - } - - animatorX.start(); - animatorY.start(); - } - - /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. - * - * @param durationMillis animation duration - * @param easing EasingFunction - * - * @deprecated Use {@link #animateX(int, EasingFunction)} - * @see #animateX(int, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateX(int durationMillis, Easing.EasingOption easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorX.setDuration(durationMillis); - animatorX.addUpdateListener(mListener); - animatorX.start(); - } - - /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. - * - * @param durationMillis animation duration - * @param easing EasingFunction - * - * @deprecated Use {@link #animateY(int, EasingFunction)} - * @see #animateY(int, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateY(int durationMillis, Easing.EasingOption easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorY.setDuration(durationMillis); - animatorY.addUpdateListener(mListener); - animatorY.start(); - } - /** * Gets the Y axis phase of the animation. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java index 631e313b10..acb7dcc965 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java @@ -1,8 +1,7 @@ - package com.github.mikephil.charting.animation; import android.animation.TimeInterpolator; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; /** * Easing options. @@ -19,113 +18,6 @@ public interface EasingFunction extends TimeInterpolator { float getInterpolation(float input); } - /** - * Enum holding EasingOption constants - * - * @deprecated Use Easing.Linear instead of Easing.EasingOption.Linear - */ - @Deprecated - public enum EasingOption { - Linear, - EaseInQuad, - EaseOutQuad, - EaseInOutQuad, - EaseInCubic, - EaseOutCubic, - EaseInOutCubic, - EaseInQuart, - EaseOutQuart, - EaseInOutQuart, - EaseInSine, - EaseOutSine, - EaseInOutSine, - EaseInExpo, - EaseOutExpo, - EaseInOutExpo, - EaseInCirc, - EaseOutCirc, - EaseInOutCirc, - EaseInElastic, - EaseOutElastic, - EaseInOutElastic, - EaseInBack, - EaseOutBack, - EaseInOutBack, - EaseInBounce, - EaseOutBounce, - EaseInOutBounce, - } - - /** - * Returns the EasingFunction of the given EasingOption - * - * @param easing EasingOption to get - * @return EasingFunction - */ - @SuppressWarnings("deprecation") - @Deprecated - public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { - switch (easing) { - default: - case Linear: - return Easing.Linear; - case EaseInQuad: - return Easing.EaseInQuad; - case EaseOutQuad: - return Easing.EaseOutQuad; - case EaseInOutQuad: - return Easing.EaseInOutQuad; - case EaseInCubic: - return Easing.EaseInCubic; - case EaseOutCubic: - return Easing.EaseOutCubic; - case EaseInOutCubic: - return Easing.EaseInOutCubic; - case EaseInQuart: - return Easing.EaseInQuart; - case EaseOutQuart: - return Easing.EaseOutQuart; - case EaseInOutQuart: - return Easing.EaseInOutQuart; - case EaseInSine: - return Easing.EaseInSine; - case EaseOutSine: - return Easing.EaseOutSine; - case EaseInOutSine: - return Easing.EaseInOutSine; - case EaseInExpo: - return Easing.EaseInExpo; - case EaseOutExpo: - return Easing.EaseOutExpo; - case EaseInOutExpo: - return Easing.EaseInOutExpo; - case EaseInCirc: - return Easing.EaseInCirc; - case EaseOutCirc: - return Easing.EaseOutCirc; - case EaseInOutCirc: - return Easing.EaseInOutCirc; - case EaseInElastic: - return Easing.EaseInElastic; - case EaseOutElastic: - return Easing.EaseOutElastic; - case EaseInOutElastic: - return Easing.EaseInOutElastic; - case EaseInBack: - return Easing.EaseInBack; - case EaseOutBack: - return Easing.EaseOutBack; - case EaseInOutBack: - return Easing.EaseInOutBack; - case EaseInBounce: - return Easing.EaseInBounce; - case EaseOutBounce: - return Easing.EaseOutBounce; - case EaseInOutBounce: - return Easing.EaseInOutBounce; - } - } - private static final float DOUBLE_PI = 2f * (float) Math.PI; @SuppressWarnings("unused") diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 0b0219e445..0926dff244 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -100,6 +100,8 @@ public abstract class BarLineChartBase= 11) { - - MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - - Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis - .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), - xValue, yValue, (float) origin.x, (float) origin.y, duration); - addViewportJob(job); + MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - MPPointD.recycleInstance(origin); + Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis + .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + xValue, yValue, (float) origin.x, (float) origin.y, duration); + addViewportJob(job); - } else { - Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(origin); } protected Matrix mFitScreenMatrixBuffer = new Matrix(); @@ -874,21 +877,16 @@ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { @TargetApi(11) public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { - if (android.os.Build.VERSION.SDK_INT >= 11) { + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - - float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); - Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - addViewportJob(job); + addViewportJob(job); - MPPointD.recycleInstance(bounds); - } else { - Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(bounds); } /** @@ -941,23 +939,18 @@ public void centerViewTo(float xValue, float yValue, AxisDependency axis) { @TargetApi(11) public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { - if (android.os.Build.VERSION.SDK_INT >= 11) { - - MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); - float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); + float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); - Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, - xValue - xInView / 2f, yValue + yInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, + xValue - xInView / 2f, yValue + yInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - addViewportJob(job); + addViewportJob(job); - MPPointD.recycleInstance(bounds); - } else { - Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(bounds); } /** @@ -1240,6 +1233,17 @@ public void setClipValuesToContent(boolean enabled) { mClipValuesToContent = enabled; } + /** + * When disabled, the data and/or highlights will not be clipped to contentRect. Disabling this option can + * be useful, when the data lies fully within the content rect, but is drawn in such a way (such as thick lines) + * that there is unwanted clipping. + * + * @param enabled + */ + public void setClipDataToContent(boolean enabled) { + mClipDataToContent = enabled; + } + /** * When enabled, the values will be clipped to contentRect, * otherwise they can bleed outside the content rect. @@ -1250,6 +1254,17 @@ public boolean isClipValuesToContentEnabled() { return mClipValuesToContent; } + /** + * When disabled, the data and/or highlights will not be clipped to contentRect. Disabling this option can + * be useful, when the data lies fully within the content rect, but is drawn in such a way (such as thick lines) + * that there is unwanted clipping. + * + * @return + */ + public boolean isClipDataToContentEnabled() { + return mClipDataToContent; + } + /** * Sets the width of the border lines in dp. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 35ec2ec1e0..5cf49ea9d1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -17,7 +17,7 @@ import android.os.Build; import android.os.Environment; import android.provider.MediaStore.Images; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -209,18 +209,14 @@ protected void init() { setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_HARDWARE, null); - if (Build.VERSION.SDK_INT < 11) { - mAnimator = new ChartAnimator(); - } else { - mAnimator = new ChartAnimator(new AnimatorUpdateListener() { + mAnimator = new ChartAnimator(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - // ViewCompat.postInvalidateOnAnimation(Chart.this); - postInvalidate(); - } - }); - } + @Override + public void onAnimationUpdate(ValueAnimator animation) { + // ViewCompat.postInvalidateOnAnimation(Chart.this); + postInvalidate(); + } + }); // initialize the utils Utils.init(getContext()); @@ -403,8 +399,23 @@ protected void onDraw(Canvas canvas) { boolean hasText = !TextUtils.isEmpty(mNoDataText); if (hasText) { - MPPointF c = getCenter(); - canvas.drawText(mNoDataText, c.x, c.y, mInfoPaint); + MPPointF pt = getCenter(); + + switch (mInfoPaint.getTextAlign()) { + case LEFT: + pt.x = 0; + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + + case RIGHT: + pt.x *= 2.0; + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + + default: + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + } } return; @@ -553,6 +564,18 @@ public void highlightValues(Highlight[] highs) { invalidate(); } + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + */ + public void highlightValue(float x, int dataSetIndex, int dataIndex) { + highlightValue(x, dataSetIndex, dataIndex, true); + } + /** * Highlights any y-value at the given x-value in the given DataSet. * Provide -1 as the dataSetIndex to undo all highlighting. @@ -561,7 +584,20 @@ public void highlightValues(Highlight[] highs) { * @param dataSetIndex The dataset index to search in */ public void highlightValue(float x, int dataSetIndex) { - highlightValue(x, dataSetIndex, true); + highlightValue(x, dataSetIndex, -1, true); + } + + /** + * Highlights the value at the given x-value and y-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + */ + public void highlightValue(float x, float y, int dataSetIndex, int dataIndex) { + highlightValue(x, y, dataSetIndex, dataIndex, true); } /** @@ -573,7 +609,19 @@ public void highlightValue(float x, int dataSetIndex) { * @param dataSetIndex The dataset index to search in */ public void highlightValue(float x, float y, int dataSetIndex) { - highlightValue(x, y, dataSetIndex, true); + highlightValue(x, y, dataSetIndex, -1, true); + } + + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, int dataSetIndex, int dataIndex, boolean callListener) { + highlightValue(x, Float.NaN, dataSetIndex, dataIndex, callListener); } /** @@ -584,7 +632,7 @@ public void highlightValue(float x, float y, int dataSetIndex) { * @param callListener Should the listener be called for this change */ public void highlightValue(float x, int dataSetIndex, boolean callListener) { - highlightValue(x, Float.NaN, dataSetIndex, callListener); + highlightValue(x, Float.NaN, dataSetIndex, -1, callListener); } /** @@ -593,17 +641,30 @@ public void highlightValue(float x, int dataSetIndex, boolean callListener) { * @param x The x-value to highlight * @param y The y-value to highlight. Supply `NaN` for "any" * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) * @param callListener Should the listener be called for this change */ - public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { + public void highlightValue(float x, float y, int dataSetIndex, int dataIndex, boolean callListener) { if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) { highlightValue(null, callListener); } else { - highlightValue(new Highlight(x, y, dataSetIndex), callListener); + highlightValue(new Highlight(x, y, dataSetIndex, dataIndex), callListener); } } + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { + highlightValue(x, y, dataSetIndex, -1, callListener); + } + /** * Highlights the values represented by the provided Highlight object * This method *will not* call the listener. @@ -892,60 +953,6 @@ public void animateY(int durationMillis, EasingFunction easing) { */ /** CODE BELOW FOR PREDEFINED EASING OPTIONS */ - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. ANIMATIONS - * ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillisX - * @param durationMillisY - * @param easingX a predefined easing option - * @param easingY a predefined easing option - * - * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} - * @see #animateXY(int, int, EasingFunction, EasingFunction) - */ - @Deprecated - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { - mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); - } - - /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillis - * @param easing a predefined easing option - * - * @deprecated Use {@link #animateX(int, EasingFunction)} - * @see #animateX(int, EasingFunction) - */ - @Deprecated - public void animateX(int durationMillis, Easing.EasingOption easing) { - mAnimator.animateX(durationMillis, easing); - } - - /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillis - * @param easing a predefined easing option - * - * @deprecated Use {@link #animateY(int, EasingFunction)} - * @see #animateY(int, EasingFunction) - */ - @Deprecated - public void animateY(int durationMillis, Easing.EasingOption easing) { - mAnimator.animateY(durationMillis, easing); - } - /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. @@ -1221,6 +1228,15 @@ public void setNoDataTextTypeface(Typeface tf) { mInfoPaint.setTypeface(tf); } + /** + * alignment of the no data text + * + * @param align + */ + public void setNoDataTextAlignment(Align align) { + mInfoPaint.setTextAlign(align); + } + /** * Set this to false to disable all gestures and touches on the chart, * default: true @@ -1527,6 +1543,8 @@ public Bitmap getChartBitmap() { */ public boolean saveToPath(String title, String pathOnSD) { + + Bitmap b = getChartBitmap(); OutputStream stream = null; @@ -1642,7 +1660,18 @@ public boolean saveToGallery(String fileName, String subFolderPath, String fileD * @return returns true if saving was successful, false if not */ public boolean saveToGallery(String fileName, int quality) { - return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.JPEG, quality); + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.PNG, quality); + } + + /** + * Saves the current state of the chart to the gallery as a PNG image. + * NOTE: Needs permission WRITE_EXTERNAL_STORAGE + * + * @param fileName e.g. "my_image" + * @return returns true if saving was successful, false if not + */ + public boolean saveToGallery(String fileName) { + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.PNG, 40); } /** @@ -1739,16 +1768,10 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { */ public void setHardwareAccelerationEnabled(boolean enabled) { - if (android.os.Build.VERSION.SDK_INT >= 11) { - - if (enabled) - setLayerType(View.LAYER_TYPE_HARDWARE, null); - else - setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } else { - Log.e(LOG_TAG, - "Cannot enable/disable hardware acceleration for devices below API level 11."); - } + if (enabled) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index e4ec309d9f..9aac1ce97c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -60,6 +60,84 @@ protected void init() { private RectF mOffsetsBuffer = new RectF(); + protected void calculateLegendOffsets(RectF offsets) { + + offsets.left = 0.f; + offsets.right = 0.f; + offsets.top = 0.f; + offsets.bottom = 0.f; + + if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled()) + return; + + switch (mLegend.getOrientation()) { + case VERTICAL: + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + offsets.left += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case RIGHT: + offsets.right += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case CENTER: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + default: + break; + } + } + + break; + + case HORIZONTAL: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisLeft.isEnabled() && mAxisLeft.isDrawLabelsEnabled()) + offsets.top += mAxisLeft.getRequiredHeightSpace( + mAxisRendererLeft.getPaintAxisLabels()); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisRight.isEnabled() && mAxisRight.isDrawLabelsEnabled()) + offsets.bottom += mAxisRight.getRequiredHeightSpace( + mAxisRendererRight.getPaintAxisLabels()); + break; + + default: + break; + } + break; + } + } + @Override public void calculateOffsets() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 660fd29bdc..de11b3a844 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -94,6 +94,12 @@ public class PieChart extends PieRadarChartBase { protected float mMaxAngle = 360f; + /** + * Minimum angle to draw slices, this only works if there is enough room for all slices to have + * the minimum angle, default 0f. + */ + private float mMinAngleForSlices = 0f; + public PieChart(Context context) { super(context); } @@ -228,7 +234,12 @@ private void calcAngles() { List dataSets = mData.getDataSets(); + boolean hasMinAngle = mMinAngleForSlices != 0f && entryCount * mMinAngleForSlices <= mMaxAngle; + float[] minAngles = new float[entryCount]; + int cnt = 0; + float offset = 0f; + float diff = 0f; for (int i = 0; i < mData.getDataSetCount(); i++) { @@ -236,7 +247,20 @@ private void calcAngles() { for (int j = 0; j < set.getEntryCount(); j++) { - mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum); + float drawAngle = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum); + + if (hasMinAngle) { + float temp = drawAngle - mMinAngleForSlices; + if (temp <= 0) { + minAngles[cnt] = mMinAngleForSlices; + offset += -temp; + } else { + minAngles[cnt] = drawAngle; + diff += temp; + } + } + + mDrawAngles[cnt] = drawAngle; if (cnt == 0) { mAbsoluteAngles[cnt] = mDrawAngles[cnt]; @@ -248,6 +272,20 @@ private void calcAngles() { } } + if (hasMinAngle) { + // Correct bigger slices by relatively reducing their angles based on the total angle needed to subtract + // This requires that `entryCount * mMinAngleForSlices <= mMaxAngle` be true to properly work! + for (int i = 0; i < entryCount; i++) { + minAngles[i] -= (minAngles[i] - mMinAngleForSlices) / diff * offset; + if (i == 0) { + mAbsoluteAngles[0] = minAngles[0]; + } else { + mAbsoluteAngles[i] = mAbsoluteAngles[i - 1] + minAngles[i]; + } + } + + mDrawAngles = minAngles; + } } /** @@ -650,6 +688,16 @@ public void setEntryLabelTextSize(float size) { ((PieChartRenderer) mRenderer).getPaintEntryLabels().setTextSize(Utils.convertDpToPixel(size)); } + /** + * Sets whether to draw slices in a curved fashion, only works if drawing the hole is enabled + * and if the slices are not drawn under the hole. + * + * @param enabled draw curved ends of slices + */ + public void setDrawRoundedSlices(boolean enabled) { + mDrawRoundedSlices = enabled; + } + /** * Returns true if the chart is set to draw each end of a pie-slice * "rounded". @@ -719,6 +767,32 @@ public void setMaxAngle(float maxangle) { this.mMaxAngle = maxangle; } + /** + * The minimum angle slices on the chart are rendered with, default is 0f. + * + * @return minimum angle for slices + */ + public float getMinAngleForSlices() { + return mMinAngleForSlices; + } + + /** + * Set the angle to set minimum size for slices, you must call {@link #notifyDataSetChanged()} + * and {@link #invalidate()} when changing this, only works if there is enough room for all + * slices to have the minimum angle. + * + * @param minAngle minimum 0, maximum is half of {@link #setMaxAngle(float)} + */ + public void setMinAngleForSlices(float minAngle) { + + if (minAngle > (mMaxAngle / 2f)) + minAngle = mMaxAngle / 2f; + else if (minAngle < 0) + minAngle = 0f; + + this.mMinAngleForSlices = minAngle; + } + @Override protected void onDetachedFromWindow() { // releases the bitmap in the renderer to avoid oom error diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 618de18a34..e6d38d3a01 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -480,9 +480,6 @@ public float getYChartMin() { @SuppressLint("NewApi") public void spin(int durationmillis, float fromangle, float toangle, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; - setRotationAngle(fromangle); ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 3c9aec0dde..8c0885395d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -84,6 +84,7 @@ protected void init() { super.init(); mYAxis = new YAxis(AxisDependency.LEFT); + mYAxis.setLabelXOffset(10f); mWebLineWidth = Utils.convertDpToPixel(1.5f); mInnerWebLineWidth = Utils.convertDpToPixel(0.75f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 3c8028c24b..c90b4fc9b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -152,6 +152,39 @@ public abstract class AxisBase extends ComponentBase { */ public float mAxisRange = 0f; + private int mAxisMinLabels = 2; + private int mAxisMaxLabels = 25; + + /** + * The minumum number of labels on the axis + */ + public int getAxisMinLabels() { + return mAxisMinLabels; + } + + /** + * The minumum number of labels on the axis + */ + public void setAxisMinLabels(int labels) { + if (labels > 0) + mAxisMinLabels = labels; + } + + /** + * The maximum number of labels on the axis + */ + public int getAxisMaxLabels() { + return mAxisMaxLabels; + } + + /** + * The maximum number of labels on the axis + */ + public void setAxisMaxLabels(int labels) { + if (labels > 0) + mAxisMaxLabels = labels; + } + /** * default constructor */ @@ -315,10 +348,10 @@ public boolean isDrawLabelsEnabled() { */ public void setLabelCount(int count) { - if (count > 25) - count = 25; - if (count < 2) - count = 2; + if (count > getAxisMaxLabels()) + count = getAxisMaxLabels(); + if (count < getAxisMinLabels()) + count = getAxisMinLabels(); mLabelCount = count; mForceLabels = false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index fb1afc8bba..708129259b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -1,10 +1,8 @@ - package com.github.mikephil.charting.components; import android.graphics.DashPathEffect; import android.graphics.Paint; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; @@ -22,19 +20,6 @@ */ public class Legend extends ComponentBase { - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public enum LegendPosition { - RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, - LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, - BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, - ABOVE_CHART_LEFT, ABOVE_CHART_RIGHT, ABOVE_CHART_CENTER, - PIECHART_CENTER - } - public enum LegendForm { /** * Avoid drawing a form @@ -182,43 +167,6 @@ public Legend(LegendEntry[] entries) { this.mEntries = entries; } - @Deprecated - public Legend(int[] colors, String[] labels) { - this(); - - if (colors == null || labels == null) { - throw new IllegalArgumentException("colors array or labels array is NULL"); - } - - if (colors.length != labels.length) { - throw new IllegalArgumentException( - "colors array and labels array need to be of same size"); - } - - List entries = new ArrayList<>(); - - for (int i = 0; i < Math.min(colors.length, labels.length); i++) { - final LegendEntry entry = new LegendEntry(); - entry.formColor = colors[i]; - entry.label = labels[i]; - - if (entry.formColor == ColorTemplate.COLOR_SKIP) - entry.form = LegendForm.NONE; - else if (entry.formColor == ColorTemplate.COLOR_NONE || - entry.formColor == 0) - entry.form = LegendForm.EMPTY; - - entries.add(entry); - } - - mEntries = entries.toArray(new LegendEntry[entries.size()]); - } - - @Deprecated - public Legend(List colors, List labels) { - this(Utils.convertIntegers(colors), Utils.convertStrings(labels)); - } - /** * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. * @@ -287,50 +235,6 @@ public float getMaximumEntryHeight(Paint p) { return max; } - @Deprecated - public int[] getColors() { - - int[] old = new int[mEntries.length]; - for (int i = 0; i < mEntries.length; i++) { - old[i] = mEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : - (mEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : - mEntries[i].formColor); - } - return old; - } - - @Deprecated - public String[] getLabels() { - - String[] old = new String[mEntries.length]; - for (int i = 0; i < mEntries.length; i++) { - old[i] = mEntries[i].label; - } - return old; - } - - @Deprecated - public int[] getExtraColors() { - - int[] old = new int[mExtraEntries.length]; - for (int i = 0; i < mExtraEntries.length; i++) { - old[i] = mExtraEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : - (mExtraEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : - mExtraEntries[i].formColor); - } - return old; - } - - @Deprecated - public String[] getExtraLabels() { - - String[] old = new String[mExtraEntries.length]; - for (int i = 0; i < mExtraEntries.length; i++) { - old[i] = mExtraEntries[i].label; - } - return old; - } - public LegendEntry[] getExtraEntries() { return mExtraEntries; @@ -346,11 +250,6 @@ public void setExtra(LegendEntry[] entries) { mExtraEntries = entries; } - @Deprecated - public void setExtra(List colors, List labels) { - setExtra(Utils.convertIntegers(colors), Utils.convertStrings(labels)); - } - /** * Entries that will be appended to the end of the auto calculated * entries after calculating the legend. @@ -423,109 +322,6 @@ public boolean isLegendCustom() { return mIsLegendCustom; } - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public LegendPosition getPosition() { - - if (mOrientation == LegendOrientation.VERTICAL - && mHorizontalAlignment == LegendHorizontalAlignment.CENTER - && mVerticalAlignment == LegendVerticalAlignment.CENTER) { - return LegendPosition.PIECHART_CENTER; - } else if (mOrientation == LegendOrientation.HORIZONTAL) { - if (mVerticalAlignment == LegendVerticalAlignment.TOP) - return mHorizontalAlignment == LegendHorizontalAlignment.LEFT - ? LegendPosition.ABOVE_CHART_LEFT - : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT - ? LegendPosition.ABOVE_CHART_RIGHT - : LegendPosition.ABOVE_CHART_CENTER); - else - return mHorizontalAlignment == LegendHorizontalAlignment.LEFT - ? LegendPosition.BELOW_CHART_LEFT - : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT - ? LegendPosition.BELOW_CHART_RIGHT - : LegendPosition.BELOW_CHART_CENTER); - } else { - if (mHorizontalAlignment == LegendHorizontalAlignment.LEFT) - return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside - ? LegendPosition.LEFT_OF_CHART_INSIDE - : (mVerticalAlignment == LegendVerticalAlignment.CENTER - ? LegendPosition.LEFT_OF_CHART_CENTER - : LegendPosition.LEFT_OF_CHART); - else - return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside - ? LegendPosition.RIGHT_OF_CHART_INSIDE - : (mVerticalAlignment == LegendVerticalAlignment.CENTER - ? LegendPosition.RIGHT_OF_CHART_CENTER - : LegendPosition.RIGHT_OF_CHART); - } - } - - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public void setPosition(LegendPosition newValue) { - - switch (newValue) { - case LEFT_OF_CHART: - case LEFT_OF_CHART_INSIDE: - case LEFT_OF_CHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.LEFT; - mVerticalAlignment = newValue == LegendPosition.LEFT_OF_CHART_CENTER - ? LegendVerticalAlignment.CENTER - : LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.VERTICAL; - break; - - case RIGHT_OF_CHART: - case RIGHT_OF_CHART_INSIDE: - case RIGHT_OF_CHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.RIGHT; - mVerticalAlignment = newValue == LegendPosition.RIGHT_OF_CHART_CENTER - ? LegendVerticalAlignment.CENTER - : LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.VERTICAL; - break; - - case ABOVE_CHART_LEFT: - case ABOVE_CHART_CENTER: - case ABOVE_CHART_RIGHT: - mHorizontalAlignment = newValue == LegendPosition.ABOVE_CHART_LEFT - ? LegendHorizontalAlignment.LEFT - : (newValue == LegendPosition.ABOVE_CHART_RIGHT - ? LegendHorizontalAlignment.RIGHT - : LegendHorizontalAlignment.CENTER); - mVerticalAlignment = LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.HORIZONTAL; - break; - - case BELOW_CHART_LEFT: - case BELOW_CHART_CENTER: - case BELOW_CHART_RIGHT: - mHorizontalAlignment = newValue == LegendPosition.BELOW_CHART_LEFT - ? LegendHorizontalAlignment.LEFT - : (newValue == LegendPosition.BELOW_CHART_RIGHT - ? LegendHorizontalAlignment.RIGHT - : LegendHorizontalAlignment.CENTER); - mVerticalAlignment = LegendVerticalAlignment.BOTTOM; - mOrientation = LegendOrientation.HORIZONTAL; - break; - - case PIECHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.CENTER; - mVerticalAlignment = LegendVerticalAlignment.CENTER; - mOrientation = LegendOrientation.VERTICAL; - break; - } - - mDrawInside = newValue == LegendPosition.LEFT_OF_CHART_INSIDE - || newValue == LegendPosition.RIGHT_OF_CHART_INSIDE; - } - /** * returns the horizontal alignment of the legend * @@ -907,8 +703,7 @@ else if (wasStacked) { width += Utils.calcTextWidth(labelpaint, label); - if (i < entryCount - 1) - maxHeight += labelLineHeight + yEntrySpace; + maxHeight += labelLineHeight + yEntrySpace; } else { wasStacked = true; width += formSize; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java index f164d8341f..7bd7b8e6c3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java @@ -142,10 +142,10 @@ public void draw(Canvas canvas, float posX, float posY) { float width = mSize.width; float height = mSize.height; - if (width == 0.f && mDrawable != null) { + if (width == 0.f) { width = mDrawable.getIntrinsicWidth(); } - if (height == 0.f && mDrawable != null) { + if (height == 0.f) { height = mDrawable.getIntrinsicHeight(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 2381dbf868..d2071ec5a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -73,6 +73,11 @@ public class YAxis extends AxisBase { */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + /** + * the horizontal offset of the y-label + */ + private float mXLabelOffset = 0.0f; + /** * enum for the position of the y-labels relative to the chart */ @@ -174,6 +179,22 @@ public void setPosition(YAxisLabelPosition pos) { mPosition = pos; } + /** + * returns the horizontal offset of the y-label + */ + public float getLabelXOffset() { + return mXLabelOffset; + } + + /** + * sets the horizontal offset of the y-label + * + * @param xOffset + */ + public void setLabelXOffset(float xOffset) { + mXLabelOffset = xOffset; + } + /** * returns true if drawing the top y-axis label entry is enabled * @@ -370,6 +391,7 @@ public boolean needsOffset() { /** * Returns true if autoscale restriction for axis min value is enabled */ + @Deprecated public boolean isUseAutoScaleMinRestriction( ) { return mUseAutoScaleRestrictionMin; } @@ -377,6 +399,7 @@ public boolean isUseAutoScaleMinRestriction( ) { /** * Sets autoscale restriction for axis min value as enabled/disabled */ + @Deprecated public void setUseAutoScaleMinRestriction( boolean isEnabled ) { mUseAutoScaleRestrictionMin = isEnabled; } @@ -384,6 +407,7 @@ public void setUseAutoScaleMinRestriction( boolean isEnabled ) { /** * Returns true if autoscale restriction for axis max value is enabled */ + @Deprecated public boolean isUseAutoScaleMaxRestriction() { return mUseAutoScaleRestrictionMax; } @@ -391,6 +415,7 @@ public boolean isUseAutoScaleMaxRestriction() { /** * Sets autoscale restriction for axis max value as enabled/disabled */ + @Deprecated public void setUseAutoScaleMaxRestriction( boolean isEnabled ) { mUseAutoScaleRestrictionMax = isEnabled; } @@ -402,24 +427,26 @@ public void calculate(float dataMin, float dataMax) { float min = dataMin; float max = dataMax; - // if custom, use value as is, else use data value - if( mCustomAxisMin ) { - if( mUseAutoScaleRestrictionMin ) { - min = Math.min( dataMin, mAxisMinimum ); - } else { - min = mAxisMinimum; + // Make sure max is greater than min + // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991 + if (min > max) + { + if (mCustomAxisMax && mCustomAxisMin) + { + float t = min; + min = max; + max = t; } - } - - if( mCustomAxisMax ) { - if( mUseAutoScaleRestrictionMax ) { - max = Math.max( max, mAxisMaximum ); - } else { - max = mAxisMaximum; + else if (mCustomAxisMax) + { + min = max < 0f ? max * 1.5f : max * 0.5f; + } + else if (mCustomAxisMin) + { + max = min < 0f ? min * 0.5f : min * 1.5f; } } - // temporary range (before calculations) float range = Math.abs(max - min); // in case all values are equal @@ -428,13 +455,13 @@ public void calculate(float dataMin, float dataMax) { min = min - 1f; } - float bottomSpace = range / 100f * getSpaceBottom(); - this.mAxisMinimum = (min - bottomSpace); - - float topSpace = range / 100f * getSpaceTop(); - this.mAxisMaximum = (max + topSpace); + // recalculate + range = Math.abs(max - min); + + // calc extra spacing + this.mAxisMinimum = mCustomAxisMin ? this.mAxisMinimum : min - (range / 100f) * getSpaceBottom(); + this.mAxisMaximum = mCustomAxisMax ? this.mAxisMaximum : max + (range / 100f) * getSpaceTop(); - // calc actual range - this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); + this.mAxisRange = Math.abs(this.mAxisMinimum - this.mAxisMaximum); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 496f4046f8..e65638805b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -4,6 +4,7 @@ import android.graphics.Color; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import java.util.ArrayList; import java.util.List; @@ -38,9 +39,9 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl /** * array of labels used to describe the different values of the stacked bars */ - private String[] mStackLabels = new String[]{ - "Stack" - }; + private String[] mStackLabels = new String[]{}; + + protected List mFills = null; public BarDataSet(List yVals, String label) { super(yVals, label); @@ -54,8 +55,8 @@ public BarDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BarDataSet copied = new BarDataSet(entries, getLabel()); copy(copied); @@ -71,6 +72,67 @@ protected void copy(BarDataSet barDataSet) { barDataSet.mHighLightAlpha = mHighLightAlpha; } + @Override + public List getFills() { + return mFills; + } + + @Override + public Fill getFill(int index) { + return mFills.get(index % mFills.size()); + } + + /** + * This method is deprecated. + * Use getFills() instead. + */ + @Deprecated + public List getGradients() { + return mFills; + } + + /** + * This method is deprecated. + * Use getFill(...) instead. + * + * @param index + */ + @Deprecated + public Fill getGradient(int index) { + return getFill(index); + } + + /** + * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. + * + * @param startColor + * @param endColor + */ + public void setGradientColor(int startColor, int endColor) { + mFills.clear(); + mFills.add(new Fill(startColor, endColor)); + } + + /** + * This method is deprecated. + * Use setFills(...) instead. + * + * @param gradientColors + */ + @Deprecated + public void setGradientColors(List gradientColors) { + this.mFills = gradientColors; + } + + /** + * Sets the fills for the bars in this dataset. + * + * @param fills + */ + public void setFills(List fills) { + this.mFills = fills; + } + /** * Calculates the total number of entries this DataSet represents, including * stacks. All values belonging to a stack are calculated separately. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 7800986dcd..7e7445cac7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; @@ -29,10 +28,6 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; - protected GradientColor mGradientColor = null; - - protected List mGradientColors = null; - /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -146,21 +141,6 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } - @Override - public GradientColor getGradientColor() { - return mGradientColor; - } - - @Override - public List getGradientColors() { - return mGradientColors; - } - - @Override - public GradientColor getGradientColor(int index) { - return mGradientColors.get(index % mGradientColors.size()); - } - /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -236,25 +216,6 @@ public void setColor(int color) { mColors.add(color); } - /** - * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. - * - * @param startColor - * @param endColor - */ - public void setGradientColor(int startColor, int endColor) { - mGradientColor = new GradientColor(startColor, endColor); - } - - /** - * Sets the start and end color for gradient colors, ONLY color that should be used for this DataSet. - * - * @param gradientColors - */ - public void setGradientColors(List gradientColors) { - this.mGradientColors = gradientColors; - } - /** * Sets a color with a specific alpha value. * @@ -534,8 +495,6 @@ protected void copy(BaseDataSet baseDataSet) { baseDataSet.mFormLineDashEffect = mFormLineDashEffect; baseDataSet.mFormLineWidth = mFormLineWidth; baseDataSet.mFormSize = mFormSize; - baseDataSet.mGradientColor = mGradientColor; - baseDataSet.mGradientColors = mGradientColors; baseDataSet.mHighlightEnabled = mHighlightEnabled; baseDataSet.mIconsOffset = mIconsOffset; baseDataSet.mValueColors = mValueColors; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 1f88272dd9..9ef87fb2d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -42,8 +42,8 @@ protected void calcMinMax(BubbleEntry e) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BubbleDataSet copied = new BubbleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index c7f8362803..dcd5b76cea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -80,8 +80,8 @@ public CandleDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } CandleDataSet copied = new CandleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 60d89f4753..bfc5ed7016 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -400,7 +400,7 @@ public boolean removeDataSet(T d) { // if a DataSet was removed if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; @@ -527,7 +527,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = set.removeEntry(e); if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 39625b30f9..0b36aa3bef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -3,6 +3,7 @@ import android.util.Log; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; @@ -91,18 +92,26 @@ public void calcMinMax() { if (data.getXMin() < mXMin) mXMin = data.getXMin(); - if (data.mLeftAxisMax > mLeftAxisMax) - mLeftAxisMax = data.mLeftAxisMax; - - if (data.mLeftAxisMin < mLeftAxisMin) - mLeftAxisMin = data.mLeftAxisMin; - - if (data.mRightAxisMax > mRightAxisMax) - mRightAxisMax = data.mRightAxisMax; - - if (data.mRightAxisMin < mRightAxisMin) - mRightAxisMin = data.mRightAxisMin; - + for (IBarLineScatterCandleBubbleDataSet dataset : sets) { + if (dataset.getAxisDependency() == YAxis.AxisDependency.LEFT) { + if (dataset.getYMax() > mLeftAxisMax) { + mLeftAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mLeftAxisMin) { + mLeftAxisMin = dataset.getYMin(); + } + } + else { + if (dataset.getYMax() > mRightAxisMax) { + mRightAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mRightAxisMin) { + mRightAxisMin = dataset.getYMin(); + } + } + } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 3c69d9c58f..fda07efef2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -17,7 +17,7 @@ public abstract class DataSet extends BaseDataSet { /** * the entries that this DataSet represents / holds together */ - protected List mValues = null; + protected List mEntries; /** * maximum y-value in the value array @@ -45,15 +45,15 @@ public abstract class DataSet extends BaseDataSet { * label that describes the DataSet can be specified. The label can also be * used to retrieve the DataSet from a ChartData object. * - * @param values + * @param entries * @param label */ - public DataSet(List values, String label) { + public DataSet(List entries, String label) { super(label); - this.mValues = values; + this.mEntries = entries; - if (mValues == null) - mValues = new ArrayList(); + if (mEntries == null) + mEntries = new ArrayList(); calcMinMax(); } @@ -61,35 +61,36 @@ public DataSet(List values, String label) { @Override public void calcMinMax() { - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - for (T e : mValues) { + if (mEntries == null || mEntries.isEmpty()) + return; + + for (T e : mEntries) { calcMinMax(e); } } @Override public void calcMinMaxY(float fromX, float toX) { - - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; + + if (mEntries == null || mEntries.isEmpty()) + return; int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); + if (indexTo < indexFrom) return; + for (int i = indexFrom; i <= indexTo; i++) { // only recalculate y - calcMinMaxY(mValues.get(i)); + calcMinMaxY(mEntries.get(i)); } } @@ -128,25 +129,47 @@ protected void calcMinMaxY(T e) { @Override public int getEntryCount() { - return mValues.size(); + return mEntries.size(); } /** - * Returns the array of entries that this DataSet represents. + * This method is deprecated. + * Use getEntries() instead. * * @return */ + @Deprecated public List getValues() { - return mValues; + return mEntries; } /** - * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * Returns the array of entries that this DataSet represents. * * @return */ + public List getEntries() { + return mEntries; + } + + /** + * This method is deprecated. + * Use setEntries(...) instead. + * + * @param values + */ + @Deprecated public void setValues(List values) { - mValues = values; + setEntries(values); + } + + /** + * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * + * @return + */ + public void setEntries(List entries) { + mEntries = entries; notifyDataSetChanged(); } @@ -169,8 +192,8 @@ protected void copy(DataSet dataSet) { public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(toSimpleString()); - for (int i = 0; i < mValues.size(); i++) { - buffer.append(mValues.get(i).toString() + " "); + for (int i = 0; i < mEntries.size(); i++) { + buffer.append(mEntries.get(i).toString() + " "); } return buffer.toString(); } @@ -183,7 +206,7 @@ public String toString() { */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); - buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mValues.size() + + buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mEntries.size() + "\n"); return buffer.toString(); } @@ -214,23 +237,23 @@ public void addEntryOrdered(T e) { if (e == null) return; - if (mValues == null) { - mValues = new ArrayList(); + if (mEntries == null) { + mEntries = new ArrayList(); } calcMinMax(e); - if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { + if (mEntries.size() > 0 && mEntries.get(mEntries.size() - 1).getX() > e.getX()) { int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP); - mValues.add(closestIndex, e); + mEntries.add(closestIndex, e); } else { - mValues.add(e); + mEntries.add(e); } } @Override public void clear() { - mValues.clear(); + mEntries.clear(); notifyDataSetChanged(); } @@ -240,9 +263,9 @@ public boolean addEntry(T e) { if (e == null) return false; - List values = getValues(); + List values = getEntries(); if (values == null) { - values = new ArrayList(); + values = new ArrayList<>(); } calcMinMax(e); @@ -257,11 +280,11 @@ public boolean removeEntry(T e) { if (e == null) return false; - if (mValues == null) + if (mEntries == null) return false; // remove the entry - boolean removed = mValues.remove(e); + boolean removed = mEntries.remove(e); if (removed) { calcMinMax(); @@ -272,7 +295,7 @@ public boolean removeEntry(T e) { @Override public int getEntryIndex(Entry e) { - return mValues.indexOf(e); + return mEntries.indexOf(e); } @Override @@ -280,7 +303,7 @@ public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { int index = getEntryIndex(xValue, closestToY, rounding); if (index > -1) - return mValues.get(index); + return mEntries.get(index); return null; } @@ -291,24 +314,24 @@ public T getEntryForXValue(float xValue, float closestToY) { @Override public T getEntryForIndex(int index) { - return mValues.get(index); + return mEntries.get(index); } @Override public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { - if (mValues == null || mValues.isEmpty()) + if (mEntries == null || mEntries.isEmpty()) return -1; int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; int closest = high; while (low < high) { int m = (low + high) / 2; - final float d1 = mValues.get(m).getX() - xValue, - d2 = mValues.get(m + 1).getX() - xValue, + final float d1 = mEntries.get(m).getX() - xValue, + d2 = mEntries.get(m + 1).getX() - xValue, ad1 = Math.abs(d1), ad2 = Math.abs(d2); if (ad2 < ad1) { @@ -335,10 +358,10 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { } if (closest != -1) { - float closestXValue = mValues.get(closest).getX(); + float closestXValue = mEntries.get(closest).getX(); if (rounding == Rounding.UP) { // If rounding up, and found x-value is lower than specified x, and we can go upper... - if (closestXValue < xValue && closest < mValues.size() - 1) { + if (closestXValue < xValue && closest < mEntries.size() - 1) { ++closest; } } else if (rounding == Rounding.DOWN) { @@ -350,23 +373,23 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { // Search by closest to y-value if (!Float.isNaN(closestToY)) { - while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue) + while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue) closest -= 1; - float closestYValue = mValues.get(closest).getY(); + float closestYValue = mEntries.get(closest).getY(); int closestYIndex = closest; while (true) { closest += 1; - if (closest >= mValues.size()) + if (closest >= mEntries.size()) break; - final Entry value = mValues.get(closest); + final Entry value = mEntries.get(closest); if (value.getX() != closestXValue) break; - if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) { + if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) { closestYValue = closestToY; closestYIndex = closest; } @@ -385,22 +408,22 @@ public List getEntriesForXValue(float xValue) { List entries = new ArrayList(); int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; while (low <= high) { int m = (high + low) / 2; - T entry = mValues.get(m); + T entry = mEntries.get(m); // if we have a match if (xValue == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xValue) + while (m > 0 && mEntries.get(m - 1).getX() == xValue) m--; - high = mValues.size(); + high = mEntries.size(); // loop over all "equal" entries for (; m < high; m++) { - entry = mValues.get(m); + entry = mEntries.get(m); if (entry.getX() == xValue) { entries.add(entry); } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index c1018d1fb4..10d1837ecd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -85,8 +85,8 @@ public LineDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } LineDataSet copied = new LineDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index 688585cbdd..b4347e4647 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -17,6 +17,7 @@ */ public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet implements ILineRadarDataSet { + // TODO: Move to using `Fill` class /** * the color that is used for filling the line surface */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index db7972a3fb..423ce19b16 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import android.util.Log; + import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; @@ -46,6 +48,18 @@ public IPieDataSet getDataSet() { return mDataSets.get(0); } + @Override + public List getDataSets() { + List dataSets = super.getDataSets(); + + if (dataSets.size() < 1) { + Log.e("MPAndroidChart", + "Found multiple data sets while pie chart only allows one"); + } + + return dataSets; + } + /** * The PieData object can only have one DataSet. Use getDataSet() method instead. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index e592399513..c83b24547b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; +import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; @@ -22,13 +23,14 @@ public class PieDataSet extends DataSet implements IPieDataSet { private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; - private boolean mUsingSliceColorAsValueLineColor = false; private int mValueLineColor = 0xff000000; + private boolean mUseValueColorForLine = false; private float mValueLineWidth = 1.0f; private float mValueLinePart1OffsetPercentage = 75.f; private float mValueLinePart1Length = 0.3f; private float mValueLinePart2Length = 0.4f; private boolean mValueLineVariableLength = true; + private Integer mHighlightColor = null; public PieDataSet(List yVals, String label) { super(yVals, label); @@ -38,8 +40,8 @@ public PieDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList<>(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } PieDataSet copied = new PieDataSet(entries, getLabel()); copy(copied); @@ -135,15 +137,23 @@ public void setYValuePosition(ValuePosition yValuePosition) { } /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * This method is deprecated. + * Use isUseValueColorForLineEnabled() instead. */ - @Override + @Deprecated public boolean isUsingSliceColorAsValueLineColor() { - return mUsingSliceColorAsValueLineColor; + return isUseValueColorForLineEnabled(); } - public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLineColor) { - this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor; + /** + * This method is deprecated. + * Use setUseValueColorForLine(...) instead. + * + * @param enabled + */ + @Deprecated + public void setUsingSliceColorAsValueLineColor(boolean enabled) { + setUseValueColorForLine(enabled); } /** @@ -158,6 +168,17 @@ public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } + @Override + public boolean isUseValueColorForLineEnabled() + { + return mUseValueColorForLine; + } + + public void setUseValueColorForLine(boolean enabled) + { + mUseValueColorForLine = enabled; + } + /** * When valuePosition is OutsideSlice, indicates line width */ @@ -218,6 +239,21 @@ public void setValueLineVariableLength(boolean valueLineVariableLength) { this.mValueLineVariableLength = valueLineVariableLength; } + /** Gets the color for the highlighted sector */ + @Override + @Nullable + public Integer getHighlightColor() + { + return mHighlightColor; + } + + /** Sets the color for the highlighted sector (null for using entry color) */ + public void setHighlightColor(@Nullable Integer color) + { + this.mHighlightColor = color; + } + + public enum ValuePosition { INSIDE_SLICE, OUTSIDE_SLICE diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java index 09c94b417d..8a9740b6b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java @@ -102,8 +102,8 @@ public void setHighlightCircleStrokeWidth(float strokeWidth) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } RadarDataSet copied = new RadarDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index d234c751a0..85ed808160 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -48,8 +48,8 @@ public ScatterDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } ScatterDataSet copied = new ScatterDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java new file mode 100644 index 0000000000..9351341c76 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java @@ -0,0 +1,146 @@ + +package com.github.mikephil.charting.data.filter; + +import java.util.ArrayList; + +/** + * Implemented according to modified Douglas Peucker {@link} + * http://psimpl.sourceforge.net/douglas-peucker.html + */ +public class ApproximatorN +{ + public float[] reduceWithDouglasPeucker(float[] points, float resultCount) { + + int pointCount = points.length / 2; + + // if a shape has 2 or less points it cannot be reduced + if (resultCount <= 2 || resultCount >= pointCount) + return points; + + boolean[] keep = new boolean[pointCount]; + + // first and last always stay + keep[0] = true; + keep[pointCount - 1] = true; + + int currentStoredPoints = 2; + + ArrayList queue = new ArrayList<>(); + Line line = new Line(0, pointCount - 1, points); + queue.add(line); + + do { + line = queue.remove(queue.size() - 1); + + // store the key + keep[line.index] = true; + + // check point count tolerance + currentStoredPoints += 1; + + if (currentStoredPoints == resultCount) + break; + + // split the polyline at the key and recurse + Line left = new Line(line.start, line.index, points); + if (left.index > 0) { + int insertionIndex = insertionIndex(left, queue); + queue.add(insertionIndex, left); + } + + Line right = new Line(line.index, line.end, points); + if (right.index > 0) { + int insertionIndex = insertionIndex(right, queue); + queue.add(insertionIndex, right); + } + } while (queue.isEmpty()); + + float[] reducedEntries = new float[currentStoredPoints * 2]; + + for (int i = 0, i2 = 0, r2 = 0; i < currentStoredPoints; i++, r2 += 2) { + if (keep[i]) { + reducedEntries[i2++] = points[r2]; + reducedEntries[i2++] = points[r2 + 1]; + } + } + + return reducedEntries; + } + + private static float distanceToLine( + float ptX, float ptY, float[] + fromLinePoint1, float[] fromLinePoint2) { + float dx = fromLinePoint2[0] - fromLinePoint1[0]; + float dy = fromLinePoint2[1] - fromLinePoint1[1]; + + float dividend = Math.abs( + dy * ptX - + dx * ptY - + fromLinePoint1[0] * fromLinePoint2[1] + + fromLinePoint2[0] * fromLinePoint1[1]); + double divisor = Math.sqrt(dx * dx + dy * dy); + + return (float)(dividend / divisor); + } + + private static class Line { + int start; + int end; + + float distance = 0; + int index = 0; + + Line(int start, int end, float[] points) { + this.start = start; + this.end = end; + + float[] startPoint = new float[]{points[start * 2], points[start * 2 + 1]}; + float[] endPoint = new float[]{points[end * 2], points[end * 2 + 1]}; + + if (end <= start + 1) return; + + for (int i = start + 1, i2 = i * 2; i < end; i++, i2 += 2) { + float distance = distanceToLine( + points[i2], points[i2 + 1], + startPoint, endPoint); + + if (distance > this.distance) { + this.index = i; + this.distance = distance; + } + } + } + + boolean equals(final Line rhs) { + return (start == rhs.start) && (end == rhs.end) && index == rhs.index; + } + + boolean lessThan(final Line rhs) { + return distance < rhs.distance; + } + } + + private static int insertionIndex(Line line, ArrayList queue) { + int min = 0; + int max = queue.size(); + + while (!queue.isEmpty()) { + int midIndex = min + (max - min) / 2; + Line midLine = queue.get(midIndex); + + if (midLine.equals(line)) { + return midIndex; + } + else if (line.lessThan(midLine)) { + // perform search in left half + max = midIndex; + } + else { + // perform search in right half + min = midIndex + 1; + } + } + + return min; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 032698d5e5..62307cbeaf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -60,10 +60,18 @@ public class Highlight { */ private float mDrawY; + public Highlight(float x, float y, int dataSetIndex, int dataIndex) { + this.mX = x; + this.mY = y; + this.mDataSetIndex = dataSetIndex; + this.mDataIndex = dataIndex; + } + public Highlight(float x, float y, int dataSetIndex) { this.mX = x; this.mY = y; this.mDataSetIndex = dataSetIndex; + this.mDataIndex = -1; } public Highlight(float x, int dataSetIndex, int stackIndex) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index fbdfd79531..5e82a48420 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -1,12 +1,19 @@ package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.Fill; + +import java.util.List; /** * Created by philipp on 21/10/15. */ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { + List getFills(); + + Fill getFill(int index); + /** * Returns true if this DataSet is stacked (stacksize > 1) or not. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index f64db706e0..fd8af7064b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -286,28 +285,6 @@ public interface IDataSet { */ int getColor(); - /** - * Returns the Gradient color model - * - * @return - */ - GradientColor getGradientColor(); - - /** - * Returns the Gradient colors - * - * @return - */ - List getGradientColors(); - - /** - * Returns the Gradient colors - * - * @param index - * @return - */ - GradientColor getGradientColor(int index); - /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 1698ef786b..b228fca0e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; +import androidx.annotation.Nullable; + import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -36,14 +38,14 @@ public interface IPieDataSet extends IDataSet { PieDataSet.ValuePosition getYValuePosition(); /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * When valuePosition is OutsideSlice, indicates line color * */ - boolean isUsingSliceColorAsValueLineColor(); + int getValueLineColor(); /** - * When valuePosition is OutsideSlice, indicates line color + * When valuePosition is OutsideSlice and enabled, line will have the same color as the slice * */ - int getValueLineColor(); + boolean isUseValueColorForLineEnabled(); /** * When valuePosition is OutsideSlice, indicates line width @@ -70,5 +72,11 @@ public interface IPieDataSet extends IDataSet { * */ boolean isValueLineVariableLength(); + /** + * Gets the color for the highlighted sector + * */ + @Nullable + Integer getHighlightColor(); + } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 53ab12a369..5685d32fa0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -580,12 +580,19 @@ public boolean onDoubleTap(MotionEvent e) { MPPointF trans = getTrans(e.getX(), e.getY()); - mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); + float scaleX = mChart.isScaleXEnabled() ? 1.4f : 1f; + float scaleY = mChart.isScaleYEnabled() ? 1.4f : 1f; + + mChart.zoom(scaleX, scaleY, trans.x, trans.y); if (mChart.isLogEnabled()) Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); + if (l != null) { + l.onChartScale(e, scaleX, scaleY); + } + MPPointF.recycleInstance(trans); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java index a17cdde941..da0c5ed180 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -57,7 +57,7 @@ public interface OnChartGestureListener { void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY); /** - * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. + * Callbacks when the chart is scaled / zoomed via pinch zoom / double-tap gesture. * * @param me * @param scaleX scalefactor on the x-axis diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 527617472a..d3527f924a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -45,6 +45,7 @@ public boolean onTouch(View v, MotionEvent event) { return true; // if rotation by touch is enabled + // TODO: Also check if the pie itself is being touched, rather than the entire chart area if (mChart.isRotationEnabled()) { float x = event.getX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java index 1162c01198..b5c8715a08 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java @@ -1,28 +1,69 @@ package com.github.mikephil.charting.model; -public class GradientColor { +import com.github.mikephil.charting.utils.Fill; - private int startColor; - private int endColor; - - public GradientColor(int startColor, int endColor) { - this.startColor = startColor; - this.endColor = endColor; +/** + * Deprecated. Use `Fill` + */ +@Deprecated +public class GradientColor extends Fill +{ + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getStartColor() + { + return getGradientColors()[0]; } - public int getStartColor() { - return startColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setStartColor(int startColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + startColor, + getGradientColors() != null && getGradientColors().length > 1 + ? getGradientColors()[1] + : 0 + }); + } else + { + getGradientColors()[0] = startColor; + } } - public void setStartColor(int startColor) { - this.startColor = startColor; + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getEndColor() + { + return getGradientColors()[1]; } - public int getEndColor() { - return endColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setEndColor(int endColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + getGradientColors() != null && getGradientColors().length > 0 + ? getGradientColors()[0] + : 0, + endColor + }); + } else + { + getGradientColors()[1] = endColor; + } } - public void setEndColor(int endColor) { - this.endColor = endColor; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 90528a1359..72ea2d17c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -174,9 +174,12 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); + } int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0; @@ -214,11 +217,14 @@ protected void computeAxisValues(float min, float max) { double f; int i; - if (interval != 0.0) { + if (interval != 0.0 && last != first) { for (f = first; f <= last; f += interval) { ++n; } } + else if (last == first && n == 0) { + n = 1; + } mAxis.mEntryCount = n; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index d3f71af02c..1656a3a37f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -15,12 +15,11 @@ import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import android.graphics.LinearGradient; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -145,13 +144,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) continue; @@ -162,38 +163,24 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!isSingleColor) { // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j / 4)); + mRenderPaint.setColor(dataSet.getColor(pos)); } - if (dataSet.getGradientColor() != null) { - GradientColor gradientColor = dataSet.getGradientColor(); - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - gradientColor.getStartColor(), - gradientColor.getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.DOWN : Fill.Direction.UP); } - - if (dataSet.getGradientColors() != null) { - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - dataSet.getGradientColor(j / 4).getStartColor(), - dataSet.getGradientColor(j / 4).getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } - - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); - if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mBarBorderPaint); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 17bba048b9..5ce19c2c9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -67,6 +67,9 @@ protected float getShapeSize(float entrySize, float maxSize, float reference, bo protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { + if (dataSet.getEntryCount() < 1) + return; + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseY = mAnimator.getPhaseY(); @@ -105,7 +108,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - final int color = dataSet.getColor((int) entry.getX()); + final int color = dataSet.getColor(j); mRenderPaint.setColor(color); c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint); @@ -131,7 +134,7 @@ public void drawValues(Canvas c) { IBubbleDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index e4c06fe46c..991b702117 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -264,7 +264,7 @@ public void drawValues(Canvas c) { ICandleDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index a1e1650865..0cd72345fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -112,13 +113,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) break; @@ -132,8 +135,20 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mRenderPaint.setColor(dataSet.getColor(j / 4)); } - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT); + } + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); + } if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], @@ -201,7 +216,8 @@ public void drawValues(Canvas c) { // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); - negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) + - (buffer.buffer[j + 2] - buffer.buffer[j]); if (isInverted) { posOffset = -posOffset - valueTextWidth; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 85597db6a1..5d49580561 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -90,6 +90,7 @@ public void computeLegend(ChartData data) { for (int i = 0; i < data.getDataSetCount(); i++) { IDataSet dataSet = data.getDataSetByIndex(i); + if (dataSet == null) continue; List clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); @@ -100,10 +101,19 @@ public void computeLegend(ChartData data) { IBarDataSet bds = (IBarDataSet) dataSet; String[] sLabels = bds.getStackLabels(); - for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { + int minEntries = Math.min(clrs.size(), bds.getStackSize()); + + for (int j = 0; j < minEntries; j++) { + String label; + if (sLabels.length > 0) { + int labelIndex = j % minEntries; + label = labelIndex < sLabels.length ? sLabels[labelIndex] : null; + } else { + label = null; + } computedEntries.add(new LegendEntry( - sLabels[j % sLabels.length], + label, dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a0e1777569..a86c16f76b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -185,7 +185,6 @@ protected void drawHorizontalBezier(ILineDataSet dataSet) { protected void drawCubicBezier(ILineDataSet dataSet) { - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -323,10 +322,14 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // more than 1 color if (dataSet.getColors().size() > 1) { - if (mLineBuffer.length <= pointsPerEntryPair * 2) - mLineBuffer = new float[pointsPerEntryPair * 4]; + int numberOfFloats = pointsPerEntryPair * 2; - for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { + if (mLineBuffer.length <= numberOfFloats) + mLineBuffer = new float[numberOfFloats * 2]; + + int max = mXBounds.min + mXBounds.range; + + for (int j = mXBounds.min; j < max; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -357,16 +360,26 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[3] = mLineBuffer[1]; } + // Determine the start and end coordinates of the line, and make sure they differ. + float firstCoordinateX = mLineBuffer[0]; + float firstCoordinateY = mLineBuffer[1]; + float lastCoordinateX = mLineBuffer[numberOfFloats - 2]; + float lastCoordinateY = mLineBuffer[numberOfFloats - 1]; + + if (firstCoordinateX == lastCoordinateX && + firstCoordinateY == lastCoordinateY) + continue; + trans.pointValuesToPixel(mLineBuffer); - if (!mViewPortHandler.isInBoundsRight(mLineBuffer[0])) + if (!mViewPortHandler.isInBoundsRight(firstCoordinateX)) break; // make sure the lines don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2]) - || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler - .isInBoundsBottom(mLineBuffer[3]))) + if (!mViewPortHandler.isInBoundsLeft(lastCoordinateX) || + !mViewPortHandler.isInBoundsTop(Math.max(firstCoordinateY, lastCoordinateY)) || + !mViewPortHandler.isInBoundsBottom(Math.min(firstCoordinateY, lastCoordinateY))) continue; // get the color that is set for this line-segment @@ -497,12 +510,12 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex // create a new path Entry currentEntry = null; - Entry previousEntry = null; + Entry previousEntry = entry; for (int x = startIndex + 1; x <= endIndex; x++) { currentEntry = dataSet.getEntryForIndex(x); - if (isDrawSteppedEnabled && previousEntry != null) { + if (isDrawSteppedEnabled) { filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY); } @@ -530,7 +543,7 @@ public void drawValues(Canvas c) { ILineDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 8c37a0b83d..f35c775d45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -231,6 +231,9 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; + final float roundedRadius = (radius - (radius * mChart.getHoleRadius() / 100f)) / 2f; + final RectF roundedCircleBox = new RectF(); + final boolean drawRoundedSlices = drawInnerArc && mChart.isDrawRoundedSlicesEnabled(); int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { @@ -250,133 +253,151 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero - if ((Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { + if (!(Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { + angle += sliceAngle * phaseX; + continue; + } - if (!mChart.needsHighlight(j)) { + // Don't draw if it's highlighted, unless the chart uses rounded slices + if (dataSet.isHighlightEnabled() && mChart.needsHighlight(j) && !drawRoundedSlices) { + angle += sliceAngle * phaseX; + continue; + } - final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; + final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(dataSet.getColor(j)); + mRenderPaint.setColor(dataSet.getColor(j)); - final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? - 0.f : - sliceSpace / (Utils.FDEG2RAD * radius); - final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; - float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; - if (sweepAngleOuter < 0.f) { - sweepAngleOuter = 0.f; - } + final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * radius); + final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; + if (sweepAngleOuter < 0.f) { + sweepAngleOuter = 0.f; + } - mPathBuffer.reset(); + mPathBuffer.reset(); - float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); - float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); + if (drawRoundedSlices) { + float x = center.x + (radius - roundedRadius) * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + float y = center.y + (radius - roundedRadius) * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); + roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius); + } - if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { - // Android is doing "mod 360" - mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); - } else { + float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); - mPathBuffer.moveTo(arcStartPointX, arcStartPointY); + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); + } else { - mPathBuffer.arcTo( - circleBox, - startAngleOuter, - sweepAngleOuter - ); - } + if (drawRoundedSlices) { + mPathBuffer.arcTo(roundedCircleBox, startAngleOuter + 180, -180); + } - // API < 21 does not receive floats in addArc, but a RectF - mInnerRectBuffer.set( - center.x - innerRadius, - center.y - innerRadius, - center.x + innerRadius, - center.y + innerRadius); - - if (drawInnerArc && - (innerRadius > 0.f || accountForSliceSpacing)) { - - if (accountForSliceSpacing) { - float minSpacedRadius = - calculateMinimumRadiusForSpacedSlice( - center, radius, - sliceAngle * phaseY, - arcStartPointX, arcStartPointY, - startAngleOuter, - sweepAngleOuter); - - if (minSpacedRadius < 0.f) - minSpacedRadius = -minSpacedRadius; - - innerRadius = Math.max(innerRadius, minSpacedRadius); - } + mPathBuffer.arcTo( + circleBox, + startAngleOuter, + sweepAngleOuter + ); + } - final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? - 0.f : - sliceSpace / (Utils.FDEG2RAD * innerRadius); - final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; - float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; - if (sweepAngleInner < 0.f) { - sweepAngleInner = 0.f; - } - final float endAngleInner = startAngleInner + sweepAngleInner; - - if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { - // Android is doing "mod 360" - mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); - } else { - - mPathBuffer.lineTo( - center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), - center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); - - mPathBuffer.arcTo( - mInnerRectBuffer, - endAngleInner, - -sweepAngleInner - ); - } - } else { + // API < 21 does not receive floats in addArc, but a RectF + mInnerRectBuffer.set( + center.x - innerRadius, + center.y - innerRadius, + center.x + innerRadius, + center.y + innerRadius); - if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { - if (accountForSliceSpacing) { - - float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; - - float sliceSpaceOffset = - calculateMinimumRadiusForSpacedSlice( - center, - radius, - sliceAngle * phaseY, - arcStartPointX, - arcStartPointY, - startAngleOuter, - sweepAngleOuter); - - float arcEndPointX = center.x + - sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); - float arcEndPointY = center.y + - sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); - - mPathBuffer.lineTo( - arcEndPointX, - arcEndPointY); - - } else { - mPathBuffer.lineTo( - center.x, - center.y); - } - } + if (drawInnerArc && (innerRadius > 0.f || accountForSliceSpacing)) { - } + if (accountForSliceSpacing) { + float minSpacedRadius = + calculateMinimumRadiusForSpacedSlice( + center, radius, + sliceAngle * phaseY, + arcStartPointX, arcStartPointY, + startAngleOuter, + sweepAngleOuter); - mPathBuffer.close(); + if (minSpacedRadius < 0.f) + minSpacedRadius = -minSpacedRadius; - mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); + innerRadius = Math.max(innerRadius, minSpacedRadius); } + + final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * innerRadius); + final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; + if (sweepAngleInner < 0.f) { + sweepAngleInner = 0.f; + } + final float endAngleInner = startAngleInner + sweepAngleInner; + + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); + } else { + + if (drawRoundedSlices) { + float x = center.x + (radius - roundedRadius) * (float) Math.cos(endAngleInner * Utils.FDEG2RAD); + float y = center.y + (radius - roundedRadius) * (float) Math.sin(endAngleInner * Utils.FDEG2RAD); + roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius); + mPathBuffer.arcTo(roundedCircleBox, endAngleInner, 180); + } else + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } + } else { + + if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { + if (accountForSliceSpacing) { + + float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; + + float sliceSpaceOffset = + calculateMinimumRadiusForSpacedSlice( + center, + radius, + sliceAngle * phaseY, + arcStartPointX, + arcStartPointY, + startAngleOuter, + sweepAngleOuter); + + float arcEndPointX = center.x + + sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); + float arcEndPointY = center.y + + sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); + + mPathBuffer.lineTo( + arcEndPointX, + arcEndPointY); + + } else { + mPathBuffer.lineTo( + center.x, + center.y); + } + } + } + mPathBuffer.close(); + + mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); + angle += sliceAngle * phaseX; } @@ -397,11 +418,17 @@ public void drawValues(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + final float roundedRadius = (radius - (radius * mChart.getHoleRadius() / 100f)) / 2f; final float holeRadiusPercent = mChart.getHoleRadius() / 100.f; float labelRadiusOffset = radius / 10f * 3.6f; if (mChart.isDrawHoleEnabled()) { labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f; + + if (!mChart.isDrawSlicesUnderHoleEnabled() && mChart.isDrawRoundedSlicesEnabled()) { + // Add curved circle slice and spacing to rotation angle, so that it sits nicely inside + rotationAngle += roundedRadius * 360 / (Math.PI * 2 * radius); + } } final float labelRadius = radius - labelRadiusOffset; @@ -442,7 +469,9 @@ public void drawValues(Canvas c) { int entryCount = dataSet.getEntryCount(); - mValueLinePaint.setColor(dataSet.getValueLineColor()); + boolean isUseValueColorForLineEnabled = dataSet.isUseValueColorForLineEnabled(); + int valueLineColor = dataSet.getValueLineColor(); + mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); final float sliceSpace = getSliceSpace(dataSet); @@ -472,6 +501,7 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getY() / yValueSum * 100f : entry.getY(); + String entryLabel = entry.getLabel(); final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD); @@ -537,12 +567,15 @@ public void drawValues(Canvas c) { labelPty = pt2y; } - if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + int lineColor = ColorTemplate.COLOR_NONE; - if (dataSet.isUsingSliceColorAsValueLineColor()) { - mValueLinePaint.setColor(dataSet.getColor(j)); - } + if (isUseValueColorForLineEnabled) + lineColor = dataSet.getColor(j); + else if (valueLineColor != ColorTemplate.COLOR_NONE) + lineColor = valueLineColor; + if (lineColor != ColorTemplate.COLOR_NONE) { + mValueLinePaint.setColor(lineColor); c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint); c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint); } @@ -559,13 +592,13 @@ public void drawValues(Canvas c) { labelPty, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight); } } else if (drawXOutside) { - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight / 2.f); } } else if (drawYOutside) { @@ -586,13 +619,13 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), x, y + lineHeight); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, x, y + lineHeight); } } else if (drawXInside) { - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, x, y + lineHeight / 2f); } } else if (drawYInside) { @@ -640,7 +673,6 @@ protected void drawEntryLabel(Canvas c, String label, float x, float y) { @Override public void drawExtras(Canvas c) { - // drawCircles(c); drawHole(c); c.drawBitmap(mDrawBitmap.get(), 0, 0, null); drawCenterText(c); @@ -766,6 +798,15 @@ protected void drawCenterText(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { + /* Skip entirely if using rounded circle slices, because it doesn't make sense to highlight + * in this way. + * TODO: add support for changing slice color with highlighting rather than only shifting the slice + */ + + final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); + if (drawInnerArc && mChart.isDrawRoundedSlicesEnabled()) + return; + float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -776,7 +817,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final MPPointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -793,8 +833,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; IPieDataSet set = mChart.getData() - .getDataSetByIndex(indices[i] - .getDataSetIndex()); + .getDataSetByIndex(indices[i].getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) continue; @@ -825,7 +864,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(set.getColor(index)); + Integer highlightColor = set.getHighlightColor(); + if (highlightColor == null) + highlightColor = set.getColor(index); + mRenderPaint.setColor(highlightColor); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 36a38a53c5..ccd077e55c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -49,6 +49,9 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { + if (dataSet.getEntryCount() < 1) + return; + ViewPortHandler viewPortHandler = mViewPortHandler; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -101,7 +104,7 @@ public void drawValues(Canvas c) { IScatterDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index a2bf679777..53cca7ee03 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -119,12 +119,17 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + // draw for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); + c.drawText(text, + fixedPosition + xOffset, + positions[i * 2 + 1] + offset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 71275b03c3..fedf8054a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -142,11 +142,16 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisLabelPaint); + c.drawText(text, + positions[i * 2], + fixedPosition - offset + xOffset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index ee7392e928..f7b1ad9e87 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -52,9 +52,11 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); } boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); @@ -161,6 +163,8 @@ public void renderAxisLabels(Canvas c) { ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int j = from; j < to; j++) { float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; @@ -169,7 +173,7 @@ public void renderAxisLabels(Canvas c) { String label = mYAxis.getFormattedLabel(j); - c.drawText(label, pOut.x + 10, pOut.y, mAxisLabelPaint); + c.drawText(label, pOut.x + xOffset, pOut.y, mAxisLabelPaint); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java new file mode 100644 index 0000000000..d12e1fb8d7 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java @@ -0,0 +1,342 @@ +package com.github.mikephil.charting.utils; + +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class Fill +{ + public enum Type + { + EMPTY, COLOR, LINEAR_GRADIENT, DRAWABLE + } + + public enum Direction + { + DOWN, UP, RIGHT, LEFT + } + + /** + * the type of fill + */ + private Type mType = Type.EMPTY; + + /** + * the color that is used for filling + */ + @Nullable + private Integer mColor = null; + + private Integer mFinalColor = null; + + /** + * the drawable to be used for filling + */ + @Nullable + protected Drawable mDrawable; + + @Nullable + private int[] mGradientColors; + + @Nullable + private float[] mGradientPositions; + + /** + * transparency used for filling + */ + private int mAlpha = 255; + + public Fill() + { + } + + public Fill(int color) + { + this.mType = Type.COLOR; + this.mColor = color; + calculateFinalColor(); + } + + public Fill(int startColor, int endColor) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = new int[]{startColor, endColor}; + } + + public Fill(@NonNull int[] gradientColors) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + } + + public Fill(@NonNull int[] gradientColors, @NonNull float[] gradientPositions) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + this.mGradientPositions = gradientPositions; + } + + public Fill(@NonNull Drawable drawable) + { + this.mType = Type.DRAWABLE; + this.mDrawable = drawable; + } + + public Type getType() + { + return mType; + } + + public void setType(Type type) + { + this.mType = type; + } + + @Nullable + public Integer getColor() + { + return mColor; + } + + public void setColor(int color) + { + this.mColor = color; + calculateFinalColor(); + } + + public int[] getGradientColors() + { + return mGradientColors; + } + + public void setGradientColors(int[] colors) + { + this.mGradientColors = colors; + } + + public float[] getGradientPositions() + { + return mGradientPositions; + } + + public void setGradientPositions(float[] positions) + { + this.mGradientPositions = positions; + } + + public void setGradientColors(int startColor, int endColor) + { + this.mGradientColors = new int[]{startColor, endColor}; + } + + public int getAlpha() + { + return mAlpha; + } + + public void setAlpha(int alpha) + { + this.mAlpha = alpha; + calculateFinalColor(); + } + + private void calculateFinalColor() + { + if (mColor == null) + { + mFinalColor = null; + } else + { + int alpha = (int) Math.floor(((mColor >> 24) / 255.0) * (mAlpha / 255.0) * 255.0); + mFinalColor = (alpha << 24) | (mColor & 0xffffff); + } + } + + public void fillRect(Canvas c, Paint paint, + float left, float top, float right, float bottom, + Direction gradientDirection) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (isClipPathSupported()) + { + int save = c.save(); + + c.clipRect(left, top, right, bottom); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawRect(left, top, right, bottom, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + (int) (gradientDirection == Direction.RIGHT + ? right + : gradientDirection == Direction.LEFT + ? left + : left), + (int) (gradientDirection == Direction.UP + ? bottom + : gradientDirection == Direction.DOWN + ? top + : top), + (int) (gradientDirection == Direction.RIGHT + ? left + : gradientDirection == Direction.LEFT + ? right + : left), + (int) (gradientDirection == Direction.UP + ? top + : gradientDirection == Direction.DOWN + ? bottom + : top), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawRect(left, top, right, bottom, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom); + mDrawable.draw(c); + } + break; + } + } + + public void fillPath(Canvas c, Path path, Paint paint, + @Nullable RectF clipRect) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (clipRect != null && isClipPathSupported()) + { + int save = c.save(); + + c.clipPath(path); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawPath(path, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + 0, + 0, + c.getWidth(), + c.getHeight(), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawPath(path, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + ensureClipPathSupported(); + + int save = c.save(); + c.clipPath(path); + + mDrawable.setBounds( + clipRect == null ? 0 : (int) clipRect.left, + clipRect == null ? 0 : (int) clipRect.top, + clipRect == null ? c.getWidth() : (int) clipRect.right, + clipRect == null ? c.getHeight() : (int) clipRect.bottom); + mDrawable.draw(c); + + c.restoreToCount(save); + } + break; + } + } + + private boolean isClipPathSupported() + { + return Utils.getSDKInt() >= 18; + } + + private void ensureClipPathSupported() + { + if (Utils.getSDKInt() < 18) + { + throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " + + "this code was run on API level " + Utils.getSDKInt() + "."); + } + } +} diff --git a/README.md b/README.md index 55eb482f91..a3253e3ff9 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,7 @@ -**Remember: _It's all about the looks._** - ![banner](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic_smaller.png) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) -[![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![API](https://img.shields.io/badge/API-14%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=14) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) @@ -12,41 +10,32 @@ [**Charts**](https://github.com/danielgindi/Charts) is the iOS version of this library -## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart) - - - - -MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend -SciChart Android. - - - -All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** - -
- - -## Usage :chart_with_upwards_trend: - -**Gradle** +## Table of Contents +1. [Quick Start](#quick-start) + 1. [Gradle](#gradle-setup) + 1. [Maven](#maven-setup) +1. [Documentation](#documentation) +1. [Examples](#examples) +1. [Questions](#report) +1. [Donate](#donate) +1. [Social Media](#social) +1. [More Examples](#more-examples) +1. [License](#licence) +1. [Creators](#creators) + +### Gradle Setup -- **Project level `build.gradle`** ```gradle -allprojects { - repositories { - maven { url 'https://jitpack.io/' } - } +repositories { + maven { url 'https://jitpack.io/' } } -``` -- **App level `build.gradle`** -```gradle + dependencies { - implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' } ``` -**Maven** +### Maven Setup ```xml @@ -55,63 +44,55 @@ dependencies { https://jitpack.io - com.github.PhilJay MPAndroidChart - v3.0.3 + v3.1.0 ```
-## Documentation :notebook_with_decorative_cover: +

Documentation :notebook_with_decorative_cover:

-See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. +See the [**documentation**](https://weeklycoding.com/mpandroidchart/) for examples and general use of MPAndroidChart. -See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for more advanced documentation. +See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/) for more advanced documentation.
-## Examples :eyes: +

Examples :eyes:

+ Download the [MPAndroidChart Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) or look at the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample). [![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI)
-## Questions & Issues :thinking: +

Questions & Issues :thinking:

This repository's issue tracker is only for bugs and feature requests. The maintainers ask that you refrain from asking questions about how to use MPAndroidChart through the issue tracker. -Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer. +Please read the [**documentation**](https://weeklycoding.com/mpandroidchart/) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer.
-## Donations :heart: + **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! -**My Bitcoin Wallet** (Bitcoin only) - -1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg - -**My Ethereum Wallet** (Ethereum only) - -0x04ef098bf9f91871391363e3caf791afa3adc39b - **PayPal** - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! -- [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! +- [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome!
-## Social Media :fire: +

Social Media :fire:

If you like this library, please tell others about it :two_hearts: :two_hearts: @@ -119,13 +100,11 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: [![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) [![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -You can follow the creator on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - -Philipp is also on [StackOverflow](http://stackoverflow.com/users/1590502/philipp-jahoda) +If you like, you can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda).
-## More Examples :+1: +

More Examples :+1:


@@ -195,15 +174,15 @@ Philipp is also on [StackOverflow](http://stackoverflow.com/users/1590502/philip
-# License :page_facing_up: +

License :page_facing_up:

-Copyright 2018 Philipp Jahoda +Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +> http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -213,7 +192,7 @@ limitations under the License.
-## Special Thanks :heart: +

Special Thanks :heart:

These people rock! diff --git a/build.gradle b/build.gradle index 65ca5186cf..ac31f01cf5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,18 +1,16 @@ buildscript { repositories { - jcenter() google() + mavenCentral() } dependencies { - classpath "io.realm:realm-gradle-plugin:4.2.0" - classpath 'com.android.tools.build:gradle:3.1.2' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' + classpath 'com.android.tools.build:gradle:7.0.4' } } allprojects { repositories { - jcenter() google() + mavenCentral() } } diff --git a/gradle.properties b/gradle.properties index 4a9594aeec..0c0632ee2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,3 @@ -org.gradle.jvmargs=-Xmx2048M \ No newline at end of file +android.enableJetifier=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx2048M diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 02b0428be0..ffed3a254e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Wed Apr 25 08:04:33 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip