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.graphics.Typeface; 9 import android.net.Uri; 10 import android.os.Bundle; 11 import androidx.core.content.ContextCompat; 12 import android.text.SpannableString; 13 import android.text.style.ForegroundColorSpan; 14 import android.text.style.RelativeSizeSpan; 15 import android.text.style.StyleSpan; 16 import android.util.Log; 17 import android.view.Menu; 18 import android.view.MenuItem; 19 import android.view.WindowManager; 20 import android.widget.SeekBar; 21 import android.widget.SeekBar.OnSeekBarChangeListener; 22 import android.widget.TextView; 23 24 import com.github.mikephil.charting.animation.Easing; 25 import com.github.mikephil.charting.charts.PieChart; 26 import com.github.mikephil.charting.components.Legend; 27 import com.github.mikephil.charting.data.Entry; 28 import com.github.mikephil.charting.data.PieData; 29 import com.github.mikephil.charting.data.PieDataSet; 30 import com.github.mikephil.charting.data.PieEntry; 31 import com.github.mikephil.charting.formatter.PercentFormatter; 32 import com.github.mikephil.charting.highlight.Highlight; 33 import com.github.mikephil.charting.interfaces.datasets.IDataSet; 34 import com.github.mikephil.charting.listener.OnChartValueSelectedListener; 35 import com.github.mikephil.charting.utils.ColorTemplate; 36 import com.github.mikephil.charting.utils.MPPointF; 37 import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; 38 39 import java.util.ArrayList; 40 41 public class PieChartActivity extends DemoBase implements OnSeekBarChangeListener, 42 OnChartValueSelectedListener { 43 44 private PieChart chart; 45 private SeekBar seekBarX, seekBarY; 46 private TextView tvX, tvY; 47 48 @Override onCreate(Bundle savedInstanceState)49 protected void onCreate(Bundle savedInstanceState) { 50 super.onCreate(savedInstanceState); 51 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 52 WindowManager.LayoutParams.FLAG_FULLSCREEN); 53 setContentView(R.layout.activity_piechart); 54 55 setTitle("PieChartActivity"); 56 57 tvX = findViewById(R.id.tvXMax); 58 tvY = findViewById(R.id.tvYMax); 59 60 seekBarX = findViewById(R.id.seekBar1); 61 seekBarY = findViewById(R.id.seekBar2); 62 63 seekBarX.setOnSeekBarChangeListener(this); 64 seekBarY.setOnSeekBarChangeListener(this); 65 66 chart = findViewById(R.id.chart1); 67 chart.setUsePercentValues(true); 68 chart.getDescription().setEnabled(false); 69 chart.setExtraOffsets(5, 10, 5, 5); 70 71 chart.setDragDecelerationFrictionCoef(0.95f); 72 73 chart.setCenterTextTypeface(tfLight); 74 chart.setCenterText(generateCenterSpannableText()); 75 76 chart.setDrawHoleEnabled(true); 77 chart.setHoleColor(Color.WHITE); 78 79 chart.setTransparentCircleColor(Color.WHITE); 80 chart.setTransparentCircleAlpha(110); 81 82 chart.setHoleRadius(58f); 83 chart.setTransparentCircleRadius(61f); 84 85 chart.setDrawCenterText(true); 86 87 chart.setRotationAngle(0); 88 // enable rotation of the chart by touch 89 chart.setRotationEnabled(true); 90 chart.setHighlightPerTapEnabled(true); 91 92 // chart.setUnit(" €"); 93 // chart.setDrawUnitsInChart(true); 94 95 // add a selection listener 96 chart.setOnChartValueSelectedListener(this); 97 98 seekBarX.setProgress(4); 99 seekBarY.setProgress(10); 100 101 chart.animateY(1400, Easing.EaseInOutQuad); 102 // chart.spin(2000, 0, 360); 103 104 Legend l = chart.getLegend(); 105 l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); 106 l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); 107 l.setOrientation(Legend.LegendOrientation.VERTICAL); 108 l.setDrawInside(false); 109 l.setXEntrySpace(7f); 110 l.setYEntrySpace(0f); 111 l.setYOffset(0f); 112 113 // entry label styling 114 chart.setEntryLabelColor(Color.WHITE); 115 chart.setEntryLabelTypeface(tfRegular); 116 chart.setEntryLabelTextSize(12f); 117 } 118 setData(int count, float range)119 private void setData(int count, float range) { 120 ArrayList<PieEntry> entries = new ArrayList<>(); 121 122 // NOTE: The order of the entries when being added to the entries array determines their position around the center of 123 // the chart. 124 for (int i = 0; i < count ; i++) { 125 entries.add(new PieEntry((float) ((Math.random() * range) + range / 5), 126 parties[i % parties.length], 127 getResources().getDrawable(R.drawable.star))); 128 } 129 130 PieDataSet dataSet = new PieDataSet(entries, "Election Results"); 131 132 dataSet.setDrawIcons(false); 133 134 dataSet.setSliceSpace(3f); 135 dataSet.setIconsOffset(new MPPointF(0, 40)); 136 dataSet.setSelectionShift(5f); 137 138 // add a lot of colors 139 140 ArrayList<Integer> colors = new ArrayList<>(); 141 142 for (int c : ColorTemplate.VORDIPLOM_COLORS) 143 colors.add(c); 144 145 for (int c : ColorTemplate.JOYFUL_COLORS) 146 colors.add(c); 147 148 for (int c : ColorTemplate.COLORFUL_COLORS) 149 colors.add(c); 150 151 for (int c : ColorTemplate.LIBERTY_COLORS) 152 colors.add(c); 153 154 for (int c : ColorTemplate.PASTEL_COLORS) 155 colors.add(c); 156 157 colors.add(ColorTemplate.getHoloBlue()); 158 159 dataSet.setColors(colors); 160 //dataSet.setSelectionShift(0f); 161 162 PieData data = new PieData(dataSet); 163 data.setValueFormatter(new PercentFormatter()); 164 data.setValueTextSize(11f); 165 data.setValueTextColor(Color.WHITE); 166 data.setValueTypeface(tfLight); 167 chart.setData(data); 168 169 // undo all highlights 170 chart.highlightValues(null); 171 172 chart.invalidate(); 173 } 174 175 @Override onCreateOptionsMenu(Menu menu)176 public boolean onCreateOptionsMenu(Menu menu) { 177 getMenuInflater().inflate(R.menu.pie, menu); 178 return true; 179 } 180 181 @Override onOptionsItemSelected(MenuItem item)182 public boolean onOptionsItemSelected(MenuItem item) { 183 184 switch (item.getItemId()) { 185 case R.id.viewGithub: { 186 Intent i = new Intent(Intent.ACTION_VIEW); 187 i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java")); 188 startActivity(i); 189 break; 190 } 191 case R.id.actionToggleValues: { 192 for (IDataSet<?> set : chart.getData().getDataSets()) 193 set.setDrawValues(!set.isDrawValuesEnabled()); 194 195 chart.invalidate(); 196 break; 197 } 198 case R.id.actionToggleIcons: { 199 for (IDataSet<?> set : chart.getData().getDataSets()) 200 set.setDrawIcons(!set.isDrawIconsEnabled()); 201 202 chart.invalidate(); 203 break; 204 } 205 case R.id.actionToggleHole: { 206 if (chart.isDrawHoleEnabled()) 207 chart.setDrawHoleEnabled(false); 208 else 209 chart.setDrawHoleEnabled(true); 210 chart.invalidate(); 211 break; 212 } 213 case R.id.actionToggleMinAngles: { 214 if (chart.getMinAngleForSlices() == 0f) 215 chart.setMinAngleForSlices(36f); 216 else 217 chart.setMinAngleForSlices(0f); 218 chart.notifyDataSetChanged(); 219 chart.invalidate(); 220 break; 221 } 222 case R.id.actionToggleCurvedSlices: { 223 boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); 224 chart.setDrawRoundedSlices(toSet); 225 if (toSet && !chart.isDrawHoleEnabled()) { 226 chart.setDrawHoleEnabled(true); 227 } 228 if (toSet && chart.isDrawSlicesUnderHoleEnabled()) { 229 chart.setDrawSlicesUnderHole(false); 230 } 231 chart.invalidate(); 232 break; 233 } 234 case R.id.actionDrawCenter: { 235 if (chart.isDrawCenterTextEnabled()) 236 chart.setDrawCenterText(false); 237 else 238 chart.setDrawCenterText(true); 239 chart.invalidate(); 240 break; 241 } 242 case R.id.actionToggleXValues: { 243 244 chart.setDrawEntryLabels(!chart.isDrawEntryLabelsEnabled()); 245 chart.invalidate(); 246 break; 247 } 248 case R.id.actionTogglePercent: 249 chart.setUsePercentValues(!chart.isUsePercentValuesEnabled()); 250 chart.invalidate(); 251 break; 252 case R.id.animateX: { 253 chart.animateX(1400); 254 break; 255 } 256 case R.id.animateY: { 257 chart.animateY(1400); 258 break; 259 } 260 case R.id.animateXY: { 261 chart.animateXY(1400, 1400); 262 break; 263 } 264 case R.id.actionToggleSpin: { 265 chart.spin(1000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); 266 break; 267 } 268 case R.id.actionSave: { 269 if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { 270 saveToGallery(); 271 } else { 272 requestStoragePermission(chart); 273 } 274 break; 275 } 276 } 277 return true; 278 } 279 280 @Override onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)281 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 282 283 tvX.setText(String.valueOf(seekBarX.getProgress())); 284 tvY.setText(String.valueOf(seekBarY.getProgress())); 285 286 setData(seekBarX.getProgress(), seekBarY.getProgress()); 287 } 288 289 @Override saveToGallery()290 protected void saveToGallery() { 291 saveToGallery(chart, "PieChartActivity"); 292 } 293 generateCenterSpannableText()294 private SpannableString generateCenterSpannableText() { 295 296 SpannableString s = new SpannableString("MPAndroidChart\ndeveloped by Philipp Jahoda"); 297 s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); 298 s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); 299 s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); 300 s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); 301 s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); 302 s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0); 303 return s; 304 } 305 306 @Override onValueSelected(Entry e, Highlight h)307 public void onValueSelected(Entry e, Highlight h) { 308 309 if (e == null) 310 return; 311 Log.i("VAL SELECTED", 312 "Value: " + e.getY() + ", index: " + h.getX() 313 + ", DataSet index: " + h.getDataSetIndex()); 314 } 315 316 @Override onNothingSelected()317 public void onNothingSelected() { 318 Log.i("PieChart", "nothing selected"); 319 } 320 321 @Override onStartTrackingTouch(SeekBar seekBar)322 public void onStartTrackingTouch(SeekBar seekBar) {} 323 324 @Override onStopTrackingTouch(SeekBar seekBar)325 public void onStopTrackingTouch(SeekBar seekBar) {} 326 } 327