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.view.Menu; 12 import android.view.MenuItem; 13 import android.view.WindowManager; 14 import android.widget.SeekBar; 15 import android.widget.SeekBar.OnSeekBarChangeListener; 16 import android.widget.TextView; 17 18 import com.github.mikephil.charting.charts.LineChart; 19 import com.github.mikephil.charting.components.AxisBase; 20 import com.github.mikephil.charting.components.Legend; 21 import com.github.mikephil.charting.components.XAxis; 22 import com.github.mikephil.charting.components.YAxis; 23 import com.github.mikephil.charting.components.YAxis.AxisDependency; 24 import com.github.mikephil.charting.data.Entry; 25 import com.github.mikephil.charting.data.LineData; 26 import com.github.mikephil.charting.data.LineDataSet; 27 import com.github.mikephil.charting.formatter.IAxisValueFormatter; 28 import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; 29 import com.github.mikephil.charting.utils.ColorTemplate; 30 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 31 32 import java.text.SimpleDateFormat; 33 import java.util.ArrayList; 34 import java.util.Date; 35 import java.util.List; 36 import java.util.Locale; 37 import java.util.concurrent.TimeUnit; 38 39 public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { 40 41 private LineChart chart; 42 private SeekBar seekBarX; 43 private TextView tvX; 44 45 @Override onCreate(Bundle savedInstanceState)46 protected void onCreate(Bundle savedInstanceState) { 47 super.onCreate(savedInstanceState); 48 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 49 WindowManager.LayoutParams.FLAG_FULLSCREEN); 50 setContentView(R.layout.activity_linechart_time); 51 52 setTitle("LineChartTime"); 53 54 tvX = findViewById(R.id.tvXMax); 55 seekBarX = findViewById(R.id.seekBar1); 56 seekBarX.setOnSeekBarChangeListener(this); 57 58 chart = findViewById(R.id.chart1); 59 60 // no description text 61 chart.getDescription().setEnabled(false); 62 63 // enable touch gestures 64 chart.setTouchEnabled(true); 65 66 chart.setDragDecelerationFrictionCoef(0.9f); 67 68 // enable scaling and dragging 69 chart.setDragEnabled(true); 70 chart.setScaleEnabled(true); 71 chart.setDrawGridBackground(false); 72 chart.setHighlightPerDragEnabled(true); 73 74 // set an alternative background color 75 chart.setBackgroundColor(Color.WHITE); 76 chart.setViewPortOffsets(0f, 0f, 0f, 0f); 77 78 // add data 79 seekBarX.setProgress(100); 80 81 // get the legend (only possible after setting data) 82 Legend l = chart.getLegend(); 83 l.setEnabled(false); 84 85 XAxis xAxis = chart.getXAxis(); 86 xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); 87 xAxis.setTypeface(tfLight); 88 xAxis.setTextSize(10f); 89 xAxis.setTextColor(Color.WHITE); 90 xAxis.setDrawAxisLine(false); 91 xAxis.setDrawGridLines(true); 92 xAxis.setTextColor(Color.rgb(255, 192, 56)); 93 xAxis.setCenterAxisLabels(true); 94 xAxis.setGranularity(1f); // one hour 95 xAxis.setValueFormatter(new IAxisValueFormatter() { 96 97 private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); 98 99 @Override 100 public String getFormattedValue(float value, AxisBase axis) { 101 102 long millis = TimeUnit.HOURS.toMillis((long) value); 103 return mFormat.format(new Date(millis)); 104 } 105 }); 106 107 YAxis leftAxis = chart.getAxisLeft(); 108 leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); 109 leftAxis.setTypeface(tfLight); 110 leftAxis.setTextColor(ColorTemplate.getHoloBlue()); 111 leftAxis.setDrawGridLines(true); 112 leftAxis.setGranularityEnabled(true); 113 leftAxis.setAxisMinimum(0f); 114 leftAxis.setAxisMaximum(170f); 115 leftAxis.setYOffset(-9f); 116 leftAxis.setTextColor(Color.rgb(255, 192, 56)); 117 118 YAxis rightAxis = chart.getAxisRight(); 119 rightAxis.setEnabled(false); 120 } 121 setData(int count, float range)122 private void setData(int count, float range) { 123 124 // now in hours 125 long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); 126 127 ArrayList<Entry> values = new ArrayList<>(); 128 129 // count = hours 130 float to = now + count; 131 132 // increment by 1 hour 133 for (float x = now; x < to; x++) { 134 135 float y = getRandom(range, 50); 136 values.add(new Entry(x, y)); // add one entry per hour 137 } 138 139 // create a dataset and give it a type 140 LineDataSet set1 = new LineDataSet(values, "DataSet 1"); 141 set1.setAxisDependency(AxisDependency.LEFT); 142 set1.setColor(ColorTemplate.getHoloBlue()); 143 set1.setValueTextColor(ColorTemplate.getHoloBlue()); 144 set1.setLineWidth(1.5f); 145 set1.setDrawCircles(false); 146 set1.setDrawValues(false); 147 set1.setFillAlpha(65); 148 set1.setFillColor(ColorTemplate.getHoloBlue()); 149 set1.setHighLightColor(Color.rgb(244, 117, 117)); 150 set1.setDrawCircleHole(false); 151 152 // create a data object with the data sets 153 LineData data = new LineData(set1); 154 data.setValueTextColor(Color.WHITE); 155 data.setValueTextSize(9f); 156 157 // set data 158 chart.setData(data); 159 } 160 161 @Override onCreateOptionsMenu(Menu menu)162 public boolean onCreateOptionsMenu(Menu menu) { 163 getMenuInflater().inflate(R.menu.line, menu); 164 return true; 165 } 166 167 @Override onOptionsItemSelected(MenuItem item)168 public boolean onOptionsItemSelected(MenuItem item) { 169 170 switch (item.getItemId()) { 171 case R.id.viewGithub: { 172 Intent i = new Intent(Intent.ACTION_VIEW); 173 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java")); 174 startActivity(i); 175 break; 176 } 177 case R.id.actionToggleValues: { 178 List<ILineDataSet> sets = chart.getData() 179 .getDataSets(); 180 181 for (ILineDataSet iSet : sets) { 182 183 LineDataSet set = (LineDataSet) iSet; 184 set.setDrawValues(!set.isDrawValuesEnabled()); 185 } 186 187 chart.invalidate(); 188 break; 189 } 190 case R.id.actionToggleHighlight: { 191 if (chart.getData() != null) { 192 chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); 193 chart.invalidate(); 194 } 195 break; 196 } 197 case R.id.actionToggleFilled: { 198 199 List<ILineDataSet> sets = chart.getData() 200 .getDataSets(); 201 202 for (ILineDataSet iSet : sets) { 203 204 LineDataSet set = (LineDataSet) iSet; 205 if (set.isDrawFilledEnabled()) 206 set.setDrawFilled(false); 207 else 208 set.setDrawFilled(true); 209 } 210 chart.invalidate(); 211 break; 212 } 213 case R.id.actionToggleCircles: { 214 List<ILineDataSet> sets = chart.getData() 215 .getDataSets(); 216 217 for (ILineDataSet iSet : sets) { 218 219 LineDataSet set = (LineDataSet) iSet; 220 if (set.isDrawCirclesEnabled()) 221 set.setDrawCircles(false); 222 else 223 set.setDrawCircles(true); 224 } 225 chart.invalidate(); 226 break; 227 } 228 case R.id.actionToggleCubic: { 229 List<ILineDataSet> sets = chart.getData() 230 .getDataSets(); 231 232 for (ILineDataSet iSet : sets) { 233 234 LineDataSet set = (LineDataSet) iSet; 235 if (set.getMode() == LineDataSet.Mode.CUBIC_BEZIER) 236 set.setMode(LineDataSet.Mode.LINEAR); 237 else 238 set.setMode(LineDataSet.Mode.CUBIC_BEZIER); 239 } 240 chart.invalidate(); 241 break; 242 } 243 case R.id.actionToggleStepped: { 244 List<ILineDataSet> sets = chart.getData() 245 .getDataSets(); 246 247 for (ILineDataSet iSet : sets) { 248 249 LineDataSet set = (LineDataSet) iSet; 250 if (set.getMode() == LineDataSet.Mode.STEPPED) 251 set.setMode(LineDataSet.Mode.LINEAR); 252 else 253 set.setMode(LineDataSet.Mode.STEPPED); 254 } 255 chart.invalidate(); 256 break; 257 } 258 case R.id.actionTogglePinch: { 259 if (chart.isPinchZoomEnabled()) 260 chart.setPinchZoom(false); 261 else 262 chart.setPinchZoom(true); 263 264 chart.invalidate(); 265 break; 266 } 267 case R.id.actionToggleAutoScaleMinMax: { 268 chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); 269 chart.notifyDataSetChanged(); 270 break; 271 } 272 case R.id.animateX: { 273 chart.animateX(2000); 274 break; 275 } 276 case R.id.animateY: { 277 chart.animateY(2000); 278 break; 279 } 280 case R.id.animateXY: { 281 chart.animateXY(2000, 2000); 282 break; 283 } 284 285 case R.id.actionSave: { 286 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 287 saveToGallery(); 288 } else { 289 requestStoragePermission(chart); 290 } 291 break; 292 } 293 } 294 return true; 295 } 296 297 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)298 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 299 300 tvX.setText(String.valueOf(seekBarX.getProgress())); 301 302 setData(seekBarX.getProgress(), 50); 303 304 // redraw 305 chart.invalidate(); 306 } 307 308 @Override saveToGallery()309 protected void saveToGallery() { 310 saveToGallery(chart, "LineChartTime"); 311 } 312 313 @Override onStartTrackingTouch(SeekBar seekBar)314 public void onStartTrackingTouch(SeekBar seekBar) {} 315 316 @Override onStopTrackingTouch(SeekBar seekBar)317 public void onStopTrackingTouch(SeekBar seekBar) {} 318 } 319