Skip to content

Commit 9a2d5fc

Browse files
committed
Bubble chart implementation, ported from the iOS version :-)
1 parent 24a3b1c commit 9a2d5fc

12 files changed

Lines changed: 957 additions & 16 deletions

File tree

MPChartExample/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
<activity android:name="BarChartActivityMultiDataset"></activity>
3535
<activity android:name="DrawChartActivity"></activity>
3636
<activity android:name="ScatterChartActivity"></activity>
37+
<activity android:name="BubbleChartActivity"></activity>
3738
<activity android:name="com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo"></activity>
3839
<activity android:name="ListViewBarChartActivity"></activity>
3940
<activity android:name="ListViewMultiChartActivity"></activity>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3+
android:layout_width="match_parent"
4+
android:layout_height="match_parent" >
5+
6+
<com.github.mikephil.charting.charts.BubbleChart
7+
android:id="@+id/chart1"
8+
android:layout_width="match_parent"
9+
android:layout_height="match_parent"
10+
android:layout_above="@+id/seekBar1" />
11+
12+
<SeekBar
13+
android:id="@+id/seekBar2"
14+
android:layout_width="match_parent"
15+
android:layout_height="wrap_content"
16+
android:layout_alignParentBottom="true"
17+
android:layout_alignParentLeft="true"
18+
android:layout_margin="8dp"
19+
android:layout_toLeftOf="@+id/tvYMax"
20+
android:layout_marginRight="5dp"
21+
android:max="200"
22+
android:paddingBottom="12dp" />
23+
24+
<SeekBar
25+
android:id="@+id/seekBar1"
26+
android:layout_width="match_parent"
27+
android:layout_height="wrap_content"
28+
android:layout_above="@+id/seekBar2"
29+
android:layout_margin="8dp"
30+
android:layout_marginBottom="35dp"
31+
android:layout_toLeftOf="@+id/tvXMax"
32+
android:layout_marginRight="5dp"
33+
android:max="30"
34+
android:paddingBottom="12dp" />
35+
36+
<TextView
37+
android:id="@+id/tvXMax"
38+
android:layout_width="50dp"
39+
android:layout_height="wrap_content"
40+
android:layout_alignBottom="@+id/seekBar1"
41+
android:layout_alignParentRight="true"
42+
android:text="500"
43+
android:layout_marginBottom="15dp"
44+
android:layout_marginRight="10dp"
45+
android:gravity="right"
46+
android:textAppearance="?android:attr/textAppearanceMedium" />
47+
48+
<TextView
49+
android:id="@+id/tvYMax"
50+
android:layout_width="50dp"
51+
android:layout_height="wrap_content"
52+
android:layout_alignBottom="@+id/seekBar2"
53+
android:layout_alignParentRight="true"
54+
android:text="500"
55+
android:layout_marginBottom="15dp"
56+
android:layout_marginRight="10dp"
57+
android:gravity="right"
58+
android:textAppearance="?android:attr/textAppearanceMedium" />
59+
60+
</RelativeLayout>

