This commit is contained in:
coco
2026-07-03 15:56:07 +08:00
commit caef23209c
5767 changed files with 1004268 additions and 0 deletions
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="lecho.lib.hellocharts.samples"
android:versionCode="13"
android:versionName="1.5.8" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LineChartActivity"
android:label="@string/title_activity_line_chart" >
</activity>
<activity
android:name=".ColumnChartActivity"
android:label="@string/title_activity_column_chart" >
</activity>
<activity
android:name=".PieChartActivity"
android:label="@string/title_activity_pie_chart" >
</activity>
<activity
android:name=".BubbleChartActivity"
android:label="@string/title_activity_bubble_chart" >
</activity>
<activity
android:name=".PreviewLineChartActivity"
android:label="@string/title_activity_preview_line_chart" >
</activity>
<activity
android:name=".PreviewColumnChartActivity"
android:label="@string/title_activity_preview_column_chart" >
</activity>
<activity
android:name=".ComboLineColumnChartActivity"
android:label="@string/title_activity_combo_line_column_chart" >
</activity>
<activity
android:name=".LineColumnDependencyActivity"
android:label="@string/title_activity_line_column_dependency" >
</activity>
<activity
android:name=".GoodBadChartActivity"
android:label="@string/title_activity_good_bad" >
</activity>
<activity
android:name=".TempoChartActivity"
android:label="@string/title_activity_tempo_chart" >
</activity>
<activity
android:name=".SpeedChartActivity"
android:label="@string/title_activity_speed_chart" >
</activity>
<activity
android:name=".ViewPagerChartsActivity"
android:label="@string/title_activity_view_pager_charts" >
</activity>
<activity
android:name=".AboutActivity"
android:label="@string/title_activity_about" >
</activity>
</application>
</manifest>
@@ -0,0 +1,48 @@
apply plugin: 'com.android.application'
dependencies {
//compile fileTree(dir: 'libs', include: '*.jar')
compile project(':hellocharts-library')
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:appcompat-v7:23.3.0'
}
android {
compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
defaultConfig {
minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION)
targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION)
versionCode Integer.parseInt(project.VERSION_CODE)
versionName project.VERSION_NAME
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
@@ -0,0 +1,20 @@
# 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 *;
#}
@@ -0,0 +1,16 @@
# 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-21
android.library.reference.1=..\\..\\appcompat_v7_21\\appcompat_v7_21
android.library.reference.2=..\\hellocharts-library
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="@color/holo_blue_dark"/>
<item android:state_focused="true" android:color="@color/holo_blue_light"/>
<item android:color="@color/holo_blue"/>
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.AboutActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.BubbleChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.ColumnChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.ComboLineColumnChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.GoodBadChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.LineChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.LineColumnDependencyActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.MainActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.PieChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.PreviewColumnChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.PreviewLineChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.TempoChartActivity"
tools:ignore="MergeRootFrame" />
@@ -0,0 +1,7 @@
<lecho.lib.hellocharts.view.hack.HackyViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="lecho.lib.hellocharts.samples.ViewPagerChartsActivity" />
@@ -0,0 +1,75 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.AboutActivity$PlaceholderFragment" >
<ImageView
android:id="@+id/app_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:contentDescription="@string/about_app_icon_content_description"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/app_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/app_icon"
android:layout_centerHorizontal="true"
android:text="@string/app_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<LinearLayout
android:id="@+id/version_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/app_name"
android:layout_centerHorizontal="true"
android:orientation="horizontal" >
<TextView
android:id="@+id/version_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_version_label" />
<TextView
android:id="@+id/version"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/version_layout"
android:layout_centerHorizontal="true"
android:text="@string/about_author" />
<TextView
android:id="@+id/go_to_github"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/author"
android:layout_marginTop="8dp"
android:gravity="center"
android:padding="8dp"
android:text="@string/about_go_to_github"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/selector_text_link" />
</RelativeLayout>
</ScrollView>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.BubbleChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.BubbleChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.BubbleChartView>
</RelativeLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.ColumnChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.ColumnChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.ColumnChartView>
</RelativeLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.ComboLineColumnChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.ComboLineColumnChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.ComboLineColumnChartView>
</RelativeLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.GoodBadActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.LineChartView>
</RelativeLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.LineChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.LineChartView>
</RelativeLayout>
@@ -0,0 +1,33 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.PreviewLineChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart_top"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.LineChartView>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="@android:color/darker_gray" />
<lecho.lib.hellocharts.view.ColumnChartView
android:id="@+id/chart_bottom"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.ColumnChartView>
</LinearLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.MainActivity$PlaceholderFragment" >
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView>
</RelativeLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.PieChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.PieChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.PieChartView>
</RelativeLayout>
@@ -0,0 +1,33 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.PreviewLineChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.ColumnChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.ColumnChartView>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="@android:color/darker_gray" />
<lecho.lib.hellocharts.view.PreviewColumnChartView
android:id="@+id/chart_preview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.PreviewColumnChartView>
</LinearLayout>
@@ -0,0 +1,33 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.PreviewLineChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.LineChartView>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="@android:color/darker_gray" />
<lecho.lib.hellocharts.view.PreviewLineChartView
android:id="@+id/chart_preview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</lecho.lib.hellocharts.view.PreviewLineChartView>
</LinearLayout>
@@ -0,0 +1,17 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.TempoChartActivity$PlaceholderFragment" >
<lecho.lib.hellocharts.view.LineChartView
android:id="@+id/chart"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</lecho.lib.hellocharts.view.LineChartView>
</RelativeLayout>
@@ -0,0 +1,11 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="lecho.lib.hellocharts.samples.ViewPagerChartsActivity$PlaceholderFragment" >
</RelativeLayout>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp" >
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@+id/chart_layout"
android:text="TEXT1"
android:textSize="16sp" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/text1"
android:layout_below="@+id/text1"
android:layout_toLeftOf="@id/chart_layout"
android:text="TEXT2"
android:textSize="12sp" />
<FrameLayout
android:id="@id/chart_layout"
android:layout_width="54dp"
android:layout_height="54dp"
android:layout_alignParentRight="true"
android:visibility="gone" >
</FrameLayout>
</RelativeLayout>
@@ -0,0 +1,55 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.BubbleChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_shape_circles"
android:title="Circle shape"
app:showAsAction="never"/>
<item
android:id="@+id/action_shape_square"
android:title="Square shape"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes"
android:title="Toggle axes"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes_names"
android:title="Toggle axes names"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels"
android:title="Toggle labels"
app:showAsAction="never"/>
<item
android:id="@+id/action_animate"
android:title="Animate chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_selection_mode"
android:title="Toggle selection mode"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_touch_zoom"
android:title="Toggle touch zoom"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_both"
android:title="Zoom X/Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_horizontal"
android:title="Zoom X"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_vertical"
android:title="Zoom Y"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,63 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.ColumnChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_subcolumns"
android:title="Subcolumns"
app:showAsAction="never"/>
<item
android:id="@+id/action_stacked"
android:title="Stacked"
app:showAsAction="never"/>
<item
android:id="@+id/action_negative_subcolumns"
android:title="Negative subcolumns"
app:showAsAction="never"/>
<item
android:id="@+id/action_negative_stacked"
android:title="Negative stacked"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes"
android:title="Toggle axes"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes_names"
android:title="Toggle axes names"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels"
android:title="Toggle labels"
app:showAsAction="never"/>
<item
android:id="@+id/action_animate"
android:title="Animate chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_selection_mode"
android:title="Toggle selection mode"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_touch_zoom"
android:title="Toggle touch zoom"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_both"
android:title="Zoom X/Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_horizontal"
android:title="Zoom X"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_vertical"
android:title="Zoom Y"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,42 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.ComboLineColumnChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_add_line"
android:title="Add line"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_lines"
android:title="Toggle lines/scattered"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_points"
android:title="Toggle points"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_cubic"
android:title="Toggle Cubic curve"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes"
android:title="Toggle axes"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes_names"
android:title="Toggle axes names"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels"
android:title="Toggle labels"
app:showAsAction="never"/>
<item
android:id="@+id/action_animate"
android:title="Animate chart"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,87 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.LineChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_add_line"
android:title="Add line"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_lines"
android:title="Toggle lines/scattered"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_points"
android:title="Toggle points"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_gradient"
android:title="Toggle gradient"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_cubic"
android:title="Toggle Cubic curve"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_area"
android:title="Toggle area"
app:showAsAction="never"/>
<item
android:id="@+id/action_point_color"
android:title="Toggle Point Color"
app:showAsAction="never"/>
<item
android:id="@+id/action_shape_circles"
android:title="Circle shape"
app:showAsAction="never"/>
<item
android:id="@+id/action_shape_square"
android:title="Square shape"
app:showAsAction="never"/>
<item
android:id="@+id/action_shape_diamond"
android:title="Diamond shape"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes"
android:title="Toggle axes"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_axes_names"
android:title="Toggle axes names"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels"
android:title="Toggle labels"
app:showAsAction="never"/>
<item
android:id="@+id/action_animate"
android:title="Animate chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_selection_mode"
android:title="Toggle selection mode"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_touch_zoom"
android:title="Toggle touch zoom"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_both"
android:title="Zoom X/Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_horizontal"
android:title="Zoom X"
app:showAsAction="never"/>
<item
android:id="@+id/action_zoom_vertical"
android:title="Zoom Y"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,12 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.MainActivity" >
<item
android:id="@+id/action_about"
android:orderInCategory="100"
app:showAsAction="never"
android:title="@string/action_about"/>
</menu>
@@ -0,0 +1,43 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.PieChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_explode"
android:title="Explode/Implode chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_center_circle"
android:title="Center circle"
app:showAsAction="never"/>
<item
android:id="@+id/action_center_text1"
android:title="Center circle text 1"
app:showAsAction="never"/>
<item
android:id="@+id/action_center_text2"
android:title="Center circle text 2"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels"
android:title="Toggle labels"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_labels_outside"
android:title="Toggle labels outside"
app:showAsAction="never"/>
<item
android:id="@+id/action_animate"
android:title="Animate chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_toggle_selection_mode"
android:title="Toggle selection mode"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,27 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.PreviewColumnChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_both"
android:title="Preview X/Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_horizontal"
android:title="Preveiw X"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_vertical"
android:title="Preview Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_change_color"
android:title="Change color"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,27 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.PreviewLineChartActivity" >
<item
android:id="@+id/action_reset"
android:title="Reset chart"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_both"
android:title="Preview X/Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_horizontal"
android:title="Preveiw X"
app:showAsAction="never"/>
<item
android:id="@+id/action_preview_vertical"
android:title="Preview Y"
app:showAsAction="never"/>
<item
android:id="@+id/action_change_color"
android:title="Change color"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,17 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="lecho.lib.hellocharts.samples.TempoChartActivity" >
<item
android:id="@+id/action_tempo"
android:orderInCategory="100"
android:title="Tempo/Height"
app:showAsAction="never"/>
<item
android:id="@+id/action_speed"
android:orderInCategory="100"
android:title="Speed/Height"
app:showAsAction="never"/>
</menu>
@@ -0,0 +1,6 @@
<resources>
<dimen name="pie_chart_text1_size">38sp</dimen>
<dimen name="pie_chart_text2_size">12dp</dimen>
</resources>
@@ -0,0 +1,11 @@
<resources>
<!--
Customize dimensions originally defined in res/values/dimens.xml (such as
screen margins) for sw600dp devices (e.g. 7" tablets) here.
-->
<dimen name="pie_chart_text1_size">54sp</dimen>
<dimen name="pie_chart_text2_size">24dp</dimen>
</resources>
@@ -0,0 +1,3 @@
<resources>
</resources>
@@ -0,0 +1,3 @@
<resources>
</resources>
@@ -0,0 +1,10 @@
<resources>
<!--
Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
-->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="holo_blue">#33B5E5</color>
<color name="holo_blue_light">#8033B5E5</color>
<color name="holo_blue_dark">#0099CC</color>
<color name="holo_orange_dark">#FF8800</color>
<color name="holo_orange">#FFBB33</color>
</resources>
@@ -0,0 +1,9 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="pie_chart_text1_size">42sp</dimen>
<dimen name="pie_chart_text2_size">16dp</dimen>
</resources>
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">HelloCharts</string>
<string name="action_about">About</string>
<string name="title_activity_line_chart">LineChartActivity</string>
<string name="title_activity_column_chart">ColumnChartActivity</string>
<string name="title_activity_pie_chart">PieChartActivity</string>
<string name="title_activity_bubble_chart">BubbleChartActivity</string>
<string name="title_activity_preview_line_chart">PreviewLineChartActivity</string>
<string name="title_activity_preview_column_chart">PreviewColumnChartActivity</string>
<string name="title_activity_combo_line_column_chart">ComboLineColumnChartActivity</string>
<string name="title_activity_line_column_dependency">LineColumnDependency</string>
<string name="title_activity_good_bad">GoodBadActivity</string>
<string name="title_activity_tempo_chart">TempoChartActivity</string>
<string name="title_activity_speed_chart">SpeedChartActivity</string>
<string name="title_activity_view_pager_charts">ViewPagerChartsActivity</string>
<string name="title_section1">Section 1</string>
<string name="title_section2">Section 2</string>
<string name="title_section3">Section 3</string>
<string name="title_activity_about">AboutActivity</string>
<string name="about_version_label">"Library version "</string>
<string name="about_author">Leszek Wach 2014</string>
<string name="about_app_icon_content_description">App icon</string>
<string name="about_go_to_github">Go to GitHub</string>
</resources>
@@ -0,0 +1,10 @@
<resources>
<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
<item name="colorPrimary">@color/holo_blue</item>
<item name="colorPrimaryDark">@color/holo_blue_dark</item>
</style>
<style name="AppTheme" parent="AppBaseTheme"></style>
</resources>
@@ -0,0 +1,96 @@
package lecho.lib.hellocharts.samples;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class AboutActivity extends ActionBarActivity {
public static final String TAG = AboutActivity.class.getSimpleName();
public static final String GITHUB_URL = "github.com/lecho/hellocharts-android";
public static Pair<String, Integer> getAppVersionAndBuild(Context context) {
try {
PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
return new Pair<String, Integer>(pInfo.versionName, pInfo.versionCode);
} catch (Exception e) {
Log.e(TAG, "Could not get version number");
return new Pair<String, Integer>("", 0);
}
}
@SuppressLint("DefaultLocale")
public static boolean launchWebBrowser(Context context, String url) {
try {
url = url.toLowerCase();
if (!url.startsWith("http://") || !url.startsWith("https://")) {
url = "http://" + url;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (null == resolveInfo) {
Log.e(TAG, "No activity to handle web intent");
return false;
}
context.startActivity(intent);
Log.i(TAG, "Launching browser with url: " + url);
return true;
} catch (Exception e) {
Log.e(TAG, "Could not start web browser", e);
return false;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_about);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_about, container, false);
TextView version = (TextView) rootView.findViewById(R.id.version);
version.setText(getAppVersionAndBuild(getActivity()).first);
TextView gotToGithub = (TextView) rootView.findViewById(R.id.go_to_github);
gotToGithub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
launchWebBrowser(getActivity(), GITHUB_URL);
}
});
return rootView;
}
}
}
@@ -0,0 +1,251 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.BubbleChartOnValueSelectListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.BubbleChartData;
import lecho.lib.hellocharts.model.BubbleValue;
import lecho.lib.hellocharts.model.ValueShape;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.BubbleChartView;
import lecho.lib.hellocharts.view.Chart;
public class BubbleChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bubble_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a bubble chart.
*/
public static class PlaceholderFragment extends Fragment {
private static final int BUBBLES_NUM = 8;
private BubbleChartView chart;
private BubbleChartData data;
private boolean hasAxes = true;
private boolean hasAxesNames = true;
private ValueShape shape = ValueShape.CIRCLE;
private boolean hasLabels = false;
private boolean hasLabelForSelected = false;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_bubble_chart, container, false);
chart = (BubbleChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ValueTouchListener());
generateData();
return rootView;
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.bubble_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
reset();
generateData();
return true;
}
if (id == R.id.action_shape_circles) {
setCircles();
return true;
}
if (id == R.id.action_shape_square) {
setSquares();
return true;
}
if (id == R.id.action_toggle_labels) {
toggleLabels();
return true;
}
if (id == R.id.action_toggle_axes) {
toggleAxes();
return true;
}
if (id == R.id.action_toggle_axes_names) {
toggleAxesNames();
return true;
}
if (id == R.id.action_animate) {
prepareDataAnimation();
chart.startDataAnimation();
return true;
}
if (id == R.id.action_toggle_selection_mode) {
toggleLabelForSelected();
Toast.makeText(getActivity(),
"Selection mode set to " + chart.isValueSelectionEnabled() + " select any point.",
Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_toggle_touch_zoom) {
chart.setZoomEnabled(!chart.isZoomEnabled());
Toast.makeText(getActivity(), "IsZoomEnabled " + chart.isZoomEnabled(), Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_zoom_both) {
chart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
return true;
}
if (id == R.id.action_zoom_horizontal) {
chart.setZoomType(ZoomType.HORIZONTAL);
return true;
}
if (id == R.id.action_zoom_vertical) {
chart.setZoomType(ZoomType.VERTICAL);
return true;
}
return super.onOptionsItemSelected(item);
}
private void reset() {
hasAxes = true;
hasAxesNames = true;
shape = ValueShape.CIRCLE;
hasLabels = false;
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
private void generateData() {
List<BubbleValue> values = new ArrayList<BubbleValue>();
for (int i = 0; i < BUBBLES_NUM; ++i) {
BubbleValue value = new BubbleValue(i, (float) Math.random() * 100, (float) Math.random() * 1000);
value.setColor(ChartUtils.pickColor());
value.setShape(shape);
values.add(value);
}
data = new BubbleChartData(values);
data.setHasLabels(hasLabels);
data.setHasLabelsOnlyForSelected(hasLabelForSelected);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setBubbleChartData(data);
}
private void setCircles() {
shape = ValueShape.CIRCLE;
generateData();
}
private void setSquares() {
shape = ValueShape.SQUARE;
generateData();
}
private void toggleLabels() {
hasLabels = !hasLabels;
if (hasLabels) {
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
generateData();
}
private void toggleLabelForSelected() {
hasLabelForSelected = !hasLabelForSelected;
chart.setValueSelectionEnabled(hasLabelForSelected);
if (hasLabelForSelected) {
hasLabels = false;
}
generateData();
}
private void toggleAxes() {
hasAxes = !hasAxes;
generateData();
}
private void toggleAxesNames() {
hasAxesNames = !hasAxesNames;
generateData();
}
/**
* To animate values you have to change targets values and then call {@link Chart#startDataAnimation()}
* method(don't confuse with View.animate()).
*/
private void prepareDataAnimation() {
for (BubbleValue value : data.getValues()) {
value.setTarget(value.getX() + (float) Math.random() * 4 * getSign(), (float) Math.random() * 100,
(float) Math.random() * 1000);
}
}
private int getSign() {
int[] sign = new int[]{-1, 1};
return sign[Math.round((float) Math.random())];
}
private class ValueTouchListener implements BubbleChartOnValueSelectListener {
@Override
public void onValueSelected(int bubbleIndex, BubbleValue value) {
Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onValueDeselected() {
// TODO Auto-generated method stub
}
}
}
}
@@ -0,0 +1,460 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.ColumnChartOnValueSelectListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Column;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.SubcolumnValue;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.Chart;
import lecho.lib.hellocharts.view.ColumnChartView;
public class ColumnChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_column_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a column chart.
*/
public static class PlaceholderFragment extends Fragment {
private static final int DEFAULT_DATA = 0;
private static final int SUBCOLUMNS_DATA = 1;
private static final int STACKED_DATA = 2;
private static final int NEGATIVE_SUBCOLUMNS_DATA = 3;
private static final int NEGATIVE_STACKED_DATA = 4;
private ColumnChartView chart;
private ColumnChartData data;
private boolean hasAxes = true;
private boolean hasAxesNames = true;
private boolean hasLabels = false;
private boolean hasLabelForSelected = false;
private int dataType = DEFAULT_DATA;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_column_chart, container, false);
chart = (ColumnChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ValueTouchListener());
generateData();
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.column_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
reset();
generateData();
return true;
}
if (id == R.id.action_subcolumns) {
dataType = SUBCOLUMNS_DATA;
generateData();
return true;
}
if (id == R.id.action_stacked) {
dataType = STACKED_DATA;
generateData();
return true;
}
if (id == R.id.action_negative_subcolumns) {
dataType = NEGATIVE_SUBCOLUMNS_DATA;
generateData();
return true;
}
if (id == R.id.action_negative_stacked) {
dataType = NEGATIVE_STACKED_DATA;
generateData();
return true;
}
if (id == R.id.action_toggle_labels) {
toggleLabels();
return true;
}
if (id == R.id.action_toggle_axes) {
toggleAxes();
return true;
}
if (id == R.id.action_toggle_axes_names) {
toggleAxesNames();
return true;
}
if (id == R.id.action_animate) {
prepareDataAnimation();
chart.startDataAnimation();
return true;
}
if (id == R.id.action_toggle_selection_mode) {
toggleLabelForSelected();
Toast.makeText(getActivity(),
"Selection mode set to " + chart.isValueSelectionEnabled() + " select any point.",
Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_toggle_touch_zoom) {
chart.setZoomEnabled(!chart.isZoomEnabled());
Toast.makeText(getActivity(), "IsZoomEnabled " + chart.isZoomEnabled(), Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_zoom_both) {
chart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
return true;
}
if (id == R.id.action_zoom_horizontal) {
chart.setZoomType(ZoomType.HORIZONTAL);
return true;
}
if (id == R.id.action_zoom_vertical) {
chart.setZoomType(ZoomType.VERTICAL);
return true;
}
return super.onOptionsItemSelected(item);
}
private void reset() {
hasAxes = true;
hasAxesNames = true;
hasLabels = false;
hasLabelForSelected = false;
dataType = DEFAULT_DATA;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
private void generateDefaultData() {
int numSubcolumns = 1;
int numColumns = 8;
// Column can have many subcolumns, here by default I use 1 subcolumn in each of 8 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50f + 5, ChartUtils.pickColor()));
}
Column column = new Column(values);
column.setHasLabels(hasLabels);
column.setHasLabelsOnlyForSelected(hasLabelForSelected);
columns.add(column);
}
data = new ColumnChartData(columns);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setColumnChartData(data);
}
/**
* Generates columns with subcolumns, columns have larger separation than subcolumns.
*/
private void generateSubcolumnsData() {
int numSubcolumns = 4;
int numColumns = 4;
// Column can have many subcolumns, here I use 4 subcolumn in each of 8 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50f + 5, ChartUtils.pickColor()));
}
Column column = new Column(values);
column.setHasLabels(hasLabels);
column.setHasLabelsOnlyForSelected(hasLabelForSelected);
columns.add(column);
}
data = new ColumnChartData(columns);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setColumnChartData(data);
}
/**
* Generates columns with stacked subcolumns.
*/
private void generateStackedData() {
int numSubcolumns = 4;
int numColumns = 8;
// Column can have many stacked subcolumns, here I use 4 stacke subcolumn in each of 4 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 20f + 5, ChartUtils.pickColor()));
}
Column column = new Column(values);
column.setHasLabels(hasLabels);
column.setHasLabelsOnlyForSelected(hasLabelForSelected);
columns.add(column);
}
data = new ColumnChartData(columns);
// Set stacked flag.
data.setStacked(true);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setColumnChartData(data);
}
private void generateNegativeSubcolumnsData() {
int numSubcolumns = 4;
int numColumns = 4;
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
int sign = getSign();
values.add(new SubcolumnValue((float) Math.random() * 50f * sign + 5 * sign, ChartUtils.pickColor
()));
}
Column column = new Column(values);
column.setHasLabels(hasLabels);
column.setHasLabelsOnlyForSelected(hasLabelForSelected);
columns.add(column);
}
data = new ColumnChartData(columns);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setColumnChartData(data);
}
private void generateNegativeStackedData() {
int numSubcolumns = 4;
int numColumns = 8;
// Column can have many stacked subcolumns, here I use 4 stacke subcolumn in each of 4 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
int sign = getSign();
values.add(new SubcolumnValue((float) Math.random() * 20f * sign + 5 * sign, ChartUtils.pickColor()));
}
Column column = new Column(values);
column.setHasLabels(hasLabels);
column.setHasLabelsOnlyForSelected(hasLabelForSelected);
columns.add(column);
}
data = new ColumnChartData(columns);
// Set stacked flag.
data.setStacked(true);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setColumnChartData(data);
}
private int getSign() {
int[] sign = new int[]{-1, 1};
return sign[Math.round((float) Math.random())];
}
private void generateData() {
switch (dataType) {
case DEFAULT_DATA:
generateDefaultData();
break;
case SUBCOLUMNS_DATA:
generateSubcolumnsData();
break;
case STACKED_DATA:
generateStackedData();
break;
case NEGATIVE_SUBCOLUMNS_DATA:
generateNegativeSubcolumnsData();
break;
case NEGATIVE_STACKED_DATA:
generateNegativeStackedData();
break;
default:
generateDefaultData();
break;
}
}
private void toggleLabels() {
hasLabels = !hasLabels;
if (hasLabels) {
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
generateData();
}
private void toggleLabelForSelected() {
hasLabelForSelected = !hasLabelForSelected;
chart.setValueSelectionEnabled(hasLabelForSelected);
if (hasLabelForSelected) {
hasLabels = false;
}
generateData();
}
private void toggleAxes() {
hasAxes = !hasAxes;
generateData();
}
private void toggleAxesNames() {
hasAxesNames = !hasAxesNames;
generateData();
}
/**
* To animate values you have to change targets values and then call {@link Chart#startDataAnimation()}
* method(don't confuse with View.animate()).
*/
private void prepareDataAnimation() {
for (Column column : data.getColumns()) {
for (SubcolumnValue value : column.getValues()) {
value.setTarget((float) Math.random() * 100);
}
}
}
private class ValueTouchListener implements ColumnChartOnValueSelectListener {
@Override
public void onValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) {
Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onValueDeselected() {
// TODO Auto-generated method stub
}
}
}
}
@@ -0,0 +1,299 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.listener.ComboLineColumnChartOnValueSelectListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Column;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.ComboLineColumnChartData;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.SubcolumnValue;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.ComboLineColumnChartView;
public class ComboLineColumnChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_combo_line_column_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a combo line/column chart view.
*/
public static class PlaceholderFragment extends Fragment {
private ComboLineColumnChartView chart;
private ComboLineColumnChartData data;
private int numberOfLines = 1;
private int maxNumberOfLines = 4;
private int numberOfPoints = 12;
float[][] randomNumbersTab = new float[maxNumberOfLines][numberOfPoints];
private boolean hasAxes = true;
private boolean hasAxesNames = true;
private boolean hasPoints = true;
private boolean hasLines = true;
private boolean isCubic = false;
private boolean hasLabels = false;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_combo_line_column_chart, container, false);
chart = (ComboLineColumnChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ValueTouchListener());
generateValues();
generateData();
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.combo_line_column_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
reset();
generateData();
return true;
}
if (id == R.id.action_add_line) {
addLineToData();
return true;
}
if (id == R.id.action_toggle_lines) {
toggleLines();
return true;
}
if (id == R.id.action_toggle_points) {
togglePoints();
return true;
}
if (id == R.id.action_toggle_cubic) {
toggleCubic();
return true;
}
if (id == R.id.action_toggle_labels) {
toggleLabels();
return true;
}
if (id == R.id.action_toggle_axes) {
toggleAxes();
return true;
}
if (id == R.id.action_toggle_axes_names) {
toggleAxesNames();
return true;
}
if (id == R.id.action_animate) {
prepareDataAnimation();
chart.startDataAnimation();
return true;
}
return super.onOptionsItemSelected(item);
}
private void generateValues() {
for (int i = 0; i < maxNumberOfLines; ++i) {
for (int j = 0; j < numberOfPoints; ++j) {
randomNumbersTab[i][j] = (float) Math.random() * 50f + 5;
}
}
}
private void reset() {
numberOfLines = 1;
hasAxes = true;
hasAxesNames = true;
hasLines = true;
hasPoints = true;
hasLabels = false;
isCubic = false;
}
private void generateData() {
// Chart looks the best when line data and column data have similar maximum viewports.
data = new ComboLineColumnChartData(generateColumnData(), generateLineData());
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
chart.setComboLineColumnChartData(data);
}
private LineChartData generateLineData() {
List<Line> lines = new ArrayList<Line>();
for (int i = 0; i < numberOfLines; ++i) {
List<PointValue> values = new ArrayList<PointValue>();
for (int j = 0; j < numberOfPoints; ++j) {
values.add(new PointValue(j, randomNumbersTab[i][j]));
}
Line line = new Line(values);
line.setColor(ChartUtils.COLORS[i]);
line.setCubic(isCubic);
line.setHasLabels(hasLabels);
line.setHasLines(hasLines);
line.setHasPoints(hasPoints);
lines.add(line);
}
LineChartData lineChartData = new LineChartData(lines);
return lineChartData;
}
private ColumnChartData generateColumnData() {
int numSubcolumns = 1;
int numColumns = 12;
// Column can have many subcolumns, here by default I use 1 subcolumn in each of 8 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50 + 5, ChartUtils.COLOR_GREEN));
}
columns.add(new Column(values));
}
ColumnChartData columnChartData = new ColumnChartData(columns);
return columnChartData;
}
private void addLineToData() {
if (data.getLineChartData().getLines().size() >= maxNumberOfLines) {
Toast.makeText(getActivity(), "Samples app uses max 4 lines!", Toast.LENGTH_SHORT).show();
return;
} else {
++numberOfLines;
}
generateData();
}
private void toggleLines() {
hasLines = !hasLines;
generateData();
}
private void togglePoints() {
hasPoints = !hasPoints;
generateData();
}
private void toggleCubic() {
isCubic = !isCubic;
generateData();
}
private void toggleLabels() {
hasLabels = !hasLabels;
generateData();
}
private void toggleAxes() {
hasAxes = !hasAxes;
generateData();
}
private void toggleAxesNames() {
hasAxesNames = !hasAxesNames;
generateData();
}
private void prepareDataAnimation() {
// Line animations
for (Line line : data.getLineChartData().getLines()) {
for (PointValue value : line.getValues()) {
// Here I modify target only for Y values but it is OK to modify X targets as well.
value.setTarget(value.getX(), (float) Math.random() * 50 + 5);
}
}
// Columns animations
for (Column column : data.getColumnChartData().getColumns()) {
for (SubcolumnValue value : column.getValues()) {
value.setTarget((float) Math.random() * 50 + 5);
}
}
}
private class ValueTouchListener implements ComboLineColumnChartOnValueSelectListener {
@Override
public void onValueDeselected() {
// TODO Auto-generated method stub
}
@Override
public void onColumnValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) {
Toast.makeText(getActivity(), "Selected column: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onPointValueSelected(int lineIndex, int pointIndex, PointValue value) {
Toast.makeText(getActivity(), "Selected line point: " + value, Toast.LENGTH_SHORT).show();
}
}
}
}
@@ -0,0 +1,124 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.LineChartView;
public class GoodBadChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_good_bad);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
private LineChartView chart;
private LineChartData data;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_good_bad, container, false);
chart = (LineChartView) rootView.findViewById(R.id.chart);
generateDefaultData();
chart.setLineChartData(data);
// Increase viewport height for better look
Viewport v = chart.getMaximumViewport();
float dy = v.height() * 0.2f;
v.inset(0, -dy);
chart.setMaximumViewport(v);
chart.setCurrentViewport(v);
return rootView;
}
private void generateDefaultData() {
// Generate data, every line has 3 points to form filled triangle. Point radius is set to 1 to be almost
// invisible but it has to be there because without points there is not labels. Area transparency is set to
// 255(full opacity).
// Important note. This example uses negative values, to properly fill area below 0 chart base value have to
// be set to 0. That is default base value but if you want to be sure you can call data.setBaseValue(0)
// method.
Line line;
List<PointValue> values;
List<Line> lines = new ArrayList<Line>();
// First good triangle
values = new ArrayList<PointValue>();
values.add(new PointValue(0, 0).setLabel("".toCharArray()));
values.add(new PointValue(1, 1).setLabel("Very Good:)".toCharArray()));
values.add(new PointValue(2, 0).setLabel("".toCharArray()));
line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN);
line.setAreaTransparency(255);
line.setFilled(true);
line.setPointRadius(1);
line.setHasLabels(true);
lines.add(line);
// Second good triangle
values = new ArrayList<PointValue>();
values.add(new PointValue(3, 0).setLabel("".toCharArray()));
values.add(new PointValue(4, 0.5f).setLabel("Good Enough".toCharArray()));
values.add(new PointValue(5, 0).setLabel("".toCharArray()));
line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN);
line.setAreaTransparency(255);
line.setFilled(true);
line.setPointRadius(1);
line.setHasLabels(true);
lines.add(line);
// Bad triangle
values = new ArrayList<PointValue>();
values.add(new PointValue(1, 0).setLabel("".toCharArray()));
values.add(new PointValue(2, -1).setLabel("Very Bad".toCharArray()));
values.add(new PointValue(3, 0).setLabel("".toCharArray()));
line = new Line(values);
line.setColor(ChartUtils.COLOR_RED);
line.setAreaTransparency(255);
line.setFilled(true);
line.setPointRadius(1);
line.setHasLabels(true);
lines.add(line);
data = new LineChartData(lines);
// *** Important, set base value to 0 to fill negative part of chart.
// data.setBaseValue(0);
}
}
}
@@ -0,0 +1,452 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.animation.ChartAnimationListener;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.LineChartOnValueSelectListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.ValueShape;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.Chart;
import lecho.lib.hellocharts.view.LineChartView;
public class LineChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_line_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a line chart.
*/
public static class PlaceholderFragment extends Fragment {
private LineChartView chart;
private LineChartData data;
private int numberOfLines = 1;
private int maxNumberOfLines = 4;
private int numberOfPoints = 12;
float[][] randomNumbersTab = new float[maxNumberOfLines][numberOfPoints];
private boolean hasAxes = true;
private boolean hasAxesNames = true;
private boolean hasLines = true;
private boolean hasPoints = true;
private ValueShape shape = ValueShape.CIRCLE;
private boolean isFilled = false;
private boolean hasLabels = false;
private boolean isCubic = false;
private boolean hasLabelForSelected = false;
private boolean pointsHaveDifferentColor;
private boolean hasGradientToTransparent = false;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_line_chart, container, false);
chart = (LineChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ValueTouchListener());
// Generate some random values.
generateValues();
generateData();
// Disable viewport recalculations, see toggleCubic() method for more info.
chart.setViewportCalculationEnabled(false);
resetViewport();
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.line_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
reset();
generateData();
return true;
}
if (id == R.id.action_add_line) {
addLineToData();
return true;
}
if (id == R.id.action_toggle_lines) {
toggleLines();
return true;
}
if (id == R.id.action_toggle_points) {
togglePoints();
return true;
}
if (id == R.id.action_toggle_gradient) {
toggleGradient();
return true;
}
if (id == R.id.action_toggle_cubic) {
toggleCubic();
return true;
}
if (id == R.id.action_toggle_area) {
toggleFilled();
return true;
}
if (id == R.id.action_point_color) {
togglePointColor();
return true;
}
if (id == R.id.action_shape_circles) {
setCircles();
return true;
}
if (id == R.id.action_shape_square) {
setSquares();
return true;
}
if (id == R.id.action_shape_diamond) {
setDiamonds();
return true;
}
if (id == R.id.action_toggle_labels) {
toggleLabels();
return true;
}
if (id == R.id.action_toggle_axes) {
toggleAxes();
return true;
}
if (id == R.id.action_toggle_axes_names) {
toggleAxesNames();
return true;
}
if (id == R.id.action_animate) {
prepareDataAnimation();
chart.startDataAnimation();
return true;
}
if (id == R.id.action_toggle_selection_mode) {
toggleLabelForSelected();
Toast.makeText(getActivity(),
"Selection mode set to " + chart.isValueSelectionEnabled() + " select any point.",
Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_toggle_touch_zoom) {
chart.setZoomEnabled(!chart.isZoomEnabled());
Toast.makeText(getActivity(), "IsZoomEnabled " + chart.isZoomEnabled(), Toast.LENGTH_SHORT).show();
return true;
}
if (id == R.id.action_zoom_both) {
chart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
return true;
}
if (id == R.id.action_zoom_horizontal) {
chart.setZoomType(ZoomType.HORIZONTAL);
return true;
}
if (id == R.id.action_zoom_vertical) {
chart.setZoomType(ZoomType.VERTICAL);
return true;
}
return super.onOptionsItemSelected(item);
}
private void generateValues() {
for (int i = 0; i < maxNumberOfLines; ++i) {
for (int j = 0; j < numberOfPoints; ++j) {
randomNumbersTab[i][j] = (float) Math.random() * 100f;
}
}
}
private void reset() {
numberOfLines = 1;
hasAxes = true;
hasAxesNames = true;
hasLines = true;
hasPoints = true;
shape = ValueShape.CIRCLE;
isFilled = false;
hasLabels = false;
isCubic = false;
hasLabelForSelected = false;
pointsHaveDifferentColor = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
resetViewport();
}
private void resetViewport() {
// Reset viewport height range to (0,100)
final Viewport v = new Viewport(chart.getMaximumViewport());
v.bottom = 0;
v.top = 100;
v.left = 0;
v.right = numberOfPoints - 1;
chart.setMaximumViewport(v);
chart.setCurrentViewport(v);
}
private void generateData() {
List<Line> lines = new ArrayList<Line>();
for (int i = 0; i < numberOfLines; ++i) {
List<PointValue> values = new ArrayList<PointValue>();
for (int j = 0; j < numberOfPoints; ++j) {
values.add(new PointValue(j, randomNumbersTab[i][j]));
}
Line line = new Line(values);
line.setColor(ChartUtils.COLORS[i]);
line.setShape(shape);
line.setCubic(isCubic);
line.setFilled(isFilled);
line.setHasLabels(hasLabels);
line.setHasLabelsOnlyForSelected(hasLabelForSelected);
line.setHasLines(hasLines);
line.setHasPoints(hasPoints);
line.setHasGradientToTransparent(hasGradientToTransparent);
if (pointsHaveDifferentColor){
line.setPointColor(ChartUtils.COLORS[(i + 1) % ChartUtils.COLORS.length]);
}
lines.add(line);
}
data = new LineChartData(lines);
if (hasAxes) {
Axis axisX = new Axis();
Axis axisY = new Axis().setHasLines(true);
if (hasAxesNames) {
axisX.setName("Axis X");
axisY.setName("Axis Y");
}
data.setAxisXBottom(axisX);
data.setAxisYLeft(axisY);
} else {
data.setAxisXBottom(null);
data.setAxisYLeft(null);
}
data.setBaseValue(Float.NEGATIVE_INFINITY);
chart.setLineChartData(data);
}
/**
* Adds lines to data, after that data should be set again with
* {@link LineChartView#setLineChartData(LineChartData)}. Last 4th line has non-monotonically x values.
*/
private void addLineToData() {
if (data.getLines().size() >= maxNumberOfLines) {
Toast.makeText(getActivity(), "Samples app uses max 4 lines!", Toast.LENGTH_SHORT).show();
return;
} else {
++numberOfLines;
}
generateData();
}
private void toggleLines() {
hasLines = !hasLines;
generateData();
}
private void togglePoints() {
hasPoints = !hasPoints;
generateData();
}
private void toggleGradient() {
hasGradientToTransparent = !hasGradientToTransparent;
generateData();
}
private void toggleCubic() {
isCubic = !isCubic;
generateData();
if (isCubic) {
// It is good idea to manually set a little higher max viewport for cubic lines because sometimes line
// go above or below max/min. To do that use Viewport.inest() method and pass negative value as dy
// parameter or just set top and bottom values manually.
// In this example I know that Y values are within (0,100) range so I set viewport height range manually
// to (-5, 105).
// To make this works during animations you should use Chart.setViewportCalculationEnabled(false) before
// modifying viewport.
// Remember to set viewport after you call setLineChartData().
final Viewport v = new Viewport(chart.getMaximumViewport());
v.bottom = -5;
v.top = 105;
// You have to set max and current viewports separately.
chart.setMaximumViewport(v);
// I changing current viewport with animation in this case.
chart.setCurrentViewportWithAnimation(v);
} else {
// If not cubic restore viewport to (0,100) range.
final Viewport v = new Viewport(chart.getMaximumViewport());
v.bottom = 0;
v.top = 100;
// You have to set max and current viewports separately.
// In this case, if I want animation I have to set current viewport first and use animation listener.
// Max viewport will be set in onAnimationFinished method.
chart.setViewportAnimationListener(new ChartAnimationListener() {
@Override
public void onAnimationStarted() {
// TODO Auto-generated method stub
}
@Override
public void onAnimationFinished() {
// Set max viewpirt and remove listener.
chart.setMaximumViewport(v);
chart.setViewportAnimationListener(null);
}
});
// Set current viewpirt with animation;
chart.setCurrentViewportWithAnimation(v);
}
}
private void toggleFilled() {
isFilled = !isFilled;
generateData();
}
private void togglePointColor() {
pointsHaveDifferentColor = !pointsHaveDifferentColor;
generateData();
}
private void setCircles() {
shape = ValueShape.CIRCLE;
generateData();
}
private void setSquares() {
shape = ValueShape.SQUARE;
generateData();
}
private void setDiamonds() {
shape = ValueShape.DIAMOND;
generateData();
}
private void toggleLabels() {
hasLabels = !hasLabels;
if (hasLabels) {
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
generateData();
}
private void toggleLabelForSelected() {
hasLabelForSelected = !hasLabelForSelected;
chart.setValueSelectionEnabled(hasLabelForSelected);
if (hasLabelForSelected) {
hasLabels = false;
}
generateData();
}
private void toggleAxes() {
hasAxes = !hasAxes;
generateData();
}
private void toggleAxesNames() {
hasAxesNames = !hasAxesNames;
generateData();
}
/**
* To animate values you have to change targets values and then call {@link Chart#startDataAnimation()}
* method(don't confuse with View.animate()). If you operate on data that was set before you don't have to call
* {@link LineChartView#setLineChartData(LineChartData)} again.
*/
private void prepareDataAnimation() {
for (Line line : data.getLines()) {
for (PointValue value : line.getValues()) {
// Here I modify target only for Y values but it is OK to modify X targets as well.
value.setTarget(value.getX(), (float) Math.random() * 100);
}
}
}
private class ValueTouchListener implements LineChartOnValueSelectListener {
@Override
public void onValueSelected(int lineIndex, int pointIndex, PointValue value) {
Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onValueDeselected() {
// TODO Auto-generated method stub
}
}
}
}
@@ -0,0 +1,193 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.ColumnChartOnValueSelectListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Column;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.SubcolumnValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.ColumnChartView;
import lecho.lib.hellocharts.view.LineChartView;
public class LineColumnDependencyActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_line_column_dependency);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public final static String[] months = new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec",};
public final static String[] days = new String[]{"Mon", "Tue", "Wen", "Thu", "Fri", "Sat", "Sun",};
private LineChartView chartTop;
private ColumnChartView chartBottom;
private LineChartData lineData;
private ColumnChartData columnData;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_line_column_dependency, container, false);
// *** TOP LINE CHART ***
chartTop = (LineChartView) rootView.findViewById(R.id.chart_top);
// Generate and set data for line chart
generateInitialLineData();
// *** BOTTOM COLUMN CHART ***
chartBottom = (ColumnChartView) rootView.findViewById(R.id.chart_bottom);
generateColumnData();
return rootView;
}
private void generateColumnData() {
int numSubcolumns = 1;
int numColumns = months.length;
List<AxisValue> axisValues = new ArrayList<AxisValue>();
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50f + 5, ChartUtils.pickColor()));
}
axisValues.add(new AxisValue(i).setLabel(months[i]));
columns.add(new Column(values).setHasLabelsOnlyForSelected(true));
}
columnData = new ColumnChartData(columns);
columnData.setAxisXBottom(new Axis(axisValues).setHasLines(true));
columnData.setAxisYLeft(new Axis().setHasLines(true).setMaxLabelChars(2));
chartBottom.setColumnChartData(columnData);
// Set value touch listener that will trigger changes for chartTop.
chartBottom.setOnValueTouchListener(new ValueTouchListener());
// Set selection mode to keep selected month column highlighted.
chartBottom.setValueSelectionEnabled(true);
chartBottom.setZoomType(ZoomType.HORIZONTAL);
// chartBottom.setOnClickListener(new View.OnClickListener() {
//
// @Override
// public void onClick(View v) {
// SelectedValue sv = chartBottom.getSelectedValue();
// if (!sv.isSet()) {
// generateInitialLineData();
// }
//
// }
// });
}
/**
* Generates initial data for line chart. At the begining all Y values are equals 0. That will change when user
* will select value on column chart.
*/
private void generateInitialLineData() {
int numValues = 7;
List<AxisValue> axisValues = new ArrayList<AxisValue>();
List<PointValue> values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
values.add(new PointValue(i, 0));
axisValues.add(new AxisValue(i).setLabel(days[i]));
}
Line line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN).setCubic(true);
List<Line> lines = new ArrayList<Line>();
lines.add(line);
lineData = new LineChartData(lines);
lineData.setAxisXBottom(new Axis(axisValues).setHasLines(true));
lineData.setAxisYLeft(new Axis().setHasLines(true).setMaxLabelChars(3));
chartTop.setLineChartData(lineData);
// For build-up animation you have to disable viewport recalculation.
chartTop.setViewportCalculationEnabled(false);
// And set initial max viewport and current viewport- remember to set viewports after data.
Viewport v = new Viewport(0, 110, 6, 0);
chartTop.setMaximumViewport(v);
chartTop.setCurrentViewport(v);
chartTop.setZoomType(ZoomType.HORIZONTAL);
}
private void generateLineData(int color, float range) {
// Cancel last animation if not finished.
chartTop.cancelDataAnimation();
// Modify data targets
Line line = lineData.getLines().get(0);// For this example there is always only one line.
line.setColor(color);
for (PointValue value : line.getValues()) {
// Change target only for Y value.
value.setTarget(value.getX(), (float) Math.random() * range);
}
// Start new data animation with 300ms duration;
chartTop.startDataAnimation(300);
}
private class ValueTouchListener implements ColumnChartOnValueSelectListener {
@Override
public void onValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) {
generateLineData(value.getColor(), 100);
}
@Override
public void onValueDeselected() {
generateLineData(ChartUtils.COLOR_GREEN, 0);
}
}
}
}
@@ -0,0 +1,280 @@
package lecho.lib.hellocharts.samples;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.view.AbstractChartView;
import lecho.lib.hellocharts.view.BubbleChartView;
import lecho.lib.hellocharts.view.ColumnChartView;
import lecho.lib.hellocharts.view.LineChartView;
import lecho.lib.hellocharts.view.PieChartView;
import lecho.lib.hellocharts.view.PreviewColumnChartView;
import lecho.lib.hellocharts.view.PreviewLineChartView;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_about) {
Intent intent = new Intent(this, AboutActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
public enum ChartType {
LINE_CHART, COLUMN_CHART, PIE_CHART, BUBBLE_CHART, PREVIEW_LINE_CHART, PREVIEW_COLUMN_CHART, OTHER
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment implements OnItemClickListener {
private ListView listView;
private ChartSamplesAdapter adapter;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
adapter = new ChartSamplesAdapter(getActivity(), 0, generateSamplesDescriptions());
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
return rootView;
}
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id) {
Intent intent;
switch (position) {
case 0:
// Line Chart;
intent = new Intent(getActivity(), LineChartActivity.class);
startActivity(intent);
break;
case 1:
// Column Chart;
intent = new Intent(getActivity(), ColumnChartActivity.class);
startActivity(intent);
break;
case 2:
// Pie Chart;
intent = new Intent(getActivity(), PieChartActivity.class);
startActivity(intent);
break;
case 3:
// Bubble Chart;
intent = new Intent(getActivity(), BubbleChartActivity.class);
startActivity(intent);
break;
case 4:
// Preview Line Chart;
intent = new Intent(getActivity(), PreviewLineChartActivity.class);
startActivity(intent);
break;
case 5:
// Preview Column Chart;
intent = new Intent(getActivity(), PreviewColumnChartActivity.class);
startActivity(intent);
break;
case 6:
// Combo Chart;
intent = new Intent(getActivity(), ComboLineColumnChartActivity.class);
startActivity(intent);
break;
case 7:
// Line Column Dependency;
intent = new Intent(getActivity(), LineColumnDependencyActivity.class);
startActivity(intent);
break;
case 8:
// Tempo line chart;
intent = new Intent(getActivity(), TempoChartActivity.class);
startActivity(intent);
break;
case 9:
// Speed line chart;
intent = new Intent(getActivity(), SpeedChartActivity.class);
startActivity(intent);
break;
case 10:
// Good Bad filled line chart;
intent = new Intent(getActivity(), GoodBadChartActivity.class);
startActivity(intent);
break;
case 11:
// Good Bad filled line chart;
intent = new Intent(getActivity(), ViewPagerChartsActivity.class);
startActivity(intent);
break;
default:
break;
}
}
private List<ChartSampleDescription> generateSamplesDescriptions() {
List<ChartSampleDescription> list = new ArrayList<MainActivity.ChartSampleDescription>();
list.add(new ChartSampleDescription("Line Chart", "", ChartType.LINE_CHART));
list.add(new ChartSampleDescription("Column Chart", "", ChartType.COLUMN_CHART));
list.add(new ChartSampleDescription("Pie Chart", "", ChartType.PIE_CHART));
list.add(new ChartSampleDescription("Bubble Chart", "", ChartType.BUBBLE_CHART));
list.add(new ChartSampleDescription("Preview Line Chart",
"Control line chart viewport with another line chart.", ChartType.PREVIEW_LINE_CHART));
list.add(new ChartSampleDescription("Preview Column Chart",
"Control column chart viewport with another column chart.", ChartType.PREVIEW_COLUMN_CHART));
list.add(new ChartSampleDescription("Combo Line/Column Chart", "Combo chart with lines and columns.",
ChartType.OTHER));
list.add(new ChartSampleDescription("Line/Column Chart Dependency",
"LineChart responds(with animation) to column chart value selection.", ChartType.OTHER));
list.add(new ChartSampleDescription(
"Tempo Chart",
"Presents tempo and height values on a signle chart. Example of multiple axes and reverted Y axis" +
" with time format [mm:ss].",
ChartType.OTHER));
list.add(new ChartSampleDescription("Speed Chart",
"Presents speed and height values on a signle chart. Exapmle of multiple axes inside chart area.",
ChartType.OTHER));
list.add(new ChartSampleDescription("Good/Bad Chart",
"Example of filled area line chart with custom labels", ChartType.OTHER));
list.add(new ChartSampleDescription("ViewPager with Charts",
"Interactive charts within ViewPager. Each chart can be zoom/scroll except pie chart.",
ChartType.OTHER));
return list;
}
}
public static class ChartSamplesAdapter extends ArrayAdapter<ChartSampleDescription> {
public ChartSamplesAdapter(Context context, int resource, List<ChartSampleDescription> objects) {
super(context, resource, objects);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = View.inflate(getContext(), R.layout.list_item_sample, null);
holder = new ViewHolder();
holder.text1 = (TextView) convertView.findViewById(R.id.text1);
holder.text2 = (TextView) convertView.findViewById(R.id.text2);
holder.chartLayout = (FrameLayout) convertView.findViewById(R.id.chart_layout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ChartSampleDescription item = getItem(position);
holder.chartLayout.setVisibility(View.VISIBLE);
holder.chartLayout.removeAllViews();
AbstractChartView chart;
switch (item.chartType) {
case LINE_CHART:
chart = new LineChartView(getContext());
holder.chartLayout.addView(chart);
break;
case COLUMN_CHART:
chart = new ColumnChartView(getContext());
holder.chartLayout.addView(chart);
break;
case PIE_CHART:
chart = new PieChartView(getContext());
holder.chartLayout.addView(chart);
break;
case BUBBLE_CHART:
chart = new BubbleChartView(getContext());
holder.chartLayout.addView(chart);
break;
case PREVIEW_LINE_CHART:
chart = new PreviewLineChartView(getContext());
holder.chartLayout.addView(chart);
break;
case PREVIEW_COLUMN_CHART:
chart = new PreviewColumnChartView(getContext());
holder.chartLayout.addView(chart);
break;
default:
chart = null;
holder.chartLayout.setVisibility(View.GONE);
break;
}
if (null != chart) {
chart.setInteractive(false);// Disable touch handling for chart on the ListView.
}
holder.text1.setText(item.text1);
holder.text2.setText(item.text2);
return convertView;
}
private class ViewHolder {
TextView text1;
TextView text2;
FrameLayout chartLayout;
}
}
public static class ChartSampleDescription {
String text1;
String text2;
ChartType chartType;
public ChartSampleDescription(String text1, String text2, ChartType chartType) {
this.text1 = text1;
this.text2 = text2;
this.chartType = chartType;
}
}
}
@@ -0,0 +1,283 @@
package lecho.lib.hellocharts.samples;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.listener.PieChartOnValueSelectListener;
import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.model.SliceValue;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.Chart;
import lecho.lib.hellocharts.view.PieChartView;
public class PieChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pie_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a pie chart.
*/
public static class PlaceholderFragment extends Fragment {
private PieChartView chart;
private PieChartData data;
private boolean hasLabels = false;
private boolean hasLabelsOutside = false;
private boolean hasCenterCircle = false;
private boolean hasCenterText1 = false;
private boolean hasCenterText2 = false;
private boolean isExploded = false;
private boolean hasLabelForSelected = false;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_pie_chart, container, false);
chart = (PieChartView) rootView.findViewById(R.id.chart);
chart.setOnValueTouchListener(new ValueTouchListener());
generateData();
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.pie_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
reset();
generateData();
return true;
}
if (id == R.id.action_explode) {
explodeChart();
return true;
}
if (id == R.id.action_center_circle) {
hasCenterCircle = !hasCenterCircle;
if (!hasCenterCircle) {
hasCenterText1 = false;
hasCenterText2 = false;
}
generateData();
return true;
}
if (id == R.id.action_center_text1) {
hasCenterText1 = !hasCenterText1;
if (hasCenterText1) {
hasCenterCircle = true;
}
hasCenterText2 = false;
generateData();
return true;
}
if (id == R.id.action_center_text2) {
hasCenterText2 = !hasCenterText2;
if (hasCenterText2) {
hasCenterText1 = true;// text 2 need text 1 to by also drawn.
hasCenterCircle = true;
}
generateData();
return true;
}
if (id == R.id.action_toggle_labels) {
toggleLabels();
return true;
}
if (id == R.id.action_toggle_labels_outside) {
toggleLabelsOutside();
return true;
}
if (id == R.id.action_animate) {
prepareDataAnimation();
chart.startDataAnimation();
return true;
}
if (id == R.id.action_toggle_selection_mode) {
toggleLabelForSelected();
Toast.makeText(getActivity(),
"Selection mode set to " + chart.isValueSelectionEnabled() + " select any point.",
Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
private void reset() {
chart.setCircleFillRatio(1.0f);
hasLabels = false;
hasLabelsOutside = false;
hasCenterCircle = false;
hasCenterText1 = false;
hasCenterText2 = false;
isExploded = false;
hasLabelForSelected = false;
}
private void generateData() {
int numValues = 6;
List<SliceValue> values = new ArrayList<SliceValue>();
for (int i = 0; i < numValues; ++i) {
SliceValue sliceValue = new SliceValue((float) Math.random() * 30 + 15, ChartUtils.pickColor());
values.add(sliceValue);
}
data = new PieChartData(values);
data.setHasLabels(hasLabels);
data.setHasLabelsOnlyForSelected(hasLabelForSelected);
data.setHasLabelsOutside(hasLabelsOutside);
data.setHasCenterCircle(hasCenterCircle);
if (isExploded) {
data.setSlicesSpacing(24);
}
if (hasCenterText1) {
data.setCenterText1("Hello!");
// Get roboto-italic font.
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "Roboto-Italic.ttf");
data.setCenterText1Typeface(tf);
// Get font size from dimens.xml and convert it to sp(library uses sp values).
data.setCenterText1FontSize(ChartUtils.px2sp(getResources().getDisplayMetrics().scaledDensity,
(int) getResources().getDimension(R.dimen.pie_chart_text1_size)));
}
if (hasCenterText2) {
data.setCenterText2("Charts (Roboto Italic)");
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "Roboto-Italic.ttf");
data.setCenterText2Typeface(tf);
data.setCenterText2FontSize(ChartUtils.px2sp(getResources().getDisplayMetrics().scaledDensity,
(int) getResources().getDimension(R.dimen.pie_chart_text2_size)));
}
chart.setPieChartData(data);
}
private void explodeChart() {
isExploded = !isExploded;
generateData();
}
private void toggleLabelsOutside() {
// has labels have to be true:P
hasLabelsOutside = !hasLabelsOutside;
if (hasLabelsOutside) {
hasLabels = true;
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
}
if (hasLabelsOutside) {
chart.setCircleFillRatio(0.7f);
} else {
chart.setCircleFillRatio(1.0f);
}
generateData();
}
private void toggleLabels() {
hasLabels = !hasLabels;
if (hasLabels) {
hasLabelForSelected = false;
chart.setValueSelectionEnabled(hasLabelForSelected);
if (hasLabelsOutside) {
chart.setCircleFillRatio(0.7f);
} else {
chart.setCircleFillRatio(1.0f);
}
}
generateData();
}
private void toggleLabelForSelected() {
hasLabelForSelected = !hasLabelForSelected;
chart.setValueSelectionEnabled(hasLabelForSelected);
if (hasLabelForSelected) {
hasLabels = false;
hasLabelsOutside = false;
if (hasLabelsOutside) {
chart.setCircleFillRatio(0.7f);
} else {
chart.setCircleFillRatio(1.0f);
}
}
generateData();
}
/**
* To animate values you have to change targets values and then call {@link Chart#startDataAnimation()}
* method(don't confuse with View.animate()).
*/
private void prepareDataAnimation() {
for (SliceValue value : data.getValues()) {
value.setTarget((float) Math.random() * 30 + 15);
}
}
private class ValueTouchListener implements PieChartOnValueSelectListener {
@Override
public void onValueSelected(int arcIndex, SliceValue value) {
Toast.makeText(getActivity(), "Selected: " + value, Toast.LENGTH_SHORT).show();
}
@Override
public void onValueDeselected() {
// TODO Auto-generated method stub
}
}
}
}
@@ -0,0 +1,194 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.ViewportChangeListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Column;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.SubcolumnValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.ColumnChartView;
import lecho.lib.hellocharts.view.PreviewColumnChartView;
public class PreviewColumnChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preview_column_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
private ColumnChartView chart;
private PreviewColumnChartView previewChart;
private ColumnChartData data;
/**
* Deep copy of data.
*/
private ColumnChartData previewData;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_preview_column_chart, container, false);
chart = (ColumnChartView) rootView.findViewById(R.id.chart);
previewChart = (PreviewColumnChartView) rootView.findViewById(R.id.chart_preview);
// Generate data for previewed chart and copy of that data for preview chart.
generateDefaultData();
chart.setColumnChartData(data);
// Disable zoom/scroll for previewed chart, visible chart ranges depends on preview chart viewport so
// zoom/scroll is unnecessary.
chart.setZoomEnabled(false);
chart.setScrollEnabled(false);
previewChart.setColumnChartData(previewData);
previewChart.setViewportChangeListener(new ViewportListener());
previewX(false);
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.preview_column_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
generateDefaultData();
chart.setColumnChartData(data);
previewChart.setColumnChartData(previewData);
previewX(true);
return true;
}
if (id == R.id.action_preview_both) {
previewXY();
previewChart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
return true;
}
if (id == R.id.action_preview_horizontal) {
previewX(true);
return true;
}
if (id == R.id.action_preview_vertical) {
previewY();
return true;
}
if (id == R.id.action_change_color) {
int color = ChartUtils.pickColor();
while (color == previewChart.getPreviewColor()) {
color = ChartUtils.pickColor();
}
previewChart.setPreviewColor(color);
return true;
}
return super.onOptionsItemSelected(item);
}
private void generateDefaultData() {
int numSubcolumns = 1;
int numColumns = 50;
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50f + 5, ChartUtils.pickColor()));
}
columns.add(new Column(values));
}
data = new ColumnChartData(columns);
data.setAxisXBottom(new Axis());
data.setAxisYLeft(new Axis().setHasLines(true));
// prepare preview data, is better to use separate deep copy for preview chart.
// set color to grey to make preview area more visible.
previewData = new ColumnChartData(data);
for (Column column : previewData.getColumns()) {
for (SubcolumnValue value : column.getValues()) {
value.setColor(ChartUtils.DEFAULT_DARKEN_COLOR);
}
}
}
private void previewY() {
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
float dy = tempViewport.height() / 4;
tempViewport.inset(0, dy);
previewChart.setCurrentViewportWithAnimation(tempViewport);
previewChart.setZoomType(ZoomType.VERTICAL);
}
private void previewX(boolean animate) {
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
float dx = tempViewport.width() / 4;
tempViewport.inset(dx, 0);
if (animate) {
previewChart.setCurrentViewportWithAnimation(tempViewport);
} else {
previewChart.setCurrentViewport(tempViewport);
}
previewChart.setZoomType(ZoomType.HORIZONTAL);
}
private void previewXY() {
// Better to not modify viewport of any chart directly so create a copy.
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
// Make temp viewport smaller.
float dx = tempViewport.width() / 4;
float dy = tempViewport.height() / 4;
tempViewport.inset(dx, dy);
previewChart.setCurrentViewportWithAnimation(tempViewport);
}
/**
* Viewport listener for preview chart(lower one). in {@link #onViewportChanged(Viewport)} method change
* viewport of upper chart.
*/
private class ViewportListener implements ViewportChangeListener {
@Override
public void onViewportChanged(Viewport newViewport) {
// don't use animation, it is unnecessary when using preview chart because usually viewport changes
// happens to often.
chart.setCurrentViewport(newViewport);
}
}
}
}
@@ -0,0 +1,190 @@
package lecho.lib.hellocharts.samples;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.listener.ViewportChangeListener;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.LineChartView;
import lecho.lib.hellocharts.view.PreviewLineChartView;
public class PreviewLineChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preview_line_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
/**
* A fragment containing a line chart and preview line chart.
*/
public static class PlaceholderFragment extends Fragment {
private LineChartView chart;
private PreviewLineChartView previewChart;
private LineChartData data;
/**
* Deep copy of data.
*/
private LineChartData previewData;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.fragment_preview_line_chart, container, false);
chart = (LineChartView) rootView.findViewById(R.id.chart);
previewChart = (PreviewLineChartView) rootView.findViewById(R.id.chart_preview);
// Generate data for previewed chart and copy of that data for preview chart.
generateDefaultData();
chart.setLineChartData(data);
// Disable zoom/scroll for previewed chart, visible chart ranges depends on preview chart viewport so
// zoom/scroll is unnecessary.
chart.setZoomEnabled(false);
chart.setScrollEnabled(false);
previewChart.setLineChartData(previewData);
previewChart.setViewportChangeListener(new ViewportListener());
previewX(false);
return rootView;
}
// MENU
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.preview_line_chart, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_reset) {
generateDefaultData();
chart.setLineChartData(data);
previewChart.setLineChartData(previewData);
previewX(true);
return true;
}
if (id == R.id.action_preview_both) {
previewXY();
previewChart.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
return true;
}
if (id == R.id.action_preview_horizontal) {
previewX(true);
return true;
}
if (id == R.id.action_preview_vertical) {
previewY();
return true;
}
if (id == R.id.action_change_color) {
int color = ChartUtils.pickColor();
while (color == previewChart.getPreviewColor()) {
color = ChartUtils.pickColor();
}
previewChart.setPreviewColor(color);
return true;
}
return super.onOptionsItemSelected(item);
}
private void generateDefaultData() {
int numValues = 50;
List<PointValue> values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
values.add(new PointValue(i, (float) Math.random() * 100f));
}
Line line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN);
line.setHasPoints(false);// too many values so don't draw points.
List<Line> lines = new ArrayList<Line>();
lines.add(line);
data = new LineChartData(lines);
data.setAxisXBottom(new Axis());
data.setAxisYLeft(new Axis().setHasLines(true));
// prepare preview data, is better to use separate deep copy for preview chart.
// Set color to grey to make preview area more visible.
previewData = new LineChartData(data);
previewData.getLines().get(0).setColor(ChartUtils.DEFAULT_DARKEN_COLOR);
}
private void previewY() {
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
float dy = tempViewport.height() / 4;
tempViewport.inset(0, dy);
previewChart.setCurrentViewportWithAnimation(tempViewport);
previewChart.setZoomType(ZoomType.VERTICAL);
}
private void previewX(boolean animate) {
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
float dx = tempViewport.width() / 4;
tempViewport.inset(dx, 0);
if (animate) {
previewChart.setCurrentViewportWithAnimation(tempViewport);
} else {
previewChart.setCurrentViewport(tempViewport);
}
previewChart.setZoomType(ZoomType.HORIZONTAL);
}
private void previewXY() {
// Better to not modify viewport of any chart directly so create a copy.
Viewport tempViewport = new Viewport(chart.getMaximumViewport());
// Make temp viewport smaller.
float dx = tempViewport.width() / 4;
float dy = tempViewport.height() / 4;
tempViewport.inset(dx, dy);
previewChart.setCurrentViewportWithAnimation(tempViewport);
}
/**
* Viewport listener for preview chart(lower one). in {@link #onViewportChanged(Viewport)} method change
* viewport of upper chart.
*/
private class ViewportListener implements ViewportChangeListener {
@Override
public void onViewportChanged(Viewport newViewport) {
// don't use animation, it is unnecessary when using preview chart.
chart.setCurrentViewport(newViewport);
}
}
}
}
@@ -0,0 +1,158 @@
package lecho.lib.hellocharts.samples;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.formatter.SimpleAxisValueFormatter;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.LineChartView;
public class SpeedChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tempo_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
public static class PlaceholderFragment extends Fragment {
private LineChartView chart;
private LineChartData data;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tempo_chart, container, false);
chart = (LineChartView) rootView.findViewById(R.id.chart);
generateSpeedData();
return rootView;
}
private void generateSpeedData() {
// I got speed in range (0-55) and height in meters in range(200 - 300). I want this chart to display both
// information. Differences between speed and height values are large and chart doesn't look good so I need
// to modify height values to be in range of speed values.
float speedRange = 55;
float minHeight = 200;
float maxHeight = 300;
float scale = speedRange / maxHeight;
float sub = (minHeight * scale) / 2;
int numValues = 52;
Line line;
List<PointValue> values;
List<Line> lines = new ArrayList<Line>();
// Height line, add it as first line to be drawn in the background.
values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
// Some random height values, add +200 to make line a little more natural
float rawHeight = (float) (Math.random() * 100 + 200);
float normalizedHeight = rawHeight * scale - sub;
values.add(new PointValue(i, normalizedHeight));
}
line = new Line(values);
line.setColor(Color.GRAY);
line.setHasPoints(false);
line.setFilled(true);
line.setStrokeWidth(1);
lines.add(line);
// Speed line
values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
// Some random speed values, add +20 to make line a little more natural.
values.add(new PointValue(i, (float) Math.random() * 30 + 20));
}
line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN);
line.setHasPoints(false);
line.setStrokeWidth(3);
lines.add(line);
// Data and axes
data = new LineChartData(lines);
// Distance axis(bottom X) with formatter that will ad [km] to values, remember to modify max label charts
// value.
Axis distanceAxis = new Axis();
distanceAxis.setName("Distance");
distanceAxis.setTextColor(ChartUtils.COLOR_ORANGE);
distanceAxis.setMaxLabelChars(4);
distanceAxis.setFormatter(new SimpleAxisValueFormatter().setAppendedText("km".toCharArray()));
distanceAxis.setHasLines(true);
distanceAxis.setInside(true);
data.setAxisXBottom(distanceAxis);
// Speed axis
data.setAxisYLeft(new Axis().setName("Speed [km/h]").setHasLines(true).setMaxLabelChars(3)
.setTextColor(ChartUtils.COLOR_RED).setInside(true));
// Height axis, this axis need custom formatter that will translate values back to real height values.
data.setAxisYRight(new Axis().setName("Height [m]").setMaxLabelChars(3).setTextColor(ChartUtils.COLOR_BLUE)
.setFormatter(new HeightValueFormatter(scale, sub, 0)).setInside(true));
// Set data
chart.setLineChartData(data);
// Important: adjust viewport, you could skip this step but in this case it will looks better with custom
// viewport. Set
// viewport with Y range 0-55;
Viewport v = chart.getMaximumViewport();
v.set(v.left, speedRange, v.right, 0);
chart.setMaximumViewport(v);
chart.setCurrentViewport(v);
}
/**
* Recalculated height values to display on axis.
*/
private static class HeightValueFormatter extends SimpleAxisValueFormatter {
private float scale;
private float sub;
private int decimalDigits;
public HeightValueFormatter(float scale, float sub, int decimalDigits) {
this.scale = scale;
this.sub = sub;
this.decimalDigits = decimalDigits;
}
@Override
public int formatValueForAutoGeneratedAxis(char[] formattedValue, float value, int autoDecimalDigits) {
float scaledValue = (value + sub) / scale;
return super.formatValueForAutoGeneratedAxis(formattedValue, scaledValue, this.decimalDigits);
}
}
}
}
@@ -0,0 +1,194 @@
package lecho.lib.hellocharts.samples;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.formatter.SimpleAxisValueFormatter;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.AxisValue;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.LineChartView;
public class TempoChartActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tempo_chart);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment()).commit();
}
}
public static class PlaceholderFragment extends Fragment {
private LineChartView chart;
private LineChartData data;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_tempo_chart, container, false);
chart = (LineChartView) rootView.findViewById(R.id.chart);
generateTempoData();
return rootView;
}
private void generateTempoData() {
// I got speed in range (0-50) and height in meters in range(200 - 300). I want this chart to display both
// information. Differences between speed and height values are large and chart doesn't look good so I need
// to modify height values to be in range of speed values.
// The same for displaying Tempo/Height chart.
float minHeight = 200;
float maxHeight = 300;
float tempoRange = 15; // from 0min/km to 15min/km
float scale = tempoRange / maxHeight;
float sub = (minHeight * scale) / 2;
int numValues = 52;
Line line;
List<PointValue> values;
List<Line> lines = new ArrayList<Line>();
// Height line, add it as first line to be drawn in the background.
values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
// Some random height values, add +200 to make line a little more natural
float rawHeight = (float) (Math.random() * 100 + 200);
float normalizedHeight = rawHeight * scale - sub;
values.add(new PointValue(i, normalizedHeight));
}
line = new Line(values);
line.setColor(Color.GRAY);
line.setHasPoints(false);
line.setFilled(true);
line.setStrokeWidth(1);
lines.add(line);
// Tempo line is a little tricky because worse tempo means bigger value for example 11min per km is worse
// than 2min per km but the second should be higher on the chart. So you need to know max tempo and
// tempoRange and set
// chart values to minTempo - realTempo.
values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
// Some random raw tempo values.
float realTempo = (float) Math.random() * 6 + 2;
float revertedTempo = tempoRange - realTempo;
values.add(new PointValue(i, revertedTempo));
}
line = new Line(values);
line.setColor(ChartUtils.COLOR_RED);
line.setHasPoints(false);
line.setStrokeWidth(3);
lines.add(line);
// Data and axes
data = new LineChartData(lines);
// Distance axis(bottom X) with formatter that will ad [km] to values, remember to modify max label charts
// value.
Axis distanceAxis = new Axis();
distanceAxis.setName("Distance");
distanceAxis.setTextColor(ChartUtils.COLOR_ORANGE);
distanceAxis.setMaxLabelChars(4);
distanceAxis.setFormatter(new SimpleAxisValueFormatter().setAppendedText("km".toCharArray()));
distanceAxis.setHasLines(true);
distanceAxis.setHasTiltedLabels(true);
data.setAxisXBottom(distanceAxis);
// Tempo uses minutes so I can't use auto-generated axis because auto-generation works only for decimal
// system. So generate custom axis values for example every 15 seconds and set custom labels in format
// minutes:seconds(00:00), you could do it in formatter but here will be faster.
List<AxisValue> axisValues = new ArrayList<AxisValue>();
for (float i = 0; i < tempoRange; i += 0.25f) {
// I'am translating float to minutes because I don't have data in minutes, if You store some time data
// you may skip translation.
axisValues.add(new AxisValue(i).setLabel(formatMinutes(tempoRange - i)));
}
Axis tempoAxis = new Axis(axisValues).setName("Tempo [min/km]").setHasLines(true).setMaxLabelChars(4)
.setTextColor(ChartUtils.COLOR_RED);
data.setAxisYLeft(tempoAxis);
// *** Same as in Speed/Height chart.
// Height axis, this axis need custom formatter that will translate values back to real height values.
data.setAxisYRight(new Axis().setName("Height [m]").setMaxLabelChars(3)
.setFormatter(new HeightValueFormatter(scale, sub, 0)));
// Set data
chart.setLineChartData(data);
// Important: adjust viewport, you could skip this step but in this case it will looks better with custom
// viewport. Set
// viewport with Y range 0-12;
Viewport v = chart.getMaximumViewport();
v.set(v.left, tempoRange, v.right, 0);
chart.setMaximumViewport(v);
chart.setCurrentViewport(v);
}
private String formatMinutes(float value) {
StringBuilder sb = new StringBuilder();
// translate value to seconds, for example
int valueInSeconds = (int) (value * 60);
int minutes = (int) Math.floor(valueInSeconds / 60);
int seconds = (int) valueInSeconds % 60;
sb.append(String.valueOf(minutes)).append(':');
if (seconds < 10) {
sb.append('0');
}
sb.append(String.valueOf(seconds));
return sb.toString();
}
/**
* Recalculated height values to display on axis. For this example I use auto-generated height axis so I
* override only formatAutoValue method.
*/
private static class HeightValueFormatter extends SimpleAxisValueFormatter {
private float scale;
private float sub;
private int decimalDigits;
public HeightValueFormatter(float scale, float sub, int decimalDigits) {
this.scale = scale;
this.sub = sub;
this.decimalDigits = decimalDigits;
}
@Override
public int formatValueForAutoGeneratedAxis(char[] formattedValue, float value, int autoDecimalDigits) {
float scaledValue = (value + sub) / scale;
return super.formatValueForAutoGeneratedAxis(formattedValue, scaledValue, this.decimalDigits);
}
}
}
}
@@ -0,0 +1,332 @@
package lecho.lib.hellocharts.samples;
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.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
import lecho.lib.hellocharts.gesture.ContainerScrollType;
import lecho.lib.hellocharts.gesture.ZoomType;
import lecho.lib.hellocharts.model.Axis;
import lecho.lib.hellocharts.model.BubbleChartData;
import lecho.lib.hellocharts.model.BubbleValue;
import lecho.lib.hellocharts.model.Column;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.Line;
import lecho.lib.hellocharts.model.LineChartData;
import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.model.PointValue;
import lecho.lib.hellocharts.model.SliceValue;
import lecho.lib.hellocharts.model.SubcolumnValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.BubbleChartView;
import lecho.lib.hellocharts.view.ColumnChartView;
import lecho.lib.hellocharts.view.LineChartView;
import lecho.lib.hellocharts.view.PieChartView;
import lecho.lib.hellocharts.view.PreviewLineChartView;
public class ViewPagerChartsActivity extends ActionBarActivity implements ActionBar.TabListener {
/**
* The {@link android.support.v4.view.PagerAdapter} that will provide fragments for each of the sections. We use a
* {@link FragmentPagerAdapter} derivative, which will keep every loaded fragment in memory. If this becomes too
* memory intensive, it may be best to switch to a {@link android.support.v4.app.FragmentStatePagerAdapter}.
*/
SectionsPagerAdapter mSectionsPagerAdapter;
/**
* The {@link ViewPager} that will host the section contents.
*/
ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager_charts);
// Set up the action bar.
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
// When swiping between different sections, select the corresponding
// tab. We can also use ActionBar.Tab#select() to do this if we have
// a reference to the Tab.
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
// Create a tab with text corresponding to the page title defined by
// the adapter. Also specify this Activity object, which implements
// the TabListener interface, as the callback (listener) for when
// this tab is selected.
actionBar.addTab(actionBar.newTab().setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this));
}
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
mViewPager.setCurrentItem(tab.getPosition());
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_view_pager_charts, container, false);
RelativeLayout layout = (RelativeLayout) rootView;
int sectionNum = getArguments().getInt(ARG_SECTION_NUMBER);
switch (sectionNum) {
case 1:
LineChartView lineChartView = new LineChartView(getActivity());
lineChartView.setLineChartData(generateLineChartData());
lineChartView.setZoomType(ZoomType.HORIZONTAL);
/** Note: Chart is within ViewPager so enable container scroll mode. **/
lineChartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
layout.addView(lineChartView);
break;
case 2:
ColumnChartView columnChartView = new ColumnChartView(getActivity());
columnChartView.setColumnChartData(generateColumnChartData());
columnChartView.setZoomType(ZoomType.HORIZONTAL);
/** Note: Chart is within ViewPager so enable container scroll mode. **/
columnChartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
layout.addView(columnChartView);
break;
case 3:
BubbleChartView bubbleChartView = new BubbleChartView(getActivity());
bubbleChartView.setBubbleChartData(generateBubbleChartData());
bubbleChartView.setZoomType(ZoomType.HORIZONTAL_AND_VERTICAL);
/** Note: Chart is within ViewPager so enable container scroll mode. **/
bubbleChartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
layout.addView(bubbleChartView);
break;
case 4:
PreviewLineChartView previewLineChartView = new PreviewLineChartView(getActivity());
previewLineChartView.setLineChartData(generatePreviewLineChartData());
/** Note: Chart is within ViewPager so enable container scroll mode. **/
previewLineChartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
Viewport tempViewport = new Viewport(previewLineChartView.getMaximumViewport());
float dx = tempViewport.width() / 6;
tempViewport.inset(dx, 0);
previewLineChartView.setCurrentViewport(tempViewport);
previewLineChartView.setZoomType(ZoomType.HORIZONTAL);
layout.addView(previewLineChartView);
break;
case 5:
PieChartView pieChartView = new PieChartView(getActivity());
pieChartView.setPieChartData(generatePieChartData());
/** Note: Chart is within ViewPager so enable container scroll mode. **/
pieChartView.setContainerScrollEnabled(true, ContainerScrollType.HORIZONTAL);
layout.addView(pieChartView);
break;
}
return rootView;
}
private LineChartData generateLineChartData() {
int numValues = 20;
List<PointValue> values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
values.add(new PointValue(i, (float) Math.random() * 100f));
}
Line line = new Line(values);
line.setColor(ChartUtils.COLOR_GREEN);
List<Line> lines = new ArrayList<Line>();
lines.add(line);
LineChartData data = new LineChartData(lines);
data.setAxisXBottom(new Axis().setName("Axis X"));
data.setAxisYLeft(new Axis().setName("Axis Y").setHasLines(true));
return data;
}
private ColumnChartData generateColumnChartData() {
int numSubcolumns = 1;
int numColumns = 12;
// Column can have many subcolumns, here by default I use 1 subcolumn in each of 8 columns.
List<Column> columns = new ArrayList<Column>();
List<SubcolumnValue> values;
for (int i = 0; i < numColumns; ++i) {
values = new ArrayList<SubcolumnValue>();
for (int j = 0; j < numSubcolumns; ++j) {
values.add(new SubcolumnValue((float) Math.random() * 50f + 5, ChartUtils.pickColor()));
}
columns.add(new Column(values));
}
ColumnChartData data = new ColumnChartData(columns);
data.setAxisXBottom(new Axis().setName("Axis X"));
data.setAxisYLeft(new Axis().setName("Axis Y").setHasLines(true));
return data;
}
private BubbleChartData generateBubbleChartData() {
int numBubbles = 10;
List<BubbleValue> values = new ArrayList<BubbleValue>();
for (int i = 0; i < numBubbles; ++i) {
BubbleValue value = new BubbleValue(i, (float) Math.random() * 100, (float) Math.random() * 1000);
value.setColor(ChartUtils.pickColor());
values.add(value);
}
BubbleChartData data = new BubbleChartData(values);
data.setAxisXBottom(new Axis().setName("Axis X"));
data.setAxisYLeft(new Axis().setName("Axis Y").setHasLines(true));
return data;
}
private LineChartData generatePreviewLineChartData() {
int numValues = 50;
List<PointValue> values = new ArrayList<PointValue>();
for (int i = 0; i < numValues; ++i) {
values.add(new PointValue(i, (float) Math.random() * 100f));
}
Line line = new Line(values);
line.setColor(ChartUtils.DEFAULT_DARKEN_COLOR);
line.setHasPoints(false);// too many values so don't draw points.
List<Line> lines = new ArrayList<Line>();
lines.add(line);
LineChartData data = new LineChartData(lines);
data.setAxisXBottom(new Axis());
data.setAxisYLeft(new Axis().setHasLines(true));
return data;
}
private PieChartData generatePieChartData() {
int numValues = 6;
List<SliceValue> values = new ArrayList<SliceValue>();
for (int i = 0; i < numValues; ++i) {
values.add(new SliceValue((float) Math.random() * 30 + 15, ChartUtils.pickColor()));
}
PieChartData data = new PieChartData(values);
return data;
}
}
/**
* A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
@Override
public int getCount() {
return 5;
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "LineChart";
case 1:
return "ColumnChart";
case 2:
return "BubbleChart";
case 3:
return "PreviewLineChart";
case 4:
return "PieChart";
}
return null;
}
}
}