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 new file mode 100644 index 0000000000..b75838b907 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,37 @@ + + +**Summary** + + +**Expected Behavior** + + +**Possible Solution** + + + +**Device (please complete the following information):** + - Device: [e.g. Google Pixel] + - Android Version [e.g. 7.0] + - 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 new file mode 100644 index 0000000000..3a5938eee9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,44 @@ +--- +name: Bugs +about: Create a bug report to help us improve + +--- + + + +**Summary** + + +**Expected Behavior** + + +**Possible Solution** + + + +**Device (please complete the following information):** + - Device: [e.g. Google Pixel] + - Android Version [e.g. 7.0] + - 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 new file mode 100644 index 0000000000..54b30c983b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,34 @@ +--- +name: Feature Request +about: Suggest an idea for this project + +--- + + + +**Is your feature request related to a problem? Please describe.** + + +**Describe the solution you'd like** + + +**Describe alternatives you've considered** + + +**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 new file mode 100644 index 0000000000..70a086d3d7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Support_help.md @@ -0,0 +1,27 @@ +--- +name: Support +about: I need help! + +--- + +# *STOP RIGHT THERE!* + +Issues are ***NOT*** for getting help, only for reporting bugs and feature requests. + +Search open and closed issues to see if your question already has an answer. However, **do not create a new issue.** + +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.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. + + +### 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/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..f65a30b178 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +## PR Checklist: +- [ ] I have tested this extensively and it does not break any existing behavior. +- [ ] I have added/updated examples and tests for any new behavior. +- [ ] If this is a significant change, an issue has already been created where the problem / solution was discussed: [N/A, or add link to issue here] + + + +## PR Description + + + + + 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/CONTRIBUTING.md b/CONTRIBUTING.md index 2e4d5b866c..98cf0ab89b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,49 +1,66 @@ +> ### Notice +> *Before you continue, this is the* **ANDROID** *library. If you have an* **iOS** *device, please go here instead*: +> +> – https://github.com/danielgindi/Charts +> +> They might tell you to come back here, if they do, listen to them and ignore this notice. + # How to contribute -Bug-fixes and features often come from users of the MPAndroidChart library and improve it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we -need contributors to follow so that we can have a chance of keeping on -top of things. +Bug-fixes and features often come from users of the MPAndroidChart library and improve it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. + +## Creating Issues + +There are two main issue templates, one for bugs and another for feature requests. Please use them! You're issue will be much easier to understand, and bugs easier to fix, if you follow the templates. If your issue doesn't fit into those, just use the generic template. -## Simple issues and bug reports +Search existing [issues] to see if your bug has already been reported or if a feature request already exists. Don't forget to remove `is:open` so you see all the issues! If you find that one already exists, use reactions to show how much you care! -If you are reporting a bug which can be observed visually, please add to your issue either: +## Making Pull Requests -* Screenshots, if the bug is easily explainable -* A working sample project that we can compile, run, and immediately observe the issue +Careful! If you fail to follow these guidlines, you're pull request may be closed, *even if it's really awesome*. -## Getting Started with Contributions + 0. **Search** open [pull requests] AND existing [issues] to make sure what you want to do isn't already being worked on or already has an open pull request. + 1. **Fork** the repository + 1. **Create** a new branch based on `master`, and name it according to your changes + 1. **Add** your commits, they MUST follow the [Commit Style](#commit-style) below + 1. **Test** your changes by actually running the example app, or create a new example + 1. **Create** a pull request, following the auto-generated template + 1. ??? + 1. Profit :money_with_wings: + +You are encouraged to use [GitHub Desktop] to inspect your code changes before committing them. It can reveal small changes that might have gone unnoticed, and would be requested for removal before merging. -* Make sure you have a [GitHub account](https://github.com/signup/free) -* Submit a ticket for your issue, assuming one does not already exist. - * Clearly describe the issue including steps to reproduce when it is a bug. - * Make sure you fill in the earliest version (or commit number) that you know has the issue. -* Fork the repository on GitHub +Check out [#3975](https://github.com/PhilJay/MPAndroidChart/pull/3975) for an example of a good-made-better pull request. -## Making Changes +## Commit Style -* Create a topic branch from where you want to base your work. This is usually the master branch. -* Make commits of logical units. -* Make sure your code conforms to the code style around it. It's easy, just look around! -* If you have made changes back and forth, or have made merges, your commit history might look messy and hard to understand. A single issue or change should still be in one commit. So please squash those commits together and rebase them however you need to - to make our lives easier when reading it later. -* Check for unnecessary whitespace with `git diff --check` before committing. -* Make sure your commit messages are in the proper format. + * **Make commits of logical units** + Don't load your commits with tons of changes, this makes it hard to follow what is happening. However, if you have done a lot of work, and there are commits and merges all over the place, squash them down into fewer commits. + + * **Conform to the code style** + It's easy, just look around! + + * **Write good commit messages** + You may prefer [Tim Pope's style], you might like the [commitizen-friendly] way. Regardless of the color you pick, you MUST stay within the lines! + ``` +The commit title CANNOT exceed 50 characters -```` - First line must be up to 50 chars (Fixes #1234) +The body of the message comes after an empty new line, and describes the +changes more thoroughly. If the change is obvious and self-explanatory +from the title, you can omit the body. You should describe all changes +if many were made, or maybe some trickery that only code wizards can +understand. - The first line should be a short statement as to what have changed, and should also include an issue number, prefixed with a dash. - The body of the message comes after an empty new line, and describes the changes - more thoroughly, especially if there was a special case handled there, - or maybe some trickery that only code wizards can understand. -```` +Be polite and wrap your lines to 72 characters, but if you prefer going +to 100 characters then I guess we can't stop you. +``` -* Make sure you have tested your changes well. -* If your changes could theoretically affect some other component or case, which you do not necessarily use, you still have to test it. -* Create a Pull Request from your topic branch to the relevant branch in the main repo. If you go to the main repo of the framework, you'll see a big green button which pretty much prepares the PR for you. You just have to hit it. +## Final Notes -## Making Trivial Changes +Thanks for reading the contributing file! Have some cake! :cake: -For changes of a trivial nature to comments and documentation, it is not -always necessary to create a new ticket. In this case, it is -appropriate to start the first line of a commit with '(doc)' instead of -a ticket number. Even the default commit message the GitHub generates is fine with us. +[issues]: https://github.com/PhilJay/MPAndroidChart/issues +[pull requests]: https://github.com/PhilJay/MPAndroidChart/pulls +[GitHub Desktop]: https://desktop.github.com/ +[Tim Pope's style]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[commitizen-friendly]: https://github.com/commitizen/cz-cli 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 87d8b72402..0000000000 --- a/MPChartExample/AndroidManifest.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 164f11425a..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 '26.0.2' + 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.0.1' - //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.0.2' - //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 ba01acd794..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 = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = (BarChart) 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 b18309a26a..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 = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - - mChart = (LineChart) 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.EasingOption.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 19f7bae938..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 = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = (LineChart) 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 0763f7f88a..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 = (TextView) findViewById(R.id.tvValueCount); - mSeekBarValues = (SeekBar) findViewById(R.id.seekbarValues); - mTvCount.setText("500"); - - mSeekBarValues.setProgress(500); - - mSeekBarValues.setOnSeekBarChangeListener(this); - - mChart = (LineChart) 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 ff098c32e0..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 = (BarChart) 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/MyEasingFunction.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java deleted file mode 100644 index e874a57ab6..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java +++ /dev/null @@ -1,18 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample.custom; - -import com.github.mikephil.charting.animation.EasingFunction; - -/** - * Example of a custom made animation EasingFunction. - * - * @author Philipp Jahoda - */ -public class MyEasingFunction implements EasingFunction { - - @Override - public float getInterpolation(float input) { - // do awesome stuff here, this is just linear easing - return input; - } -} 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 8395ce2720..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 = (TextView) convertView.findViewById(R.id.tvName); - holder.tvDesc = (TextView) convertView.findViewById(R.id.tvDesc); - holder.tvNew = (TextView) 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 c87290050d..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 = (BarChart) 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.EasingOption.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 d0aa25b864..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 = (BubbleChart) 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.EasingOption.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 a388df3741..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 = (CandleStickChart) 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.EasingOption.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 5fcfa76bff..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 = (HorizontalBarChart) 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.EasingOption.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 55f7f6dd4c..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 = (LineChart) 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.EasingOption.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 2936379d55..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 = (PieChart) 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 411f4b6ac9..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 = (RadarChart) 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 14175ac73a..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 = (ScatterChart) 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.EasingOption.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 07c54ad88c..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 = (ListView) 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 6c1d7cde03..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 = (LineChart) findViewById(R.id.lineChart); - barChart = (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.EasingOption.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.EasingOption.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 50% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 5772359773..0d83e3444a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.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,12 +15,10 @@ 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.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -31,7 +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.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; @@ -39,12 +41,13 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; 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 @@ -54,35 +57,40 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("BarChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mChart = (BarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + + 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 - 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); @@ -90,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); @@ -115,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<>(); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + 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)); + } + } - // mChart.setDrawLegend(false); + 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); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(0.9f); + + chart.setData(data); + } } @Override @@ -146,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; } } @@ -217,86 +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); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + public void onStartTrackingTouch(SeekBar seekBar) {} - 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 671ab5abec..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); - tvX = (TextView) findViewById(R.id.tvXMax); + setTitle("BarChartActivityMultiDataset"); + + tvX = findViewById(R.id.tvXMax); tvX.setTextSize(10); - tvY = (TextView) findViewById(R.id.tvYMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setMax(50); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = (BarChart) 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 56add4458e..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"); - tvX = (TextView) findViewById(R.id.tvValueCount); + data = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); - mSeekBarX = (SeekBar) findViewById(R.id.seekbarValues); + tvX = findViewById(R.id.tvValueCount); - mChart = (BarChart) findViewById(R.id.chart1); + seekBarX = findViewById(R.id.seekbarValues); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(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 - 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 743b7e735d..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 = (BarChart) 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 51% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 0ecc1e9c93..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("BubbleChartActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = (BubbleChart) 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 56% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index bd8dde108f..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("CandleStickChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mChart = (CandleStickChart) findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); + + 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 fadfbf175f..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 = (CombinedChart) 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 58% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index cb979e80e9..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("CubicLineChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - - mChart = (LineChart) 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); + + chart.setDrawGridBackground(false); + chart.setMaxHighlightDistance(300); - mChart.setDrawGridBackground(false); - mChart.setMaxHighlightDistance(300); - - XAxis x = mChart.getXAxis(); + 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; + public void onStartTrackingTouch(SeekBar seekBar) {} - 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; - } - }); - - // 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 970ba12909..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 = (LineChart) 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 2875b89d7e..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 = (LineChart) 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 d824167d6b..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 = (LineChart) 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 15da39a8f3..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 = (PieChart) 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.EasingOption.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 54% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index d68b75cc15..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("HorizontalBarChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mChart = (HorizontalBarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - // mChart.setHighlightEnabled(false); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart.setDrawBarShadow(false); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart.setDrawValueAboveBar(true); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); - mChart.getDescription().setEnabled(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 - 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 61% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index f87a9a8098..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("InvertedLineChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); - mChart = (LineChart) 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 79f40c4e07..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + setTitle("LineChartActivity2"); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(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 61% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 68bba4b458..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,38 +31,40 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_colored_lines); - mCharts[0] = (LineChart) findViewById(R.id.chart1); - mCharts[1] = (LineChart) findViewById(R.id.chart2); - mCharts[2] = (LineChart) findViewById(R.id.chart3); - mCharts[3] = (LineChart) 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) }; private void setupChart(LineChart chart, LineData data, int color) { - ((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color); + ((LineDataSet) data.getDataSetByIndex(0)).setCircleHoleColor(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 30e5e2a978..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 = (TextView) findViewById(R.id.tvXMax); - mSeekBarX = (SeekBar) 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 = (LineChart) 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 66% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 7ee212ff60..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); - - ListView lv = (ListView) findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + setTitle("ListViewBarChartActivity"); + + ListView lv = findViewById(R.id.listView1); + + 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) { @@ -73,7 +82,7 @@ public View getView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.from(getContext()).inflate( R.layout.list_item_barchart, null); - holder.chart = (BarChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); @@ -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 64% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 0e273596fe..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); - - ListView lv = (ListView) findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + setTitle("ListViewMultiChartActivity"); + + ListView lv = findViewById(R.id.listView1); + + 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 085580a923..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("PieChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarX.setProgress(4); - mSeekBarY.setProgress(10); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mChart = (PieChart) findViewById(R.id.chart1); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); - mChart.setExtraOffsets(5, 10, 5, 5); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart.setDragDecelerationFrictionCoef(0.95f); + seekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); - mChart.setCenterTextTypeface(mTfLight); - mChart.setCenterText(generateCenterSpannableText()); + chart = findViewById(R.id.chart1); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); + chart.setExtraOffsets(5, 10, 5, 5); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDragDecelerationFrictionCoef(0.95f); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setCenterTextTypeface(tfLight); + chart.setCenterText(generateCenterSpannableText()); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setDrawCenterText(true); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setRotationAngle(0); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); + + chart.setDrawCenterText(true); + + 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.EasingOption.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,66 +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.EasingOption - .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; } } @@ -190,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() { @@ -283,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 49fc4959e9..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; @@ -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; @@ -36,10 +40,10 @@ 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; @Override @@ -49,59 +53,60 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("PiePolylineChartActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - 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 = (PieChart) 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.EasingOption.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); @@ -109,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"); @@ -200,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); @@ -226,6 +156,7 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); + //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); @@ -234,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() { @@ -270,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/RadarChartActivitry.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java similarity index 62% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index 937973fe4e..883eb7dfc1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,19 +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.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; 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.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -28,54 +30,48 @@ import java.util.ArrayList; -public class RadarChartActivitry extends DemoBase { +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 = (TextView) findViewById(R.id.textView); - tv.setTypeface(mTfLight); - tv.setTextColor(Color.WHITE); - tv.setBackgroundColor(Color.rgb(60, 65, 82)); + setTitle("RadarChartActivity"); - mChart = (RadarChart) 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.EasingOption.EaseInOutQuad, - Easing.EasingOption.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) { @@ -84,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); @@ -113,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) { @@ -146,110 +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.EasingOption - .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 13346bf631..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 = (LineChart) 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 51% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 29904a95c9..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("ScatterChartActivity"); + + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = (ScatterChart) 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 70afd7c4c6..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); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + setTitle("StackedBarActivity"); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mChart = (BarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + + 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 d5e0f8c885..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 = (HorizontalBarChart) 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 74% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 8d97346195..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,20 +15,21 @@ /** * 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); - tvContent = (TextView) findViewById(R.id.tvContent); + 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 72% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 1a350f45ac..ca057a5aa3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -1,42 +1,42 @@ 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); - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); 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 73% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index d0781b2ee2..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; @@ -24,10 +27,10 @@ public class StackedBarsMarkerView extends MarkerView { public StackedBarsMarkerView(Context context, int layoutResource) { super(context, layoutResource); - tvContent = (TextView) findViewById(R.id.tvContent); + 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 70% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 177527b3bf..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,27 +19,28 @@ * * @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); this.xAxisValueFormatter = xAxisValueFormatter; - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); 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 66% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 1cdba2735f..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 - FrameLayout parent = (FrameLayout) v.findViewById(R.id.parentLayout); - parent.addView(mChart); - + + // programmatically add the chart + FrameLayout parent = v.findViewById(R.id.parentLayout); + 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 caf9e3e295..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 = (LineChart) 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 7888aa632f..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 = (PieChart) 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 90aba051d3..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 = (ScatterChart) 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 63% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java index 7af599e927..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); - ViewPager pager = (ViewPager) findViewById(R.id.pager); + 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 60173c368f..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 = (LineChart) 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 92% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index cf9b4b553d..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) { @@ -39,7 +41,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_barchart, null); - holder.chart = (BarChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); @@ -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 92% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index f988844fce..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) { @@ -40,7 +42,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_linechart, null); - holder.chart = (LineChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); @@ -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 93% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index db6ba32416..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) { @@ -47,7 +48,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_piechart, null); - holder.chart = (PieChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); 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 53% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 7490c3c933..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; @@ -39,18 +39,19 @@ import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.PiePolylineChartActivity; import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; +import com.xxmassdeveloper.mpchartexample.RadarChartActivity; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; 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,92 +65,68 @@ 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); - ListView lv = (ListView) findViewById(R.id.listView1); + ListView lv = findViewById(R.id.listView1); lv.setAdapter(adapter); lv.setOnItemClickListener(this); @@ -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, RadarChartActivitry.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 8e19df7541..0fb6dc7036 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,17 +1,16 @@ apply plugin: 'com.android.library' -apply plugin: 'maven' -//apply plugin: 'com.github.dcendents.android-maven' -//apply plugin: 'realm-android' +apply plugin: 'com.github.dcendents.android-maven' + +group='com.github.philjay' android { - compileSdkVersion 27 - buildToolsVersion '26.0.2' - // resourcePrefix 'mpcht' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { - minSdkVersion 9 - targetSdkVersion 27 + minSdkVersion 14 + targetSdkVersion 28 versionCode 3 - versionName '3.0.3' + versionName '3.1.0' } buildTypes { release { @@ -19,34 +18,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 { - //compile fileTree(dir: 'libs', include: ['*.jar']) - //compile 'com.android.support:support-v4:19.+' - //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API - testCompile 'junit:junit:4.12' - testCompile "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.javaCompile - task.from variant.javaCompile.destinationDir - artifacts.add('archives', task); + implementation 'androidx.annotation:annotation:1.0.0' + testImplementation 'junit:junit:4.12' } 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 639442a4c9..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,310 +1,207 @@ - package com.github.mikephil.charting.animation; import android.animation.ObjectAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.annotation.SuppressLint; +import androidx.annotation.RequiresApi; + +import com.github.mikephil.charting.animation.Easing.EasingFunction; /** - * Object responsible for all animations in the Chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * + * Object responsible for all animations in the Chart. Animations require API level 11. + * * @author Philipp Jahoda + * @author Mick Ashton */ public class ChartAnimator { /** object that is updated upon animation update */ private AnimatorUpdateListener mListener; - public ChartAnimator() { + /** The phase of drawn values on the y-axis. 0 - 1 */ + @SuppressWarnings("WeakerAccess") + protected float mPhaseY = 1f; + + /** The phase of drawn values on the x-axis. 0 - 1 */ + @SuppressWarnings("WeakerAccess") + protected float mPhaseX = 1f; - } + public ChartAnimator() { } + @RequiresApi(11) public ChartAnimator(AnimatorUpdateListener listener) { mListener = listener; } - /** - * ################ ################ ################ ################ - */ - /** CODE BELOW THIS RELATED TO ANIMATION */ - - /** the phase that is animated and influences the drawn values on the y-axis */ - protected float mPhaseY = 1f; - - /** the phase that is animated and influences the drawn values on the x-axis */ - protected float mPhaseX = 1f; + @RequiresApi(11) + private ObjectAnimator xAnimator(int duration, EasingFunction easing) { - /** - * ################ ################ ################ ################ - */ - /** METHODS FOR CUSTOM EASING */ + ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(easing); + animatorX.setDuration(duration); - /** - * 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 - * @param durationMillisY - * @param easingX - * @param easingY - */ - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, - EasingFunction easingY) { + return animatorX; + } - if (android.os.Build.VERSION.SDK_INT < 11) - return; + @RequiresApi(11) + private ObjectAnimator yAnimator(int duration, EasingFunction easing) { ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easingY); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easingX); - animatorX.setDuration( - durationMillisX); + animatorY.setInterpolator(easing); + animatorY.setDuration(duration); - // make sure only one animator produces update-callbacks (which then - // call invalidate()) - if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); - } else { - animatorY.addUpdateListener(mListener); - } + return animatorY; + } - animatorX.start(); - animatorY.start(); + /** + * Animates values along the X axis, in a linear fashion. + * + * @param durationMillis animation duration + */ + @RequiresApi(11) + public void animateX(int durationMillis) { + animateX(durationMillis, Easing.Linear); } /** - * 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. + * Animates values along the X axis. * - * @param durationMillis - * @param easing + * @param durationMillis animation duration + * @param easing EasingFunction */ + @RequiresApi(11) public void animateX(int durationMillis, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easing); - animatorX.setDuration(durationMillis); + ObjectAnimator animatorX = xAnimator(durationMillis, easing); 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. + * Animates values along both the X and Y axes, in a linear fashion. * - * @param durationMillis - * @param easing + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis */ - public void animateY(int durationMillis, EasingFunction easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easing); - animatorY.setDuration(durationMillis); - animatorY.addUpdateListener(mListener); - animatorY.start(); + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY) { + animateXY(durationMillisX, durationMillisY, Easing.Linear, Easing.Linear); } /** - * ################ ################ ################ ################ - */ - /** METHODS FOR PREDEFINED EASING */ - - /** - * 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. + * Animates values along both the X and Y axes. * - * @param durationMillisX - * @param durationMillisY - * @param easingX - * @param easingY + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easing EasingFunction for both axes */ - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; + ObjectAnimator xAnimator = xAnimator(durationMillisX, easing); + ObjectAnimator yAnimator = yAnimator(durationMillisY, easing); - 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); + xAnimator.addUpdateListener(mListener); } else { - animatorY.addUpdateListener(mListener); + yAnimator.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 - * @param easing - */ - 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(); + xAnimator.start(); + yAnimator.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. + * Animates values along both the X and Y axes. * - * @param durationMillis - * @param easing - */ - 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(); - } - - /** - * ################ ################ ################ ################ + * @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 */ - /** METHODS FOR ANIMATION WITHOUT EASING */ - - /** - * 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 - * @param durationMillisY - */ - public void animateXY(int durationMillisX, int durationMillisY) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, + EasingFunction easingY) { - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setDuration( - durationMillisX); + ObjectAnimator xAnimator = xAnimator(durationMillisX, easingX); + ObjectAnimator yAnimator = yAnimator(durationMillisY, easingY); - // make sure only one animator produces update-callbacks (which then - // call invalidate()) if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); + xAnimator.addUpdateListener(mListener); } else { - animatorY.addUpdateListener(mListener); + yAnimator.addUpdateListener(mListener); } - animatorX.start(); - animatorY.start(); + xAnimator.start(); + yAnimator.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. + * Animates values along the Y axis, in a linear fashion. * - * @param durationMillis + * @param durationMillis animation duration */ - public void animateX(int durationMillis) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setDuration(durationMillis); - animatorX.addUpdateListener(mListener); - animatorX.start(); + @RequiresApi(11) + public void animateY(int durationMillis) { + animateY(durationMillis, Easing.Linear); } /** - * 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. + * Animates values along the Y axis. * - * @param durationMillis + * @param durationMillis animation duration + * @param easing EasingFunction */ - public void animateY(int durationMillis) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; + @RequiresApi(11) + public void animateY(int durationMillis, EasingFunction easing) { - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setDuration(durationMillis); + ObjectAnimator animatorY = yAnimator(durationMillis, easing); animatorY.addUpdateListener(mListener); animatorY.start(); } /** - * This gets the y-phase that is used to animate the values. + * Gets the Y axis phase of the animation. * - * @return + * @return float value of {@link #mPhaseY} */ public float getPhaseY() { return mPhaseY; } /** - * This modifys the y-phase that is used to animate the values. + * Sets the Y axis phase of the animation. * - * @param phase + * @param phase float value between 0 - 1 */ public void setPhaseY(float phase) { + if (phase > 1f) { + phase = 1f; + } else if (phase < 0f) { + phase = 0f; + } mPhaseY = phase; } /** - * This gets the x-phase that is used to animate the values. + * Gets the X axis phase of the animation. * - * @return + * @return float value of {@link #mPhaseX} */ public float getPhaseX() { return mPhaseX; } /** - * This modifys the x-phase that is used to animate the values. + * Sets the X axis phase of the animation. * - * @param phase + * @param phase float value between 0 - 1 */ public void setPhaseX(float phase) { + if (phase > 1f) { + phase = 1f; + } else if (phase < 0f) { + phase = 0f; + } mPhaseX = phase; } } 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 1741f6f511..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,721 +1,309 @@ - package com.github.mikephil.charting.animation; +import android.animation.TimeInterpolator; +import androidx.annotation.RequiresApi; + /** * Easing options. - * + * * @author Daniel Cohen Gindi + * @author Mick Ashton */ +@SuppressWarnings("WeakerAccess") +@RequiresApi(11) public class Easing { - /** - * Use EasingOption instead of EasingFunction to avoid crashes below Android - * 3.0 - */ - 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, + public interface EasingFunction extends TimeInterpolator { + @Override + float getInterpolation(float input); } - public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { - switch (easing) { - default: - case Linear: - return Easing.EasingFunctions.Linear; - case EaseInQuad: - return Easing.EasingFunctions.EaseInQuad; - case EaseOutQuad: - return Easing.EasingFunctions.EaseOutQuad; - case EaseInOutQuad: - return Easing.EasingFunctions.EaseInOutQuad; - case EaseInCubic: - return Easing.EasingFunctions.EaseInCubic; - case EaseOutCubic: - return Easing.EasingFunctions.EaseOutCubic; - case EaseInOutCubic: - return Easing.EasingFunctions.EaseInOutCubic; - case EaseInQuart: - return Easing.EasingFunctions.EaseInQuart; - case EaseOutQuart: - return Easing.EasingFunctions.EaseOutQuart; - case EaseInOutQuart: - return Easing.EasingFunctions.EaseInOutQuart; - case EaseInSine: - return Easing.EasingFunctions.EaseInSine; - case EaseOutSine: - return Easing.EasingFunctions.EaseOutSine; - case EaseInOutSine: - return Easing.EasingFunctions.EaseInOutSine; - case EaseInExpo: - return Easing.EasingFunctions.EaseInExpo; - case EaseOutExpo: - return Easing.EasingFunctions.EaseOutExpo; - case EaseInOutExpo: - return Easing.EasingFunctions.EaseInOutExpo; - case EaseInCirc: - return Easing.EasingFunctions.EaseInCirc; - case EaseOutCirc: - return Easing.EasingFunctions.EaseOutCirc; - case EaseInOutCirc: - return Easing.EasingFunctions.EaseInOutCirc; - case EaseInElastic: - return Easing.EasingFunctions.EaseInElastic; - case EaseOutElastic: - return Easing.EasingFunctions.EaseOutElastic; - case EaseInOutElastic: - return Easing.EasingFunctions.EaseInOutElastic; - case EaseInBack: - return Easing.EasingFunctions.EaseInBack; - case EaseOutBack: - return Easing.EasingFunctions.EaseOutBack; - case EaseInOutBack: - return Easing.EasingFunctions.EaseInOutBack; - case EaseInBounce: - return Easing.EasingFunctions.EaseInBounce; - case EaseOutBounce: - return Easing.EasingFunctions.EaseOutBounce; - case EaseInOutBounce: - return Easing.EasingFunctions.EaseInOutBounce; + private static final float DOUBLE_PI = 2f * (float) Math.PI; + + @SuppressWarnings("unused") + public static final EasingFunction Linear = new EasingFunction() { + public float getInterpolation(float input) { + return input; } - } - - private static class EasingFunctions { - - /** - * ########## ########## ########## ########## ########## ########## - * PREDEFINED EASING FUNCTIONS BELOW THIS - */ - - public static final EasingFunction Linear = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return elapsed / (float) duration; - // } - - @Override - public float getInterpolation(float input) { - return input; + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInQuad = new EasingFunction() { + public float getInterpolation(float input) { + return input * input; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutQuad = new EasingFunction() { + public float getInterpolation(float input) { + return -input * (input - 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutQuad = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + + if (input < 1f) { + return 0.5f * input * input; } - }; - - public static final EasingFunction EaseInQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input; + + return -0.5f * ((--input) * (input - 2f) - 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInCubic = new EasingFunction() { + public float getInterpolation(float input) { + return (float) Math.pow(input, 3); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutCubic = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return (float) Math.pow(input, 3) + 1f; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutCubic = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(input, 3); } - }; - - public static final EasingFunction EaseOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -position * (position - 2.f); - // } - - @Override - public float getInterpolation(float input) { - return -input * (input - 2f); + input -= 2f; + return 0.5f * ((float) Math.pow(input, 3) + 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInQuart = new EasingFunction() { + + public float getInterpolation(float input) { + return (float) Math.pow(input, 4); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutQuart = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return -((float) Math.pow(input, 4) - 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutQuart = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(input, 4); } - }; + input -= 2f; + return -0.5f * ((float) Math.pow(input, 4) - 2f); + } + }; - public static final EasingFunction EaseInOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position; - // } - // return -0.5f * ((--position) * (position - 2.f) - 1.f); - // } + @SuppressWarnings("unused") + public static final EasingFunction EaseInSine = new EasingFunction() { + public float getInterpolation(float input) { + return -(float) Math.cos(input * (Math.PI / 2f)) + 1f; + } + }; - @Override - public float getInterpolation(float input) { + @SuppressWarnings("unused") + public static final EasingFunction EaseOutSine = new EasingFunction() { + public float getInterpolation(float input) { + return (float) Math.sin(input * (Math.PI / 2f)); + } + }; - float position = input / 0.5f; + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutSine = new EasingFunction() { + public float getInterpolation(float input) { + return -0.5f * ((float) Math.cos(Math.PI * input) - 1f); + } + }; - if (position < 1.f) { - return 0.5f * position * position; - } + @SuppressWarnings("unused") + public static final EasingFunction EaseInExpo = new EasingFunction() { + public float getInterpolation(float input) { + return (input == 0) ? 0f : (float) Math.pow(2f, 10f * (input - 1f)); + } + }; - return -0.5f * ((--position) * (position - 2.f) - 1.f); - } - }; - - public static final EasingFunction EaseInCubic = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input * input; + @SuppressWarnings("unused") + public static final EasingFunction EaseOutExpo = new EasingFunction() { + public float getInterpolation(float input) { + return (input == 1f) ? 1f : (-(float) Math.pow(2f, -10f * (input + 1f))); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutExpo = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1f) { + return 1f; } - }; - - public static final EasingFunction EaseOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (position * position * position + 1.f); - // } - - @Override - public float getInterpolation(float input) { - input--; - return (input * input * input + 1.f); - } - }; - - public static final EasingFunction EaseInOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position * position; - // } - // position -= 2.f; - // return 0.5f * (position * position * position + 2.f); - // } - - @Override - public float getInterpolation(float input) { - - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position; - } - position -= 2.f; - return 0.5f * (position * position * position + 2.f); - } - }; - - public static final EasingFunction EaseInQuart = new EasingFunction() { - - public float getInterpolation(float input) { - return input * input * input * input; + + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(2f, 10f * (input - 1f)); } - }; + return 0.5f * (-(float) Math.pow(2f, -10f * --input) + 2f); + } + }; - public static final EasingFunction EaseOutQuart = new EasingFunction() { + @SuppressWarnings("unused") + public static final EasingFunction EaseInCirc = new EasingFunction() { + public float getInterpolation(float input) { + return -((float) Math.sqrt(1f - input * input) - 1f); + } + }; - public float getInterpolation(float input) { - input--; - return -(input * input * input * input - 1f); - } - }; - - public static final EasingFunction EaseInOutQuart = new - EasingFunction() { - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position * position; - } - position -= 2.f; - return -0.5f * (position * position * position * position - 2.f); - } - }; - - public static final EasingFunction EaseInSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; - // } - @Override - public float getInterpolation(float input) { - return -(float) Math.cos(input * (Math.PI / 2.f)) + 1.f; + @SuppressWarnings("unused") + public static final EasingFunction EaseOutCirc = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return (float) Math.sqrt(1f - input * input); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutCirc = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return -0.5f * ((float) Math.sqrt(1f - input * input) - 1f); } - }; - - public static final EasingFunction EaseOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return (float) Math.sin(position * (Math.PI / 2.f)); - // } - @Override - public float getInterpolation(float input) { - return (float) Math.sin(input * (Math.PI / 2.f)); + return 0.5f * ((float) Math.sqrt(1f - (input -= 2f) * input) + 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1) { + return 1f; } - }; - - public static final EasingFunction EaseInOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -0.5f * ((float) Math.cos(Math.PI * input) - 1.f); + + float p = 0.3f; + float s = p / DOUBLE_PI * (float) Math.asin(1f); + return -((float) Math.pow(2f, 10f * (input -= 1f)) + *(float) Math.sin((input - s) * DOUBLE_PI / p)); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1) { + return 1f; } - }; - - public static final EasingFunction EaseInExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed - // / (float) duration - 1.f)); - // } - @Override - public float getInterpolation(float input) { - return (input == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (input - 1.f)); + + float p = 0.3f; + float s = p / DOUBLE_PI * (float) Math.asin(1f); + return 1f + + (float) Math.pow(2f, -10f * input) + * (float) Math.sin((input - s) * DOUBLE_PI / p); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; } - }; - - public static final EasingFunction EaseOutExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * - // elapsed - // / (float) duration) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - return (input == 1f) ? 1.f : (-(float) Math.pow(2.f, -10.f * (input + 1.f))); + + input *= 2f; + if (input == 2) { + return 1f; } - }; - - public static final EasingFunction EaseInOutExpo = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // if (elapsed == duration) - // { - // return 1.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - // } - // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + - // 2.f); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - if (input == 1f) - { - return 1.f; - } - - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - } - return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); - } - }; - - public static final EasingFunction EaseInCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -((float) Math.sqrt(1.f - position * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -((float) Math.sqrt(1.f - input * input) - 1.f); + + float p = 1f / 0.45f; + float s = 0.45f / DOUBLE_PI * (float) Math.asin(1f); + if (input < 1f) { + return -0.5f + * ((float) Math.pow(2f, 10f * (input -= 1f)) + * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p)); } - }; - - public static final EasingFunction EaseOutCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (float) Math.sqrt(1.f - position * position); - // } - @Override - public float getInterpolation(float input) { - input--; - return (float) Math.sqrt(1.f - input * input); + return 1f + 0.5f + * (float) Math.pow(2f, -10f * (input -= 1f)) + * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInBack = new EasingFunction() { + public float getInterpolation(float input) { + final float s = 1.70158f; + return input * input * ((s + 1f) * input - s); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutBack = new EasingFunction() { + public float getInterpolation(float input) { + final float s = 1.70158f; + input--; + return (input * input * ((s + 1f) * input + s) + 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutBack = new EasingFunction() { + public float getInterpolation(float input) { + float s = 1.70158f; + input *= 2f; + if (input < 1f) { + return 0.5f * (input * input * (((s *= (1.525f)) + 1f) * input - s)); } - }; - - public static final EasingFunction EaseInOutCirc = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return -0.5f * ((float) Math.sqrt(1.f - position * position) - // - 1.f); - // } - // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * - // position) - // + 1.f); - // } - - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) - { - return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); - } - return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) - + 1.f); - } - }; - - public static final EasingFunction EaseInElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * - // (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - Math - .sin((position - s) * (2.f * Math.PI) / p)); - } - }; - - public static final EasingFunction EaseOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - // return (float) Math.pow(2, -10 * position) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) + - // 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - return (float) Math.pow(2, -10 * position) - * (float) Math.sin((position - s) * (2.f * Math.PI) / p) + - 1.f; - } - }; - - public static final EasingFunction EaseInOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position == 2) - // { - // return 1.f; - // } - // - // float p = duration * (.3f * 1.5f); - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // if (position < 1.f) - // { - // return -.5f - // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) * - // .5f - // + 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input / 0.5f; - if (position == 2) - { - return 1.f; - } - - float p = (.3f * 1.5f); - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - if (position < 1.f) - { - return -.5f - * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math - .sin((position * 1f - s) * (2.f * Math.PI) / p)); - } - return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - * (float) Math.sin((position * 1f - s) * (2.f * Math.PI) / p) * - .5f - + 1.f; - } - }; - - public static final EasingFunction EaseInBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // return position * position * ((s + 1.f) * position - s); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - return position * position * ((s + 1.f) * position - s); + return 0.5f * ((input -= 2f) * input * (((s *= (1.525f)) + 1f) * input + s) + 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInBounce = new EasingFunction() { + public float getInterpolation(float input) { + return 1f - EaseOutBounce.getInterpolation(1f - input); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutBounce = new EasingFunction() { + public float getInterpolation(float input) { + float s = 7.5625f; + if (input < (1f / 2.75f)) { + return s * input * input; + } else if (input < (2f / 2.75f)) { + return s * (input -= (1.5f / 2.75f)) * input + 0.75f; + } else if (input < (2.5f / 2.75f)) { + return s * (input -= (2.25f / 2.75f)) * input + 0.9375f; } - }; - - public static final EasingFunction EaseOutBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // position--; - // return (position * position * ((s + 1.f) * position + s) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - position--; - return (position * position * ((s + 1.f) * position + s) + 1.f); + return s * (input -= (2.625f / 2.75f)) * input + 0.984375f; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutBounce = new EasingFunction() { + public float getInterpolation(float input) { + if (input < 0.5f) { + return EaseInBounce.getInterpolation(input * 2f) * 0.5f; } - }; - - public static final EasingFunction EaseInOutBack = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float s = 1.70158f; - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) - // * - // position - s)); - // } - // return 0.5f * ((position -= 2.f) * position - // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - // } - - @Override - public float getInterpolation(float input) { - float s = 1.70158f; - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * - position - s)); - } - return 0.5f * ((position -= 2.f) * position - * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - } - }; - - public static final EasingFunction EaseInBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return 1.f - EaseOutBounce.ease(duration - elapsed, - // duration); - // } - - @Override - public float getInterpolation(float input) { - return 1.f - EaseOutBounce.getInterpolation(1f - input); - } - }; - - public static final EasingFunction EaseOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // if (position < (1.f / 2.75f)) - // { - // return (7.5625f * position * position); - // } - // else if (position < (2.f / 2.75f)) - // { - // return (7.5625f * (position -= (1.5f / 2.75f)) * position + - // .75f); - // } - // else if (position < (2.5f / 2.75f)) - // { - // return (7.5625f * (position -= (2.25f / 2.75f)) * position + - // .9375f); - // } - // else - // { - // return (7.5625f * (position -= (2.625f / 2.75f)) * position + - // .984375f); - // } - // } - - @Override - public float getInterpolation(float input) { - float position = input; - if (position < (1.f / 2.75f)) - { - return (7.5625f * position * position); - } - else if (position < (2.f / 2.75f)) - { - return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); - } - else if (position < (2.5f / 2.75f)) - { - return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); - } - else - { - return (7.5625f * (position -= (2.625f / 2.75f)) * position + - .984375f); - } - } - }; - - public static final EasingFunction EaseInOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed < duration / 2.f) - // { - // return EaseInBounce.ease(elapsed * 2, duration) * .5f; - // } - // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * - // .5f + - // .5f; - // } - - @Override - public float getInterpolation(float input) { - if (input < 0.5f) - { - return EaseInBounce.getInterpolation(input * 2) * .5f; - } - return EaseOutBounce.getInterpolation(input * 2 - 1f) * .5f + - .5f; - } - }; + return EaseOutBounce.getInterpolation(input * 2f - 1f) * 0.5f + 0.5f; + } + }; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java deleted file mode 100644 index 98d934da23..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.mikephil.charting.animation; - -import android.animation.TimeInterpolator; -import android.annotation.SuppressLint; - -/** - * Interface for creating custom made easing functions. Uses the - * TimeInterpolator interface provided by Android. - */ -@SuppressLint("NewApi") -public interface EasingFunction extends TimeInterpolator { - - @Override - float getInterpolation(float input); -} 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 bf4c42e241..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(); @@ -866,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); } /** @@ -933,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); } /** @@ -1224,7 +1225,7 @@ public boolean isDrawBordersEnabled() { /** * When enabled, the values will be clipped to contentRect, - * otherwise they can bleed outside the content rect. + * otherwise they can bleed outside the content rect. * * @param enabled */ @@ -1232,9 +1233,20 @@ 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. + * otherwise they can bleed outside the content rect. * * @return */ @@ -1242,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 ea26f2cfca..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 @@ -3,7 +3,6 @@ import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.graphics.Bitmap; @@ -15,8 +14,10 @@ import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Environment; import android.provider.MediaStore.Images; +import androidx.annotation.RequiresApi; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -26,7 +27,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing.EasingFunction; import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.IMarker; import com.github.mikephil.charting.components.Legend; @@ -60,7 +61,6 @@ * * @author Philipp Jahoda */ -@SuppressLint("NewApi") public abstract class Chart>> extends ViewGroup implements ChartInterface { @@ -209,17 +209,14 @@ protected void init() { setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_HARDWARE, null); - if (android.os.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()); @@ -402,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; @@ -552,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. @@ -560,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); } /** @@ -572,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); } /** @@ -583,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); } /** @@ -592,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. @@ -836,43 +898,12 @@ public void setDragDecelerationFrictionCoef(float newValue) { * @param easingX a custom easing function to be used on the animation phase * @param easingY a custom easing function to be used on the animation phase */ + @RequiresApi(11) public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, EasingFunction 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 custom easing function to be used on the animation phase - */ - public void animateX(int durationMillis, EasingFunction 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 custom easing function to be used on the animation phase - */ - public void animateY(int durationMillis, EasingFunction easing) { - mAnimator.animateY(durationMillis, easing); - } - - /** - * ################ ################ ################ ################ - * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. - */ - /** 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 @@ -881,12 +912,11 @@ public void animateY(int durationMillis, EasingFunction easing) { * * @param durationMillisX * @param durationMillisY - * @param easingX a predefined easing option - * @param easingY a predefined easing option + * @param easing a custom easing function to be used on the animation phase */ - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { - mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easing) { + mAnimator.animateXY(durationMillisX, durationMillisY, easing); } /** @@ -896,9 +926,10 @@ public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOpt * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @param durationMillis - * @param easing a predefined easing option + * @param easing a custom easing function to be used on the animation phase */ - public void animateX(int durationMillis, Easing.EasingOption easing) { + @RequiresApi(11) + public void animateX(int durationMillis, EasingFunction easing) { mAnimator.animateX(durationMillis, easing); } @@ -909,12 +940,19 @@ public void animateX(int durationMillis, Easing.EasingOption easing) { * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @param durationMillis - * @param easing a predefined easing option + * @param easing a custom easing function to be used on the animation phase */ - public void animateY(int durationMillis, Easing.EasingOption easing) { + @RequiresApi(11) + public void animateY(int durationMillis, EasingFunction easing) { mAnimator.animateY(durationMillis, easing); } + /** + * ################ ################ ################ ################ + * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + */ + /** CODE BELOW FOR PREDEFINED EASING OPTIONS */ + /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. @@ -929,6 +967,7 @@ public void animateY(int durationMillis, Easing.EasingOption easing) { * * @param durationMillis */ + @RequiresApi(11) public void animateX(int durationMillis) { mAnimator.animateX(durationMillis); } @@ -941,6 +980,7 @@ public void animateX(int durationMillis) { * * @param durationMillis */ + @RequiresApi(11) public void animateY(int durationMillis) { mAnimator.animateY(durationMillis); } @@ -954,6 +994,7 @@ public void animateY(int durationMillis) { * @param durationMillisX * @param durationMillisY */ + @RequiresApi(11) public void animateXY(int durationMillisX, int durationMillisY) { mAnimator.animateXY(durationMillisX, durationMillisY); } @@ -1187,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 @@ -1493,6 +1543,8 @@ public Bitmap getChartBitmap() { */ public boolean saveToPath(String title, String pathOnSD) { + + Bitmap b = getChartBitmap(); OutputStream stream = null; @@ -1608,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); } /** @@ -1705,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 d403a752cc..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 @@ -12,6 +12,7 @@ import android.view.MotionEvent; import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.animation.Easing.EasingFunction; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; @@ -477,17 +478,14 @@ public float getYChartMin() { * @param toangle */ @SuppressLint("NewApi") - public void spin(int durationmillis, float fromangle, float toangle, Easing.EasingOption easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; + public void spin(int durationmillis, float fromangle, float toangle, EasingFunction easing) { setRotationAngle(fromangle); ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); spinAnimator.setDuration(durationmillis); - spinAnimator.setInterpolator(Easing.getEasingFunctionFromOption(easing)); + spinAnimator.setInterpolator(easing); spinAnimator.addUpdateListener(new AnimatorUpdateListener() { 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 40835f7347..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 @@ -112,6 +112,11 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mDrawLimitLineBehindData = false; + /** + * flag indicating the grid lines layer depth + */ + protected boolean mDrawGridLinesBehindData = true; + /** * Extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` */ @@ -147,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 */ @@ -310,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; @@ -444,6 +482,18 @@ public boolean isDrawLimitLinesBehindDataEnabled() { return mDrawLimitLineBehindData; } + /** + * If this is set to false, the grid lines are draw on top of the actual data, + * otherwise behind. Default: true + * + * @param enabled + */ + public void setDrawGridLinesBehindData(boolean enabled) { mDrawGridLinesBehindData = enabled; } + + public boolean isDrawGridLinesBehindDataEnabled() { + return mDrawGridLinesBehindData; + } + /** * Returns the longest formatted label (in terms of characters), this axis * contains. 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 e84caab76b..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 @@ -38,6 +38,16 @@ public class YAxis extends AxisBase { */ protected boolean mDrawZeroLine = false; + /** + * flag indicating that auto scale min restriction should be used + */ + private boolean mUseAutoScaleRestrictionMin = false; + + /** + * flag indicating that auto scale max restriction should be used + */ + private boolean mUseAutoScaleRestrictionMax = false; + /** * Color of the zero line */ @@ -63,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 */ @@ -164,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 * @@ -357,14 +388,65 @@ public boolean needsOffset() { return false; } + /** + * Returns true if autoscale restriction for axis min value is enabled + */ + @Deprecated + public boolean isUseAutoScaleMinRestriction( ) { + return mUseAutoScaleRestrictionMin; + } + + /** + * Sets autoscale restriction for axis min value as enabled/disabled + */ + @Deprecated + public void setUseAutoScaleMinRestriction( boolean isEnabled ) { + mUseAutoScaleRestrictionMin = isEnabled; + } + + /** + * Returns true if autoscale restriction for axis max value is enabled + */ + @Deprecated + public boolean isUseAutoScaleMaxRestriction() { + return mUseAutoScaleRestrictionMax; + } + + /** + * Sets autoscale restriction for axis max value as enabled/disabled + */ + @Deprecated + public void setUseAutoScaleMaxRestriction( boolean isEnabled ) { + mUseAutoScaleRestrictionMax = isEnabled; + } + + @Override public void calculate(float dataMin, float dataMax) { - // if custom, use value as is, else use data value - float min = mCustomAxisMin ? mAxisMinimum : dataMin; - float max = mCustomAxisMax ? mAxisMaximum : dataMax; + float min = dataMin; + float max = dataMax; + + // 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; + } + 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 @@ -373,21 +455,13 @@ public void calculate(float dataMin, float dataMax) { min = min - 1f; } - // bottom-space only effects non-custom min - if (!mCustomAxisMin) { - - float bottomSpace = range / 100f * getSpaceBottom(); - this.mAxisMinimum = (min - bottomSpace); - } + // recalculate + range = Math.abs(max - min); - // top-space only effects non-custom max - if (!mCustomAxisMax) { - - float topSpace = range / 100f * getSpaceTop(); - this.mAxisMaximum = (max + topSpace); - } + // 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 ae11c97b3c..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); @@ -53,23 +54,83 @@ public BarDataSet(List yVals, String label) { @Override public DataSet copy() { + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); + } + BarDataSet copied = new BarDataSet(entries, getLabel()); + copy(copied); + return copied; + } - List yVals = new ArrayList(); - yVals.clear(); + protected void copy(BarDataSet barDataSet) { + super.copy(barDataSet); + barDataSet.mStackSize = mStackSize; + barDataSet.mBarShadowColor = mBarShadowColor; + barDataSet.mBarBorderWidth = mBarBorderWidth; + barDataSet.mStackLabels = mStackLabels; + barDataSet.mHighLightAlpha = mHighLightAlpha; + } - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); - } + @Override + public List getFills() { + return mFills; + } - BarDataSet copied = new BarDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mStackSize = mStackSize; - copied.mBarShadowColor = mBarShadowColor; - copied.mStackLabels = mStackLabels; - copied.mHighLightColor = mHighLightColor; - copied.mHighLightAlpha = mHighLightAlpha; + @Override + public Fill getFill(int index) { + return mFills.get(index % mFills.size()); + } - return copied; + /** + * 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; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index fba8216c3d..eab6dccc55 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -9,12 +9,16 @@ /** * Baseclass of all DataSets for Bar-, Line-, Scatter- and CandleStickChart. - * + * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleBubbleDataSet extends DataSet implements IBarLineScatterCandleBubbleDataSet { +public abstract class BarLineScatterCandleBubbleDataSet + extends DataSet + implements IBarLineScatterCandleBubbleDataSet { - /** default highlight color */ + /** + * default highlight color + */ protected int mHighLightColor = Color.rgb(255, 187, 115); public BarLineScatterCandleBubbleDataSet(List yVals, String label) { @@ -25,7 +29,7 @@ public BarLineScatterCandleBubbleDataSet(List yVals, String label) { * Sets the color that is used for drawing the highlight indicators. Dont * forget to resolve the color using getResources().getColor(...) or * Color.rgb(...). - * + * * @param color */ public void setHighLightColor(int color) { @@ -36,4 +40,9 @@ public void setHighLightColor(int color) { public int getHighLightColor() { return mHighLightColor; } + + protected void copy(BarLineScatterCandleBubbleDataSet barLineScatterCandleBubbleDataSet) { + super.copy(barLineScatterCandleBubbleDataSet); + barLineScatterCandleBubbleDataSet.mHighLightColor = mHighLightColor; + } } 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 3869a00895..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 @@ -7,15 +7,12 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; -import java.lang.annotation.Documented; -import java.lang.annotation.Inherited; import java.util.ArrayList; import java.util.List; @@ -186,7 +183,7 @@ public void setColors(int... colors) { */ public void setColors(int[] colors, Context c) { - if(mColors == null){ + if (mColors == null) { mColors = new ArrayList<>(); } @@ -246,7 +243,7 @@ public void setColors(int[] colors, int alpha) { * Resets all colors of this DataSet and recreates the colors array. */ public void resetColors() { - if(mColors == null) { + if (mColors == null) { mColors = new ArrayList(); } mColors.clear(); @@ -488,4 +485,22 @@ public boolean contains(T e) { return false; } + + protected void copy(BaseDataSet baseDataSet) { + baseDataSet.mAxisDependency = mAxisDependency; + baseDataSet.mColors = mColors; + baseDataSet.mDrawIcons = mDrawIcons; + baseDataSet.mDrawValues = mDrawValues; + baseDataSet.mForm = mForm; + baseDataSet.mFormLineDashEffect = mFormLineDashEffect; + baseDataSet.mFormLineWidth = mFormLineWidth; + baseDataSet.mFormSize = mFormSize; + baseDataSet.mHighlightEnabled = mHighlightEnabled; + baseDataSet.mIconsOffset = mIconsOffset; + baseDataSet.mValueColors = mValueColors; + baseDataSet.mValueFormatter = mValueFormatter; + baseDataSet.mValueColors = mValueColors; + baseDataSet.mValueTextSize = mValueTextSize; + baseDataSet.mVisible = mVisible; + } } 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 d8c0c13013..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 @@ -41,20 +41,20 @@ protected void calcMinMax(BubbleEntry e) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - BubbleDataSet copied = new BubbleDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mHighLightColor = mHighLightColor; - + BubbleDataSet copied = new BubbleDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(BubbleDataSet bubbleDataSet) { + bubbleDataSet.mHighlightCircleWidth = mHighlightCircleWidth; + bubbleDataSet.mNormalizeSize = mNormalizeSize; + } + @Override public float getMaxSize() { return mMaxSize; 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 7574b78b27..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 @@ -79,27 +79,30 @@ public CandleDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - yVals.clear(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - CandleDataSet copied = new CandleDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mShadowWidth = mShadowWidth; - copied.mShowCandleBar = mShowCandleBar; - copied.mBarSpace = mBarSpace; - copied.mHighLightColor = mHighLightColor; - copied.mIncreasingPaintStyle = mIncreasingPaintStyle; - copied.mDecreasingPaintStyle = mDecreasingPaintStyle; - copied.mShadowColor = mShadowColor; - + CandleDataSet copied = new CandleDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(CandleDataSet candleDataSet) { + super.copy(candleDataSet); + candleDataSet.mShadowWidth = mShadowWidth; + candleDataSet.mShowCandleBar = mShowCandleBar; + candleDataSet.mBarSpace = mBarSpace; + candleDataSet.mShadowColorSameAsCandle = mShadowColorSameAsCandle; + candleDataSet.mHighLightColor = mHighLightColor; + candleDataSet.mIncreasingPaintStyle = mIncreasingPaintStyle; + candleDataSet.mDecreasingPaintStyle = mDecreasingPaintStyle; + candleDataSet.mNeutralColor = mNeutralColor; + candleDataSet.mIncreasingColor = mIncreasingColor; + candleDataSet.mDecreasingColor = mDecreasingColor; + candleDataSet.mShadowColor = mShadowColor; + } + @Override protected void calcMinMax(CandleEntry e) { 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 a96cfdcf66..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(); } @@ -157,12 +180,20 @@ public void setValues(List values) { */ public abstract DataSet copy(); + /** + * + * @param dataSet + */ + protected void copy(DataSet dataSet) { + super.copy(dataSet); + } + @Override 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(); } @@ -175,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(); } @@ -206,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(); } @@ -232,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); @@ -249,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(); @@ -264,7 +295,7 @@ public boolean removeEntry(T e) { @Override public int getEntryIndex(Entry e) { - return mValues.indexOf(e); + return mEntries.indexOf(e); } @Override @@ -272,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; } @@ -283,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) { @@ -327,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) { @@ -342,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; } @@ -377,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 5eced95e43..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 @@ -30,7 +30,7 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** * the color of the inner circles */ - private int mCircleColorHole = Color.WHITE; + private int mCircleHoleColor = Color.WHITE; /** * the radius of the circle-shaped value indicators @@ -84,27 +84,29 @@ public LineDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - LineDataSet copied = new LineDataSet(yVals, getLabel()); - copied.mMode = mMode; - copied.mColors = mColors; - copied.mCircleRadius = mCircleRadius; - copied.mCircleHoleRadius = mCircleHoleRadius; - copied.mCircleColors = mCircleColors; - copied.mDashPathEffect = mDashPathEffect; - copied.mDrawCircles = mDrawCircles; - copied.mDrawCircleHole = mDrawCircleHole; - copied.mHighLightColor = mHighLightColor; - + LineDataSet copied = new LineDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(LineDataSet lineDataSet) { + super.copy(lineDataSet); + lineDataSet.mCircleColors = mCircleColors; + lineDataSet.mCircleHoleColor = mCircleHoleColor; + lineDataSet.mCircleHoleRadius = mCircleHoleRadius; + lineDataSet.mCircleRadius = mCircleRadius; + lineDataSet.mCubicIntensity = mCubicIntensity; + lineDataSet.mDashPathEffect = mDashPathEffect; + lineDataSet.mDrawCircleHole = mDrawCircleHole; + lineDataSet.mDrawCircles = mDrawCircleHole; + lineDataSet.mFillFormatter = mFillFormatter; + lineDataSet.mMode = mMode; + } + /** * Returns the drawing mode for this line dataset * @@ -364,13 +366,13 @@ public void resetCircleColors() { * * @param color */ - public void setCircleColorHole(int color) { - mCircleColorHole = color; + public void setCircleHoleColor(int color) { + mCircleHoleColor = color; } @Override public int getCircleHoleColor() { - return mCircleColorHole; + return mCircleHoleColor; } /** 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 6971144e14..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 */ @@ -122,4 +123,13 @@ public void setDrawFilled(boolean filled) { public boolean isDrawFilledEnabled() { return mDrawFilled; } + + protected void copy(LineRadarDataSet lineRadarDataSet) { + super.copy(lineRadarDataSet); + lineRadarDataSet.mDrawFilled = mDrawFilled; + lineRadarDataSet.mFillAlpha = mFillAlpha; + lineRadarDataSet.mFillColor = mFillColor; + lineRadarDataSet.mFillDrawable = mFillDrawable; + lineRadarDataSet.mLineWidth = mLineWidth; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index 90a0a43fb3..d4618d809e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -109,4 +109,12 @@ public boolean isDashedHighlightLineEnabled() { public DashPathEffect getDashPathEffectHighlight() { return mHighlightDashPathEffect; } + + protected void copy(LineScatterCandleRadarDataSet lineScatterCandleRadarDataSet) { + super.copy(lineScatterCandleRadarDataSet); + lineScatterCandleRadarDataSet.mDrawHorizontalHighlightIndicator = mDrawHorizontalHighlightIndicator; + lineScatterCandleRadarDataSet.mDrawVerticalHighlightIndicator = mDrawVerticalHighlightIndicator; + lineScatterCandleRadarDataSet.mHighlightLineWidth = mHighlightLineWidth; + lineScatterCandleRadarDataSet.mHighlightDashPathEffect = mHighlightDashPathEffect; + } } 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 010cfbddc5..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,27 +3,34 @@ 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; public class PieDataSet extends DataSet implements IPieDataSet { - /** the space in pixels between the chart-slices, default 0f */ + /** + * the space in pixels between the chart-slices, default 0f + */ private float mSliceSpace = 0f; private boolean mAutomaticallyDisableSliceSpacing; - /** indicates the selection distance of a pie slice */ + /** + * indicates the selection distance of a pie slice + */ private float mShift = 18f; private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; 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); @@ -32,20 +39,19 @@ public PieDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList<>(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList<>(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - PieDataSet copied = new PieDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mSliceSpace = mSliceSpace; - copied.mShift = mShift; + PieDataSet copied = new PieDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(PieDataSet pieDataSet) { + super.copy(pieDataSet); + } + @Override protected void calcMinMax(PieEntry e) { @@ -78,7 +84,7 @@ public float getSliceSpace() { /** * When enabled, slice spacing will be 0.0 when the smallest value is going to be - * smaller than the slice spacing itself. + * smaller than the slice spacing itself. * * @param autoDisable */ @@ -88,7 +94,7 @@ public void setAutomaticallyDisableSliceSpacing(boolean autoDisable) { /** * When enabled, slice spacing will be 0.0 when the smallest value is going to be - * smaller than the slice spacing itself. + * smaller than the slice spacing itself. * * @return */ @@ -100,7 +106,7 @@ public boolean isAutomaticallyDisableSliceSpacingEnabled() { /** * sets the distance the highlighted piechart-slice of this DataSet is * "shifted" away from the center of the chart, default 12f - * + * * @param shift */ public void setSelectionShift(float shift) { @@ -113,99 +119,141 @@ public float getSelectionShift() { } @Override - public ValuePosition getXValuePosition() - { + public ValuePosition getXValuePosition() { return mXValuePosition; } - public void setXValuePosition(ValuePosition xValuePosition) - { + public void setXValuePosition(ValuePosition xValuePosition) { this.mXValuePosition = xValuePosition; } @Override - public ValuePosition getYValuePosition() - { + public ValuePosition getYValuePosition() { return mYValuePosition; } - public void setYValuePosition(ValuePosition yValuePosition) - { + public void setYValuePosition(ValuePosition yValuePosition) { this.mYValuePosition = yValuePosition; } - /** When valuePosition is OutsideSlice, indicates line color */ + /** + * This method is deprecated. + * Use isUseValueColorForLineEnabled() instead. + */ + @Deprecated + public boolean isUsingSliceColorAsValueLineColor() { + return isUseValueColorForLineEnabled(); + } + + /** + * This method is deprecated. + * Use setUseValueColorForLine(...) instead. + * + * @param enabled + */ + @Deprecated + public void setUsingSliceColorAsValueLineColor(boolean enabled) { + setUseValueColorForLine(enabled); + } + + /** + * When valuePosition is OutsideSlice, indicates line color + */ @Override - public int getValueLineColor() - { + public int getValueLineColor() { return mValueLineColor; } - public void setValueLineColor(int valueLineColor) - { + public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } - /** When valuePosition is OutsideSlice, indicates line width */ @Override - public float getValueLineWidth() + public boolean isUseValueColorForLineEnabled() { - return mValueLineWidth; + return mUseValueColorForLine; } - public void setValueLineWidth(float valueLineWidth) + public void setUseValueColorForLine(boolean enabled) { + mUseValueColorForLine = enabled; + } + + /** + * When valuePosition is OutsideSlice, indicates line width + */ + @Override + public float getValueLineWidth() { + return mValueLineWidth; + } + + public void setValueLineWidth(float valueLineWidth) { this.mValueLineWidth = valueLineWidth; } - /** When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size */ + /** + * When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size + */ @Override - public float getValueLinePart1OffsetPercentage() - { + public float getValueLinePart1OffsetPercentage() { return mValueLinePart1OffsetPercentage; } - public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) - { + public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) { this.mValueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage; } - /** When valuePosition is OutsideSlice, indicates length of first half of the line */ + /** + * When valuePosition is OutsideSlice, indicates length of first half of the line + */ @Override - public float getValueLinePart1Length() - { + public float getValueLinePart1Length() { return mValueLinePart1Length; } - public void setValueLinePart1Length(float valueLinePart1Length) - { + public void setValueLinePart1Length(float valueLinePart1Length) { this.mValueLinePart1Length = valueLinePart1Length; } - /** When valuePosition is OutsideSlice, indicates length of second half of the line */ + /** + * When valuePosition is OutsideSlice, indicates length of second half of the line + */ @Override - public float getValueLinePart2Length() - { + public float getValueLinePart2Length() { return mValueLinePart2Length; } - public void setValueLinePart2Length(float valueLinePart2Length) - { + public void setValueLinePart2Length(float valueLinePart2Length) { this.mValueLinePart2Length = valueLinePart2Length; } - /** When valuePosition is OutsideSlice, this allows variable line length */ + /** + * When valuePosition is OutsideSlice, this allows variable line length + */ @Override - public boolean isValueLineVariableLength() - { + public boolean isValueLineVariableLength() { return mValueLineVariableLength; } - public void setValueLineVariableLength(boolean valueLineVariableLength) - { + 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 f18aa8c23a..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 @@ -20,7 +20,7 @@ public class RadarDataSet extends LineRadarDataSet implements IRadar /// If Utils.COLOR_NONE, the color of the dataset is taken. protected int mHighlightCircleStrokeColor = ColorTemplate.COLOR_NONE; - protected int mHighlightCircleStrokeAlpha = (int)(0.3 * 255); + protected int mHighlightCircleStrokeAlpha = (int) (0.3 * 255); protected float mHighlightCircleInnerRadius = 3.0f; protected float mHighlightCircleOuterRadius = 4.0f; protected float mHighlightCircleStrokeWidth = 2.0f; @@ -31,101 +31,92 @@ public RadarDataSet(List yVals, String label) { /// Returns true if highlight circle should be drawn, false if not @Override - public boolean isDrawHighlightCircleEnabled() - { + public boolean isDrawHighlightCircleEnabled() { return mDrawHighlightCircleEnabled; } /// Sets whether highlight circle should be drawn or not @Override - public void setDrawHighlightCircleEnabled(boolean enabled) - { + public void setDrawHighlightCircleEnabled(boolean enabled) { mDrawHighlightCircleEnabled = enabled; } @Override - public int getHighlightCircleFillColor() - { + public int getHighlightCircleFillColor() { return mHighlightCircleFillColor; } - public void setHighlightCircleFillColor(int color) - { + public void setHighlightCircleFillColor(int color) { mHighlightCircleFillColor = color; } /// Returns the stroke color for highlight circle. /// If Utils.COLOR_NONE, the color of the dataset is taken. @Override - public int getHighlightCircleStrokeColor() - { + public int getHighlightCircleStrokeColor() { return mHighlightCircleStrokeColor; } /// Sets the stroke color for highlight circle. /// Set to Utils.COLOR_NONE in order to use the color of the dataset; - public void setHighlightCircleStrokeColor(int color) - { + public void setHighlightCircleStrokeColor(int color) { mHighlightCircleStrokeColor = color; } @Override - public int getHighlightCircleStrokeAlpha() - { + public int getHighlightCircleStrokeAlpha() { return mHighlightCircleStrokeAlpha; } - public void setHighlightCircleStrokeAlpha(int alpha) - { + public void setHighlightCircleStrokeAlpha(int alpha) { mHighlightCircleStrokeAlpha = alpha; } @Override - public float getHighlightCircleInnerRadius() - { + public float getHighlightCircleInnerRadius() { return mHighlightCircleInnerRadius; } - public void setHighlightCircleInnerRadius(float radius) - { + public void setHighlightCircleInnerRadius(float radius) { mHighlightCircleInnerRadius = radius; } @Override - public float getHighlightCircleOuterRadius() - { + public float getHighlightCircleOuterRadius() { return mHighlightCircleOuterRadius; } - public void setHighlightCircleOuterRadius(float radius) - { + public void setHighlightCircleOuterRadius(float radius) { mHighlightCircleOuterRadius = radius; } @Override - public float getHighlightCircleStrokeWidth() - { + public float getHighlightCircleStrokeWidth() { return mHighlightCircleStrokeWidth; } - public void setHighlightCircleStrokeWidth(float strokeWidth) - { + public void setHighlightCircleStrokeWidth(float strokeWidth) { mHighlightCircleStrokeWidth = strokeWidth; } @Override public DataSet copy() { - - List yVals = new ArrayList(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - RadarDataSet copied = new RadarDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mHighLightColor = mHighLightColor; - + RadarDataSet copied = new RadarDataSet(entries, getLabel()); + copy(copied); return copied; } + + protected void copy(RadarDataSet radarDataSet) { + super.copy(radarDataSet); + radarDataSet.mDrawHighlightCircleEnabled = mDrawHighlightCircleEnabled; + radarDataSet.mHighlightCircleFillColor = mHighlightCircleFillColor; + radarDataSet.mHighlightCircleInnerRadius = mHighlightCircleInnerRadius; + radarDataSet.mHighlightCircleStrokeAlpha = mHighlightCircleStrokeAlpha; + radarDataSet.mHighlightCircleStrokeColor = mHighlightCircleStrokeColor; + radarDataSet.mHighlightCircleStrokeWidth = mHighlightCircleStrokeWidth; + } } 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 a9d73885b5..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 @@ -47,28 +47,23 @@ public ScatterDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - - for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + List entries = new ArrayList(); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } - - ScatterDataSet copied = new ScatterDataSet(yVals, getLabel()); - copied.mDrawValues = mDrawValues; - copied.mValueColors = mValueColors; - copied.mColors = mColors; - copied.mShapeSize = mShapeSize; - copied.mShapeRenderer = mShapeRenderer; - copied.mScatterShapeHoleRadius = mScatterShapeHoleRadius; - copied.mScatterShapeHoleColor = mScatterShapeHoleColor; - copied.mHighlightLineWidth = mHighlightLineWidth; - copied.mHighLightColor = mHighLightColor; - copied.mHighlightDashPathEffect = mHighlightDashPathEffect; - + ScatterDataSet copied = new ScatterDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(ScatterDataSet scatterDataSet) { + super.copy(scatterDataSet); + scatterDataSet.mShapeSize = mShapeSize; + scatterDataSet.mShapeRenderer = mShapeRenderer; + scatterDataSet.mScatterShapeHoleRadius = mScatterShapeHoleRadius; + scatterDataSet.mScatterShapeHoleColor = mScatterShapeHoleColor; + } + /** * Sets the size in density pixels the drawn scattershape will have. This * only applies for non custom shapes. @@ -141,13 +136,20 @@ public int getScatterShapeHoleColor() { public static IShapeRenderer getRendererForShape(ScatterChart.ScatterShape shape) { switch (shape) { - case SQUARE: return new SquareShapeRenderer(); - case CIRCLE: return new CircleShapeRenderer(); - case TRIANGLE: return new TriangleShapeRenderer(); - case CROSS: return new CrossShapeRenderer(); - case X: return new XShapeRenderer(); - case CHEVRON_UP: return new ChevronUpShapeRenderer(); - case CHEVRON_DOWN: return new ChevronDownShapeRenderer(); + case SQUARE: + return new SquareShapeRenderer(); + case CIRCLE: + return new CircleShapeRenderer(); + case TRIANGLE: + return new TriangleShapeRenderer(); + case CROSS: + return new CrossShapeRenderer(); + case X: + return new XShapeRenderer(); + case CHEVRON_UP: + return new ChevronUpShapeRenderer(); + case CHEVRON_DOWN: + return new ChevronDownShapeRenderer(); } return null; 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/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index c950d640b3..211401ad8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -20,10 +20,10 @@ public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter { - private static String[] SUFFIX = new String[]{ + private String[] mSuffix = new String[]{ "", "k", "m", "b", "t" }; - private static final int MAX_LENGTH = 5; + private int mMaxLength = 5; private DecimalFormat mFormat; private String mText = ""; @@ -66,10 +66,14 @@ public void setAppendix(String appendix) { * Set custom suffix to be appended after the values. * Default suffix: ["", "k", "m", "b", "t"] * - * @param suff new suffix + * @param suffix new suffix */ - public void setSuffix(String[] suff) { - SUFFIX = suff; + public void setSuffix(String[] suffix) { + this.mSuffix = suffix; + } + + public void setMaxLength(int maxLength) { + this.mMaxLength = maxLength; } /** @@ -84,9 +88,9 @@ private String makePretty(double number) { int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); int combined = Integer.valueOf(numericValue2 + "" + numericValue1); - r = r.replaceAll("E[0-9][0-9]", SUFFIX[combined / 3]); + r = r.replaceAll("E[0-9][0-9]", mSuffix[combined / 3]); - while (r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")) { + while (r.length() > mMaxLength || r.matches("[0-9]+\\.[a-z]")) { r = r.substring(0, r.length() - 2) + r.substring(r.length() - 1); } 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/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index a53a9645af..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,6 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; -import com.github.mikephil.charting.data.Entry; +import androidx.annotation.Nullable; + import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -41,6 +42,11 @@ public interface IPieDataSet extends IDataSet { * */ int getValueLineColor(); + /** + * When valuePosition is OutsideSlice and enabled, line will have the same color as the slice + * */ + boolean isUseValueColorForLineEnabled(); + /** * When valuePosition is OutsideSlice, indicates line width * */ @@ -66,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/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index 0157e8fa76..e5e4c417d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -33,6 +33,8 @@ public static AnimatedZoomJob getInstance(ViewPortHandler viewPortHandler, View result.view = v; result.xOrigin = xOrigin; result.yOrigin = yOrigin; + result.yAxis = axis; + result.xAxisRange = xAxisRange; result.resetAnimator(); result.animator.setDuration(duration); return result; 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 new file mode 100644 index 0000000000..b5c8715a08 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java @@ -0,0 +1,69 @@ +package com.github.mikephil.charting.model; + +import com.github.mikephil.charting.utils.Fill; + +/** + * Deprecated. Use `Fill` + */ +@Deprecated +public class GradientColor extends Fill +{ + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getStartColor() + { + return getGradientColors()[0]; + } + + /** + * 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; + } + } + + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getEndColor() + { + return getGradientColors()[1]; + } + + /** + * 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; + } + } + +} 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 f17761234e..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,6 +15,7 @@ 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; @@ -143,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; @@ -160,11 +163,23 @@ 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)); } - 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.DOWN : Fill.Direction.UP); + } + 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], 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 9921cb1ba6..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 @@ -76,19 +76,21 @@ public void drawData(Canvas c) { int width = (int) mViewPortHandler.getChartWidth(); int height = (int) mViewPortHandler.getChartHeight(); - if (mDrawBitmap == null - || (mDrawBitmap.get().getWidth() != width) - || (mDrawBitmap.get().getHeight() != height)) { + Bitmap drawBitmap = mDrawBitmap == null ? null : mDrawBitmap.get(); - if (width > 0 && height > 0) { + if (drawBitmap == null + || (drawBitmap.getWidth() != width) + || (drawBitmap.getHeight() != height)) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, mBitmapConfig)); - mBitmapCanvas = new Canvas(mDrawBitmap.get()); + if (width > 0 && height > 0) { + drawBitmap = Bitmap.createBitmap(width, height, mBitmapConfig); + mDrawBitmap = new WeakReference<>(drawBitmap); + mBitmapCanvas = new Canvas(drawBitmap); } else return; } - mDrawBitmap.get().eraseColor(Color.TRANSPARENT); + drawBitmap.eraseColor(Color.TRANSPARENT); LineData lineData = mChart.getLineData(); @@ -98,7 +100,7 @@ public void drawData(Canvas c) { drawDataSet(c, set); } - c.drawBitmap(mDrawBitmap.get(), 0, 0, mRenderPaint); + c.drawBitmap(drawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, ILineDataSet dataSet) { @@ -183,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()); @@ -321,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; + + if (mLineBuffer.length <= numberOfFloats) + mLineBuffer = new float[numberOfFloats * 2]; + + int max = mXBounds.min + mXBounds.range; - for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { + for (int j = mXBounds.min; j < max; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -355,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 @@ -495,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); } @@ -528,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 @@ -738,7 +753,10 @@ public void releaseBitmap() { mBitmapCanvas = null; } if (mDrawBitmap != null) { - mDrawBitmap.get().recycle(); + Bitmap drawBitmap = mDrawBitmap.get(); + if (drawBitmap != null) { + drawBitmap.recycle(); + } mDrawBitmap.clear(); mDrawBitmap = null; } 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 be72a0834f..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 @@ -126,19 +126,21 @@ public void drawData(Canvas c) { int width = (int) mViewPortHandler.getChartWidth(); int height = (int) mViewPortHandler.getChartHeight(); - if (mDrawBitmap == null - || (mDrawBitmap.get().getWidth() != width) - || (mDrawBitmap.get().getHeight() != height)) { + Bitmap drawBitmap = mDrawBitmap == null ? null : mDrawBitmap.get(); - if (width > 0 && height > 0) { + if (drawBitmap == null + || (drawBitmap.getWidth() != width) + || (drawBitmap.getHeight() != height)) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444)); - mBitmapCanvas = new Canvas(mDrawBitmap.get()); + if (width > 0 && height > 0) { + drawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mDrawBitmap = new WeakReference<>(drawBitmap); + mBitmapCanvas = new Canvas(drawBitmap); } else return; } - mDrawBitmap.get().eraseColor(Color.TRANSPARENT); + drawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -229,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++) { @@ -248,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; } @@ -395,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; @@ -440,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); @@ -470,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); @@ -535,7 +567,15 @@ public void drawValues(Canvas c) { labelPty = pt2y; } - if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + int lineColor = ColorTemplate.COLOR_NONE; + + 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); } @@ -552,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) { @@ -579,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) { @@ -633,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); @@ -759,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(); @@ -769,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; @@ -786,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; @@ -818,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 : @@ -1010,7 +1059,10 @@ public void releaseBitmap() { mBitmapCanvas = null; } if (mDrawBitmap != null) { - mDrawBitmap.get().recycle(); + Bitmap drawBitmap = mDrawBitmap.get(); + if (drawBitmap != null) { + drawBitmap.recycle(); + } mDrawBitmap.clear(); mDrawBitmap = null; } 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/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 2c305796df..8adb56c73a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -207,7 +207,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) { + if (i / 2 == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 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 063680ed0d..a3253e3ff9 100644 --- a/README.md +++ b/README.md @@ -1,207 +1,188 @@ -[![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) -[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) -[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) -[![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) +![banner](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic_smaller.png) -Remember: *It's all about the looks.* - -![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.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-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) -[**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. +:zap: A powerful & easy to use chart library for Android :zap: -As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: +[**Charts**](https://github.com/danielgindi/Charts) is the iOS version of this library -[Enterprise Solution 5% Discount Coupon | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) ------ +## 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 -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. +```gradle +repositories { + maven { url 'https://jitpack.io/' } +} - +dependencies { + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' +} +``` -All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** +### Maven Setup +```xml + + + jitpack.io + https://jitpack.io + + + + com.github.PhilJay + MPAndroidChart + v3.1.0 + +```
+

