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