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.graphics.Color; 8 import android.net.Uri; 9 import android.os.Bundle; 10 import androidx.core.content.ContextCompat; 11 import android.util.Log; 12 import android.view.Menu; 13 import android.view.MenuItem; 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.components.Legend.LegendForm; 22 import com.github.mikephil.charting.components.XAxis; 23 import com.github.mikephil.charting.components.YAxis; 24 import com.github.mikephil.charting.components.YAxis.AxisDependency; 25 import com.github.mikephil.charting.data.Entry; 26 import com.github.mikephil.charting.data.LineData; 27 import com.github.mikephil.charting.data.LineDataSet; 28 import com.github.mikephil.charting.highlight.Highlight; 29 import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; 30 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 31 import com.github.mikephil.charting.utils.ColorTemplate; 32 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 37 /** 38 * Example of a dual axis {@link LineChart} with multiple data sets. 39 * 40 * @since 1.7.4 41 * @version 3.1.0 42 */ 43 public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, 44 OnChartValueSelectedListener { 45 46 private LineChart chart; 47 private SeekBar seekBarX, seekBarY; 48 private TextView tvX, tvY; 49 50 @Override onCreate(Bundle savedInstanceState)51 protected void onCreate(Bundle savedInstanceState) { 52 super.onCreate(savedInstanceState); 53 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 54 WindowManager.LayoutParams.FLAG_FULLSCREEN); 55 setContentView(R.layout.activity_linechart); 56 57 setTitle("LineChartActivity2"); 58 59 tvX = findViewById(R.id.tvXMax); 60 tvY = findViewById(R.id.tvYMax); 61 62 seekBarX = findViewById(R.id.seekBar1); 63 seekBarX.setOnSeekBarChangeListener(this); 64 65 seekBarY = findViewById(R.id.seekBar2); 66 seekBarY.setOnSeekBarChangeListener(this); 67 68 chart = findViewById(R.id.chart1); 69 chart.setOnChartValueSelectedListener(this); 70 71 // no description text 72 chart.getDescription().setEnabled(false); 73 74 // enable touch gestures 75 chart.setTouchEnabled(true); 76 77 chart.setDragDecelerationFrictionCoef(0.9f); 78 79 // enable scaling and dragging 80 chart.setDragEnabled(true); 81 chart.setScaleEnabled(true); 82 chart.setDrawGridBackground(false); 83 chart.setHighlightPerDragEnabled(true); 84 85 // if disabled, scaling can be done on x- and y-axis separately 86 chart.setPinchZoom(true); 87 88 // set an alternative background color 89 chart.setBackgroundColor(Color.LTGRAY); 90 91 // add data 92 seekBarX.setProgress(20); 93 seekBarY.setProgress(30); 94 95 chart.animateX(1500); 96 97 // get the legend (only possible after setting data) 98 Legend l = chart.getLegend(); 99 100 // modify the legend ... 101 l.setForm(LegendForm.LINE); 102 l.setTypeface(tfLight); 103 l.setTextSize(11f); 104 l.setTextColor(Color.WHITE); 105 l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); 106 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); 107 l.setOrientation(Legend.LegendOrientation.HORIZONTAL); 108 l.setDrawInside(false); 109 // l.setYOffset(11f); 110 111 XAxis xAxis = chart.getXAxis(); 112 xAxis.setTypeface(tfLight); 113 xAxis.setTextSize(11f); 114 xAxis.setTextColor(Color.WHITE); 115 xAxis.setDrawGridLines(false); 116 xAxis.setDrawAxisLine(false); 117 118 YAxis leftAxis = chart.getAxisLeft(); 119 leftAxis.setTypeface(tfLight); 120 leftAxis.setTextColor(ColorTemplate.getHoloBlue()); 121 leftAxis.setAxisMaximum(200f); 122 leftAxis.setAxisMinimum(0f); 123 leftAxis.setDrawGridLines(true); 124 leftAxis.setGranularityEnabled(true); 125 126 YAxis rightAxis = chart.getAxisRight(); 127 rightAxis.setTypeface(tfLight); 128 rightAxis.setTextColor(Color.RED); 129 rightAxis.setAxisMaximum(900); 130 rightAxis.setAxisMinimum(-200); 131 rightAxis.setDrawGridLines(false); 132 rightAxis.setDrawZeroLine(false); 133 rightAxis.setGranularityEnabled(false); 134 } 135 setData(int count, float range)136 private void setData(int count, float range) { 137 138 ArrayList<Entry> values1 = new ArrayList<>(); 139 140 for (int i = 0; i < count; i++) { 141 float val = (float) (Math.random() * (range / 2f)) + 50; 142 values1.add(new Entry(i, val)); 143 } 144 145 ArrayList<Entry> values2 = new ArrayList<>(); 146 147 for (int i = 0; i < count; i++) { 148 float val = (float) (Math.random() * range) + 450; 149 values2.add(new Entry(i, val)); 150 } 151 152 ArrayList<Entry> values3 = new ArrayList<>(); 153 154 for (int i = 0; i < count; i++) { 155 float val = (float) (Math.random() * range) + 500; 156 values3.add(new Entry(i, val)); 157 } 158 159 LineDataSet set1, set2, set3; 160 161 if (chart.getData() != null && 162 chart.getData().getDataSetCount() > 0) { 163 set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); 164 set2 = (LineDataSet) chart.getData().getDataSetByIndex(1); 165 set3 = (LineDataSet) chart.getData().getDataSetByIndex(2); 166 set1.setValues(values1); 167 set2.setValues(values2); 168 set3.setValues(values3); 169 chart.getData().notifyDataChanged(); 170 chart.notifyDataSetChanged(); 171 } else { 172 // create a dataset and give it a type 173 set1 = new LineDataSet(values1, "DataSet 1"); 174 175 set1.setAxisDependency(AxisDependency.LEFT); 176 set1.setColor(ColorTemplate.getHoloBlue()); 177 set1.setCircleColor(Color.WHITE); 178 set1.setLineWidth(2f); 179 set1.setCircleRadius(3f); 180 set1.setFillAlpha(65); 181 set1.setFillColor(ColorTemplate.getHoloBlue()); 182 set1.setHighLightColor(Color.rgb(244, 117, 117)); 183 set1.setDrawCircleHole(false); 184 //set1.setFillFormatter(new MyFillFormatter(0f)); 185 //set1.setDrawHorizontalHighlightIndicator(false); 186 //set1.setVisible(false); 187 //set1.setCircleHoleColor(Color.WHITE); 188 189 // create a dataset and give it a type 190 set2 = new LineDataSet(values2, "DataSet 2"); 191 set2.setAxisDependency(AxisDependency.RIGHT); 192 set2.setColor(Color.RED); 193 set2.setCircleColor(Color.WHITE); 194 set2.setLineWidth(2f); 195 set2.setCircleRadius(3f); 196 set2.setFillAlpha(65); 197 set2.setFillColor(Color.RED); 198 set2.setDrawCircleHole(false); 199 set2.setHighLightColor(Color.rgb(244, 117, 117)); 200 //set2.setFillFormatter(new MyFillFormatter(900f)); 201 202 set3 = new LineDataSet(values3, "DataSet 3"); 203 set3.setAxisDependency(AxisDependency.RIGHT); 204 set3.setColor(Color.YELLOW); 205 set3.setCircleColor(Color.WHITE); 206 set3.setLineWidth(2f); 207 set3.setCircleRadius(3f); 208 set3.setFillAlpha(65); 209 set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); 210 set3.setDrawCircleHole(false); 211 set3.setHighLightColor(Color.rgb(244, 117, 117)); 212 213 // create a data object with the data sets 214 LineData data = new LineData(set1, set2, set3); 215 data.setValueTextColor(Color.WHITE); 216 data.setValueTextSize(9f); 217 218 // set data 219 chart.setData(data); 220 } 221 } 222 223 @Override onCreateOptionsMenu(Menu menu)224 public boolean onCreateOptionsMenu(Menu menu) { 225 getMenuInflater().inflate(R.menu.line, menu); 226 return true; 227 } 228 229 @Override onOptionsItemSelected(MenuItem item)230 public boolean onOptionsItemSelected(MenuItem item) { 231 232 switch (item.getItemId()) { 233 case R.id.viewGithub: { 234 Intent i = new Intent(Intent.ACTION_VIEW); 235 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java")); 236 startActivity(i); 237 break; 238 } 239 case R.id.actionToggleValues: { 240 List<ILineDataSet> sets = chart.getData() 241 .getDataSets(); 242 243 for (ILineDataSet iSet : sets) { 244 245 LineDataSet set = (LineDataSet) iSet; 246 set.setDrawValues(!set.isDrawValuesEnabled()); 247 } 248 249 chart.invalidate(); 250 break; 251 } 252 case R.id.actionToggleHighlight: { 253 if (chart.getData() != null) { 254 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 255 chart.invalidate(); 256 } 257 break; 258 } 259 case R.id.actionToggleFilled: { 260 261 List<ILineDataSet> sets = chart.getData() 262 .getDataSets(); 263 264 for (ILineDataSet iSet : sets) { 265 266 LineDataSet set = (LineDataSet) iSet; 267 if (set.isDrawFilledEnabled()) 268 set.setDrawFilled(false); 269 else 270 set.setDrawFilled(true); 271 } 272 chart.invalidate(); 273 break; 274 } 275 case R.id.actionToggleCircles: { 276 List<ILineDataSet> sets = chart.getData() 277 .getDataSets(); 278 279 for (ILineDataSet iSet : sets) { 280 281 LineDataSet set = (LineDataSet) iSet; 282 if (set.isDrawCirclesEnabled()) 283 set.setDrawCircles(false); 284 else 285 set.setDrawCircles(true); 286 } 287 chart.invalidate(); 288 break; 289 } 290 case R.id.actionToggleCubic: { 291 List<ILineDataSet> sets = chart.getData() 292 .getDataSets(); 293 294 for (ILineDataSet iSet : sets) { 295 296 LineDataSet set = (LineDataSet) iSet; 297 set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER 298 ? LineDataSet.Mode.LINEAR 299 : LineDataSet.Mode.CUBIC_BEZIER); 300 } 301 chart.invalidate(); 302 break; 303 } 304 case R.id.actionToggleStepped: { 305 List<ILineDataSet> sets = chart.getData() 306 .getDataSets(); 307 308 for (ILineDataSet iSet : sets) { 309 310 LineDataSet set = (LineDataSet) iSet; 311 set.setMode(set.getMode() == LineDataSet.Mode.STEPPED 312 ? LineDataSet.Mode.LINEAR 313 : LineDataSet.Mode.STEPPED); 314 } 315 chart.invalidate(); 316 break; 317 } 318 case R.id.actionToggleHorizontalCubic: { 319 List<ILineDataSet> sets = chart.getData() 320 .getDataSets(); 321 322 for (ILineDataSet iSet : sets) { 323 324 LineDataSet set = (LineDataSet) iSet; 325 set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER 326 ? LineDataSet.Mode.LINEAR 327 : LineDataSet.Mode.HORIZONTAL_BEZIER); 328 } 329 chart.invalidate(); 330 break; 331 } 332 case R.id.actionTogglePinch: { 333 if (chart.isPinchZoomEnabled()) 334 chart.setPinchZoom(false); 335 else 336 chart.setPinchZoom(true); 337 338 chart.invalidate(); 339 break; 340 } 341 case R.id.actionToggleAutoScaleMinMax: { 342 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 343 chart.notifyDataSetChanged(); 344 break; 345 } 346 case R.id.animateX: { 347 chart.animateX(2000); 348 break; 349 } 350 case R.id.animateY: { 351 chart.animateY(2000); 352 break; 353 } 354 case R.id.animateXY: { 355 chart.animateXY(2000, 2000); 356 break; 357 } 358 case R.id.actionSave: { 359 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 360 saveToGallery(); 361 } else { 362 requestStoragePermission(chart); 363 } 364 break; 365 } 366 } 367 return true; 368 } 369 370 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)371 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 372 373 tvX.setText(String.valueOf(seekBarX.getProgress())); 374 tvY.setText(String.valueOf(seekBarY.getProgress())); 375 376 setData(seekBarX.getProgress(), seekBarY.getProgress()); 377 378 // redraw 379 chart.invalidate(); 380 } 381 382 @Override saveToGallery()383 protected void saveToGallery() { 384 saveToGallery(chart, "LineChartActivity2"); 385 } 386 387 @Override onValueSelected(Entry e, Highlight h)388 public void onValueSelected(Entry e, Highlight h) { 389 Log.i("Entry selected", e.toString()); 390 391 chart.centerViewToAnimated(e.getX(), e.getY(), chart.getData().getDataSetByIndex(h.getDataSetIndex()) 392 .getAxisDependency(), 500); 393 //chart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) 394 // .getAxisDependency(), 1000); 395 //chart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) 396 // .getAxisDependency(), 1000); 397 } 398 399 @Override onNothingSelected()400 public void onNothingSelected() { 401 Log.i("Nothing selected", "Nothing selected."); 402 } 403 404 @Override onStartTrackingTouch(SeekBar seekBar)405 public void onStartTrackingTouch(SeekBar seekBar) {} 406 407 @Override onStopTrackingTouch(SeekBar seekBar)408 public void onStopTrackingTouch(SeekBar seekBar) {} 409 } 410