Documentation :notebook_with_decorative_cover:

-Donations ------ +See the [**documentation**](https://weeklycoding.com/mpandroidchart/) for examples and general use of MPAndroidChart. -**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) +See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/) for more advanced documentation. -1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg - -**My Ethereum Wallet** (Ethereum only) +
-0x04ef098bf9f91871391363e3caf791afa3adc39b +

Examples :eyes:

-**PayPal** +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). - - [**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 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! +[![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI) +
-Spread the word ------ +

Questions & Issues :thinking:

-If you like this library, please tell others about it :two_hearts: :two_hearts: +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. - - - - - - []()Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) +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. +
-Demo ------ + -For a brief overview of the most important features, please download the **PlayStore Demo** [**MPAndroidChart Example.apk**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) and try it out. The corresponding code for the demo-application is also included in this repository inside the **MPChartExample folder**. +**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! -[![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI) +**PayPal** -Questions & Issues ------ +- [**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 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! -If you are having questions or problems, you should: +
- - **Review your code**. Make absolutely sure that everything is correct on your side. - - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) - - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) - - Check this: ["how not to contribute"](https://github.com/PhilJay/MPAndroidChart/wiki/How-not-to-contribute) - -Please do not expect answers to your questions if you have not considered all above mentioned approaches in advance. +

Social Media :fire:

-Features ------ -You can have a look at the core features of this libary [**here**](https://github.com/PhilJay/MPAndroidChart/wiki/Core-Features). - -Usage ------ +If you like this library, please tell others about it :two_hearts: :two_hearts: -In order to use the library, there are 4 different options: +[![Share on Twitter](https://github.com/PhilJay/MPAndroidChart/blob/master/design/twitter_icon.png)](https://twitter.com/intent/tweet?text=Check%20out%20the%20awesome%20MPAndroidChart%20library%20on%20Github:%20https://github.com/PhilJay/MPAndroidChart) +[![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) -**1. Gradle dependency** (recommended) +If you like, you can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda). - - Add the following to your project level `build.gradle`: - -```gradle -allprojects { - repositories { - maven { url "https://jitpack.io/" } - } -} -``` - - Add this to your app `build.gradle`: - -```gradle -dependencies { - implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' -} -``` +
-**2. Maven** -- Add the following to the `` section of your `pom.xml`: +

More Examples :+1:

- ```xml - - jitpack.io - https://jitpack.io - -``` -- Add the following to the `` section of your `pom.xml`: +
- ```xml - - com.github.PhilJay - MPAndroidChart - v3.0.3 - -``` - -**3. clone whole repository** (not recommended) +**LineChart (with legend, simple design)** -Documentation ------ -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/). +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) +

-Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). -You can also join others in a discussion on [![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) - -Chart types ------ +**LineChart (with legend, simple design)** - - **LineChart (with legend, simple design)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) - - **LineChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart3.png) +

