1 2 package com.xxmassdeveloper.mpchartexample; 3 4 import android.Manifest; 5 import android.content.Intent; 6 import android.content.pm.PackageManager; 7 import android.net.Uri; 8 import android.os.Bundle; 9 import androidx.core.content.ContextCompat; 10 import android.util.Log; 11 import android.view.Menu; 12 import android.view.MenuItem; 13 import android.view.MotionEvent; 14 import android.view.WindowManager; 15 import android.widget.SeekBar; 16 import android.widget.SeekBar.OnSeekBarChangeListener; 17 import android.widget.TextView; 18 19 import com.github.mikephil.charting.charts.LineChart; 20 import com.github.mikephil.charting.components.Legend; 21 import com.github.mikephil.charting.data.Entry; 22 import com.github.mikephil.charting.data.LineData; 23 import com.github.mikephil.charting.data.LineDataSet; 24 import com.github.mikephil.charting.highlight.Highlight; 25 import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; 26 import com.github.mikephil.charting.listener.ChartTouchListener; 27 import com.github.mikephil.charting.listener.OnChartGestureListener; 28 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 29 import com.github.mikephil.charting.utils.ColorTemplate; 30 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 31 32 import java.util.ArrayList; 33 import java.util.List; 34 35 public class MultiLineChartActivity extends DemoBase implements OnSeekBarChangeListener, 36 OnChartGestureListener, OnChartValueSelectedListener { 37 38 private LineChart chart; 39 private SeekBar seekBarX, seekBarY; 40 private TextView tvX, tvY; 41 42 @Override onCreate(Bundle savedInstanceState)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_linechart); 48 49 setTitle("MultiLineChartActivity"); 50 51 tvX = findViewById(R.id.tvXMax); 52 tvY = findViewById(R.id.tvYMax); 53 54 seekBarX = findViewById(R.id.seekBar1); 55 seekBarX.setOnSeekBarChangeListener(this); 56 57 seekBarY = findViewById(R.id.seekBar2); 58 seekBarY.setOnSeekBarChangeListener(this); 59 60 chart = findViewById(R.id.chart1); 61 chart.setOnChartValueSelectedListener(this); 62 63 chart.setDrawGridBackground(false); 64 chart.getDescription().setEnabled(false); 65 chart.setDrawBorders(false); 66 67 chart.getAxisLeft().setEnabled(false); 68 chart.getAxisRight().setDrawAxisLine(false); 69 chart.getAxisRight().setDrawGridLines(false); 70 chart.getXAxis().setDrawAxisLine(false); 71 chart.getXAxis().setDrawGridLines(false); 72 73 // enable touch gestures 74 chart.setTouchEnabled(true); 75 76 // enable scaling and dragging 77 chart.setDragEnabled(true); 78 chart.setScaleEnabled(true); 79 80 // if disabled, scaling can be done on x- and y-axis separately 81 chart.setPinchZoom(false); 82 83 seekBarX.setProgress(20); 84 seekBarY.setProgress(100); 85 86 Legend l = chart.getLegend(); 87 l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); 88 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); 89 l.setOrientation(Legend.LegendOrientation.VERTICAL); 90 l.setDrawInside(false); 91 } 92 93 private final int[] colors = new int[] { 94 ColorTemplate.VORDIPLOM_COLORS[0], 95 ColorTemplate.VORDIPLOM_COLORS[1], 96 ColorTemplate.VORDIPLOM_COLORS[2] 97 }; 98 99 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)100 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 101 102 chart.resetTracking(); 103 104 progress = seekBarX.getProgress(); 105 106 tvX.setText(String.valueOf(seekBarX.getProgress())); 107 tvY.setText(String.valueOf(seekBarY.getProgress())); 108 109 ArrayList<ILineDataSet> dataSets = new ArrayList<>(); 110 111 for (int z = 0; z < 3; z++) { 112 113 ArrayList<Entry> values = new ArrayList<>(); 114 115 for (int i = 0; i < progress; i++) { 116 double val = (Math.random() * seekBarY.getProgress()) + 3; 117 values.add(new Entry(i, (float) val)); 118 } 119 120 LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); 121 d.setLineWidth(2.5f); 122 d.setCircleRadius(4f); 123 124 int color = colors[z % colors.length]; 125 d.setColor(color); 126 d.setCircleColor(color); 127 dataSets.add(d); 128 } 129 130 // make the first DataSet dashed 131 ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); 132 ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); 133 ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); 134 135 LineData data = new LineData(dataSets); 136 chart.setData(data); 137 chart.invalidate(); 138 } 139 140 @Override onCreateOptionsMenu(Menu menu)141 public boolean onCreateOptionsMenu(Menu menu) { 142 getMenuInflater().inflate(R.menu.line, menu); 143 menu.removeItem(R.id.actionToggleIcons); 144 return true; 145 } 146 147 @Override onOptionsItemSelected(MenuItem item)148 public boolean onOptionsItemSelected(MenuItem item) { 149 150 switch (item.getItemId()) { 151 case R.id.viewGithub: { 152 Intent i = new Intent(Intent.ACTION_VIEW); 153 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java")); 154 startActivity(i); 155 break; 156 } 157 case R.id.actionToggleValues: { 158 List<ILineDataSet> sets = chart.getData() 159 .getDataSets(); 160 161 for (ILineDataSet iSet : sets) { 162 163 LineDataSet set = (LineDataSet) iSet; 164 set.setDrawValues(!set.isDrawValuesEnabled()); 165 } 166 167 chart.invalidate(); 168 break; 169 } 170 /* 171 case R.id.actionToggleIcons: { break; } 172 */ 173 case R.id.actionTogglePinch: { 174 if (chart.isPinchZoomEnabled()) 175 chart.setPinchZoom(false); 176 else 177 chart.setPinchZoom(true); 178 179 chart.invalidate(); 180 break; 181 } 182 case R.id.actionToggleAutoScaleMinMax: { 183 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 184 chart.notifyDataSetChanged(); 185 break; 186 } 187 case R.id.actionToggleHighlight: { 188 if(chart.getData() != null) { 189 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 190 chart.invalidate(); 191 } 192 break; 193 } 194 case R.id.actionToggleFilled: { 195 List<ILineDataSet> sets = chart.getData() 196 .getDataSets(); 197 198 for (ILineDataSet iSet : sets) { 199 200 LineDataSet set = (LineDataSet) iSet; 201 if (set.isDrawFilledEnabled()) 202 set.setDrawFilled(false); 203 else 204 set.setDrawFilled(true); 205 } 206 chart.invalidate(); 207 break; 208 } 209 case R.id.actionToggleCircles: { 210 List<ILineDataSet> sets = chart.getData() 211 .getDataSets(); 212 213 for (ILineDataSet iSet : sets) { 214 215 LineDataSet set = (LineDataSet) iSet; 216 if (set.isDrawCirclesEnabled()) 217 set.setDrawCircles(false); 218 else 219 set.setDrawCircles(true); 220 } 221 chart.invalidate(); 222 break; 223 } 224 case R.id.actionToggleCubic: { 225 List<ILineDataSet> sets = chart.getData() 226 .getDataSets(); 227 228 for (ILineDataSet iSet : sets) { 229 230 LineDataSet set = (LineDataSet) iSet; 231 set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER 232 ? LineDataSet.Mode.LINEAR 233 : LineDataSet.Mode.CUBIC_BEZIER); 234 } 235 chart.invalidate(); 236 break; 237 } 238 case R.id.actionToggleStepped: { 239 List<ILineDataSet> sets = chart.getData() 240 .getDataSets(); 241 242 for (ILineDataSet iSet : sets) { 243 244 LineDataSet set = (LineDataSet) iSet; 245 set.setMode(set.getMode() == LineDataSet.Mode.STEPPED 246 ? LineDataSet.Mode.LINEAR 247 : LineDataSet.Mode.STEPPED); 248 } 249 chart.invalidate(); 250 break; 251 } 252 case R.id.actionToggleHorizontalCubic: { 253 List<ILineDataSet> sets = chart.getData() 254 .getDataSets(); 255 256 for (ILineDataSet iSet : sets) { 257 258 LineDataSet set = (LineDataSet) iSet; 259 set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER 260 ? LineDataSet.Mode.LINEAR 261 : LineDataSet.Mode.HORIZONTAL_BEZIER); 262 } 263 chart.invalidate(); 264 break; 265 } 266 case R.id.actionSave: { 267 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 268 saveToGallery(); 269 } else { 270 requestStoragePermission(chart); 271 } 272 break; 273 } 274 case R.id.animateX: { 275 chart.animateX(2000); 276 break; 277 } 278 case R.id.animateY: { 279 chart.animateY(2000); 280 break; 281 } 282 case R.id.animateXY: { 283 chart.animateXY(2000, 2000); 284 break; 285 } 286 } 287 return true; 288 } 289 290 @Override saveToGallery()291 protected void saveToGallery() { 292 saveToGallery(chart, "MultiLineChartActivity"); 293 } 294 295 @Override onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture)296 public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { 297 Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); 298 } 299 300 @Override onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture)301 public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { 302 Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); 303 304 // un-highlight values after the gesture is finished and no single-tap 305 if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) 306 chart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) 307 } 308 309 @Override onChartLongPressed(MotionEvent me)310 public void onChartLongPressed(MotionEvent me) { 311 Log.i("LongPress", "Chart long pressed."); 312 } 313 314 @Override onChartDoubleTapped(MotionEvent me)315 public void onChartDoubleTapped(MotionEvent me) { 316 Log.i("DoubleTap", "Chart double-tapped."); 317 } 318 319 @Override onChartSingleTapped(MotionEvent me)320 public void onChartSingleTapped(MotionEvent me) { 321 Log.i("SingleTap", "Chart single-tapped."); 322 } 323 324 @Override onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY)325 public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { 326 Log.i("Fling", "Chart fling. VelocityX: " + velocityX + ", VelocityY: " + velocityY); 327 } 328 329 @Override onChartScale(MotionEvent me, float scaleX, float scaleY)330 public void onChartScale(MotionEvent me, float scaleX, float scaleY) { 331 Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); 332 } 333 334 @Override onChartTranslate(MotionEvent me, float dX, float dY)335 public void onChartTranslate(MotionEvent me, float dX, float dY) { 336 Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); 337 } 338 339 @Override onValueSelected(Entry e, Highlight h)340 public void onValueSelected(Entry e, Highlight h) { 341 Log.i("VAL SELECTED", 342 "Value: " + e.getY() + ", xIndex: " + e.getX() 343 + ", DataSet index: " + h.getDataSetIndex()); 344 } 345 346 @Override onNothingSelected()347 public void onNothingSelected() {} 348 349 @Override onStartTrackingTouch(SeekBar seekBar)350 public void onStartTrackingTouch(SeekBar seekBar) {} 351 352 @Override onStopTrackingTouch(SeekBar seekBar)353 public void onStopTrackingTouch(SeekBar seekBar) {} 354 } 355