MPChartExample/res/menu/bubble.xml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
3+
4+
<item
5+
android:id="@+id/actionToggleValues"
6+
android:title="Toggle Values">
7+
</item>
8+
<item
9+
android:id="@+id/actionToggleHighlight"
10+
android:title="Toggle Highlight">
11+
</item>
12+
<item
13+
android:id="@+id/actionToggleStartzero"
14+
android:title="Toggle StartZero">
15+
</item>
16+
<item
17+
android:id="@+id/actionToggleAdjustXLegend"
18+
android:title="Toggle AdjustXLegend">
19+
</item>
20+
<item
21+
android:id="@+id/animateX"
22+
android:title="Animate X">
23+
</item>
24+
<item
25+
android:id="@+id/animateY"
26+
android:title="Animate Y">
27+
</item>
28+
<item
29+
android:id="@+id/animateXY"
30+
android:title="Animate XY">
31+
</item>
32+
<item
33+
android:id="@+id/actionToggleFilter"
34+
android:title="Toggle filter">
35+
</item>
36+
<item
37+
android:id="@+id/actionSave"
38+
android:title="Save to Gallery">
39+
</item>
40+
<item
41+
android:id="@+id/actionTogglePinch"
42+
android:title="Toggle PinchZoom">
43+
</item>
44+
45+
</menu>
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
2+
package com.xxmassdeveloper.mpchartexample;
3+
4+
import android.graphics.Typeface;
5+
import android.os.Bundle;
6+
import android.util.Log;
7+
import android.view.Menu;
8+
import android.view.MenuItem;
9+
import android.view.WindowManager;
10+
import android.widget.SeekBar;
11+
import android.widget.SeekBar.OnSeekBarChangeListener;
12+
import android.widget.TextView;
13+
14+
import com.github.mikephil.charting.charts.BubbleChart;
15+
import com.github.mikephil.charting.components.Legend;
16+
import com.github.mikephil.charting.components.Legend.LegendPosition;
17+
import com.github.mikephil.charting.components.XAxis;
18+
import com.github.mikephil.charting.components.YAxis;
19+
import com.github.mikephil.charting.data.BubbleEntry;
20+
import com.github.mikephil.charting.data.DataSet;
21+
import com.github.mikephil.charting.data.Entry;
22+
import com.github.mikephil.charting.data.BubbleData;
23+
import com.github.mikephil.charting.data.BubbleDataSet;
24+
import com.github.mikephil.charting.data.filter.Approximator;
25+
import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType;
26+
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
27+
import com.github.mikephil.charting.utils.ColorTemplate;
28+
import com.github.mikephil.charting.utils.Highlight;
29+
import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;
30+
31+
import java.util.ArrayList;
32+
33+
public class BubbleChartActivity extends DemoBase implements OnSeekBarChangeListener,
34+
OnChartValueSelectedListener {
35+
36+
private BubbleChart mChart;
37+
private SeekBar mSeekBarX, mSeekBarY;
38+
private TextView tvX, tvY;
39+
40+
private Typeface tf;
41+
42+
@Override
43+
protected void onCreate(Bundle savedInstanceState) {
44+
super.onCreate(savedInstanceState);
45+
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
46+
WindowManager.LayoutParams.FLAG_FULLSCREEN);
47+
setContentView(R.layout.activity_bubblechart);
48+
49+
tvX = (TextView) findViewById(R.id.tvXMax);
50+
tvY = (TextView) findViewById(R.id.tvYMax);
51+
52+
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
53+
mSeekBarX.setOnSeekBarChangeListener(this);
54+
55+
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
56+
mSeekBarY.setOnSeekBarChangeListener(this);
57+
58+
mChart = (BubbleChart) findViewById(R.id.chart1);
59+
mChart.setDescription("");
60+
61+
tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf");
62+
63+
mChart.setOnChartValueSelectedListener(this);
64+
65+
mChart.setDrawGridBackground(false);
66+
67+
mChart.setTouchEnabled(true);
68+
mChart.setHighlightEnabled(true);
69+
70+
// enable scaling and dragging
71+
mChart.setDragEnabled(true);
72+
mChart.setScaleEnabled(true);
73+
74+
mChart.setMaxVisibleValueCount(200);
75+
mChart.setPinchZoom(true);
76+
77+
mChart.getAxisLeft().setStartAtZero(false);
78+
mChart.getAxisRight().setStartAtZero(false);
79+
80+
mSeekBarX.setProgress(5);
81+
mSeekBarY.setProgress(50);
82+
83+
Legend l = mChart.getLegend();
84+
l.setPosition(LegendPosition.RIGHT_OF_CHART);
85+
l.setTypeface(tf);
86+
87+
YAxis yl = mChart.getAxisLeft();
88+
yl.setTypeface(tf);
89+
90+
mChart.getAxisRight().setEnabled(false);
91+
92+
XAxis xl = mChart.getXAxis();
93+
xl.setPosition(XAxis.XAxisPosition.BOTTOM);
94+
xl.setTypeface(tf);
95+
}
96+
97+
@Override
98+
public boolean onCreateOptionsMenu(Menu menu) {
99+
getMenuInflater().inflate(R.menu.bubble, menu);
100+
return true;
101+
}
102+
103+
@Override
104+
public boolean onOptionsItemSelected(MenuItem item) {
105+
106+
switch (item.getItemId()) {
107+
case R.id.actionToggleValues: {
108+
for (DataSet<?> set : mChart.getData().getDataSets())
109+
set.setDrawValues(!set.isDrawValuesEnabled());
110+
111+
mChart.invalidate();
112+
break;
113+
}
114+
case R.id.actionToggleHighlight: {
115+
if (mChart.isHighlightEnabled())
116+
mChart.setHighlightEnabled(false);
117+
else
118+
mChart.setHighlightEnabled(true);
119+
mChart.invalidate();
120+
break;
121+
}
122+
case R.id.actionTogglePinch: {
123+
if (mChart.isPinchZoomEnabled())
124+
mChart.setPinchZoom(false);
125+
else
126+
mChart.setPinchZoom(true);
127+
128+
mChart.invalidate();
129+
break;
130+
}
131+
case R.id.actionToggleStartzero: {
132+
mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled());
133+
mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled());
134+
mChart.invalidate();
135+
break;
136+
}
137+
case R.id.actionToggleFilter: {
138+
139+
Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25);
140+
141+
if (!mChart.isFilteringEnabled()) {
142+
mChart.enableFiltering(a);
143+
} else {
144+
mChart.disableFiltering();
145+
}
146+
mChart.invalidate();
147+
break;
148+
}
149+
case R.id.actionSave: {
150+
// mChart.saveToGallery("title"+System.currentTimeMillis());
151+
mChart.saveToPath("title" + System.currentTimeMillis(), "");
152+
break;
153+
}
154+
case R.id.animateX: {
155+
mChart.animateX(3000);
156+
break;
157+
}
158+
case R.id.animateY: {
159+
mChart.animateY(3000);
160+
break;
161+
}
162+
case R.id.animateXY: {
163+
164+
mChart.animateXY(3000, 3000);
165+
break;
166+
}
167+
}
168+
return true;
169+
}
170+
171+
@Override
172+
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
173+
174+
int count = mSeekBarX.getProgress() + 1;
175+
int range = mSeekBarY.getProgress();
176+
177+
tvX.setText("" + count);
178+
tvY.setText("" + range);
179+
180+
ArrayList<String> xVals = new ArrayList<String>();
181+
for (int i = 0; i < count; i++) {
182+
xVals.add((i) + "");
183+
}
184+
185+
ArrayList<BubbleEntry> yVals1 = new ArrayList<BubbleEntry>();
186+
ArrayList<BubbleEntry> yVals2 = new ArrayList<BubbleEntry>();
187+
ArrayList<BubbleEntry> yVals3 = new ArrayList<BubbleEntry>();
188+
189+
for (int i = 0; i < count; i++) {
190+
float val = (float) (Math.random() * range);
191+
float size = (float) (Math.random() * range);
192+
193+
yVals1.add(new BubbleEntry(i, val, size));
194+
}
195+
196+
for (int i = 0; i < count; i++) {
197+
float val = (float) (Math.random() * range);
198+
float size = (float) (Math.random() * range);
199+
200+
yVals2.add(new BubbleEntry(i, val, size));
201+
}
202+
203+
for (int i = 0; i < count; i++) {
204+
float val = (float) (Math.random() * range);
205+
float size = (float) (Math.random() * range);
206+
207+
yVals3.add(new BubbleEntry(i, val, size));
208+
}
209+
210+
// create a dataset and give it a type
211+
BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1");
212+
set1.setColor(ColorTemplate.COLORFUL_COLORS[0]);
213+
set1.setDrawValues(true);
214+
BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2");
215+
set2.setColor(ColorTemplate.COLORFUL_COLORS[1]);
216+
set2.setDrawValues(false);
217+
BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3");
218+
set3.setColor(ColorTemplate.COLORFUL_COLORS[2]);
219+
set3.setDrawValues(false);
220+
221+
ArrayList<BubbleDataSet> dataSets = new ArrayList<BubbleDataSet>();
222+
dataSets.add(set1); // add the datasets
223+
dataSets.add(set2);
224+
dataSets.add(set3);
225+
226+
// create a data object with the datasets
227+
BubbleData data = new BubbleData(xVals, dataSets);
228+
data.setValueTypeface(tf);
229+
230+
mChart.setData(data);
231+
mChart.invalidate();
232+
}
233+
234+
@Override
235+
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
236+
Log.i("VAL SELECTED",
237+
"Value: " + e.getVal() + ", xIndex: " + e.getXIndex()
238+
+ ", DataSet index: " + dataSetIndex);
239+
}
240+
241+
@Override
242+
public void onNothingSelected() {
243+
// TODO Auto-generated method stub
244+
245+
}
246+
247+
@Override
248+
public void onStartTrackingTouch(SeekBar seekBar) {
249+
// TODO Auto-generated method stub
250+
251+
}
252+
253+
@Override
254+
public void onStopTrackingTouch(SeekBar seekBar) {
255+
// TODO Auto-generated method stub
256+
257+
}
258+
}

0 commit comments

Comments
 (0)