+ +**LineChart (cubic lines)** - - **LineChart (cubic lines)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) +

- - **LineChart (gradient fill)** -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) +**LineChart (gradient fill)** - - **Combined-Chart (bar- and linechart in this case)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) +

- - **BarChart (with legend, simple design)** +**BarChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) +

- - **BarChart (grouped DataSets)** +**BarChart (grouped DataSets)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) +

- - **Horizontal-BarChart** +**Horizontal-BarChart** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) +

+ +**Combined-Chart (bar- and linechart in this case)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) +

- - **PieChart (with selection, ...)** +**PieChart (with selection, ...)** ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/simpledesign_piechart1.png) +

- - **ScatterChart** (with squares, triangles, circles, ... and more) +**ScatterChart** (with squares, triangles, circles, ... and more) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/scatterchart.png) +

- - **CandleStickChart** (for financial data) +**CandleStickChart** (for financial data) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) +

- - **BubbleChart** (area covered by bubbles indicates the yValue) +**BubbleChart** (area covered by bubbles indicates the yValue) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) +

- - **RadarChart** (spider web chart) +**RadarChart** (spider web chart) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) +
+ +

License :page_facing_up:

-License -======= -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, @@ -209,4 +190,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [tony](https://github.com/tonypatino-monoclesociety) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. +
+ +

Special Thanks :heart:

+ +These people rock! + +- [danielgindi](https://github.com/danielgindi) - Daniel Gindi +- [mikegr](https://github.com/mikegr) - Michael Greifeneder +- [tony](https://github.com/tonypatino-monoclesociety) - Tony +- [almic](https://github.com/almic) - Mick A. +- [jitpack.io](https://github.com/jitpack-io) - JitPack.io diff --git a/build.gradle b/build.gradle index 92f3d64ccd..cee7a83e80 100644 --- a/build.gradle +++ b/build.gradle @@ -1,25 +1,17 @@ -//task wrapper(type: Wrapper) { -// gradleVersion = '2.9' -//} - buildscript { repositories { jcenter() google() } dependencies { - classpath "io.realm:realm-gradle-plugin:4.2.0" - classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' + classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } } allprojects { repositories { jcenter() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } } diff --git a/design/feature_graphic_smaller.png b/design/feature_graphic_smaller.png new file mode 100644 index 0000000000..c1e5db5799 Binary files /dev/null and b/design/feature_graphic_smaller.png differ 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 845ff30cac..0f8bc4e375 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Nov 20 11:59:54 CET 2017 +#Sat Apr 27 15:48:29 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip