Compare commits
53 commits
Author | SHA1 | Date | |
---|---|---|---|
|
a6c3808fd5 | ||
|
941579e10f | ||
|
21c811ff9a | ||
|
f3a2ec21c9 | ||
|
9347dd1af7 | ||
|
90e523042c | ||
|
33240f9225 | ||
|
4b67673da9 | ||
|
cef967fd71 | ||
|
eae977306e | ||
|
c0e7f56b5d | ||
|
351e341ee7 | ||
|
f05337768d | ||
|
f8d068d377 | ||
|
5e4a32eb41 | ||
|
1de836ac65 | ||
|
0668d30a6b | ||
|
34fefd28e1 | ||
|
45240c3723 | ||
|
14456f475f | ||
|
e02e9be2fa | ||
|
fcc5af71ce | ||
|
13aee592b1 | ||
|
c97c8d247f | ||
|
ae59e7a19e | ||
|
7752efef7e | ||
|
58545bbbfa | ||
|
4ce14e6cc9 | ||
|
8df9eda7af | ||
|
34c3ceaa05 | ||
|
ea816e8d6d | ||
|
bafb0fbbe4 | ||
|
4549ae17b7 | ||
|
912427e543 | ||
|
3f5475077e | ||
|
2e725e49d3 | ||
|
a4ca1f3fba | ||
|
634a690d6a | ||
|
1987d7eb64 | ||
|
6ebf3fa57a | ||
|
95027fa6a7 | ||
|
d86f39cc91 | ||
|
cb26ed4ef4 | ||
|
dc59171524 | ||
|
726616d079 | ||
|
fffe9a297e | ||
|
2340e12800 | ||
|
c5667d4f14 | ||
|
0563fb48b0 | ||
|
ed8876cef2 | ||
|
12b4351d0c | ||
|
adb56e75bd | ||
|
e95c1eb26a |
50 changed files with 1663 additions and 401 deletions
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: mpandroidchart
|
||||
open_collective: philippjahoda
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
@ -24,6 +24,7 @@
|
|||
<activity android:name="LineChartTime" />
|
||||
<activity android:name="BarChartActivity" />
|
||||
<activity android:name="HorizontalBarChartActivity" />
|
||||
<activity android:name="HorizontalBarNegativeChartActivity" />
|
||||
<activity android:name="PieChartActivity" />
|
||||
<activity android:name="PiePolylineChartActivity" />
|
||||
<activity android:name="MultiLineChartActivity" />
|
||||
|
|
|
@ -32,7 +32,7 @@ import com.github.mikephil.charting.highlight.Highlight;
|
|||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
|
||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||
import com.github.mikephil.charting.model.GradientColor;
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter;
|
||||
import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter;
|
||||
|
@ -164,12 +164,6 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListene
|
|||
|
||||
set1.setDrawIcons(false);
|
||||
|
||||
// set1.setColors(ColorTemplate.MATERIAL_COLORS);
|
||||
|
||||
/*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark);
|
||||
int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright);
|
||||
set1.setGradientColor(startColor, endColor);*/
|
||||
|
||||
int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light);
|
||||
int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light);
|
||||
int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light);
|
||||
|
@ -181,14 +175,14 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListene
|
|||
int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark);
|
||||
int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark);
|
||||
|
||||
List<GradientColor> gradientColors = new ArrayList<>();
|
||||
gradientColors.add(new GradientColor(startColor1, endColor1));
|
||||
gradientColors.add(new GradientColor(startColor2, endColor2));
|
||||
gradientColors.add(new GradientColor(startColor3, endColor3));
|
||||
gradientColors.add(new GradientColor(startColor4, endColor4));
|
||||
gradientColors.add(new GradientColor(startColor5, endColor5));
|
||||
List<Fill> gradientFills = new ArrayList<>();
|
||||
gradientFills.add(new Fill(startColor1, endColor1));
|
||||
gradientFills.add(new Fill(startColor2, endColor2));
|
||||
gradientFills.add(new Fill(startColor3, endColor3));
|
||||
gradientFills.add(new Fill(startColor4, endColor4));
|
||||
gradientFills.add(new Fill(startColor5, endColor5));
|
||||
|
||||
set1.setGradientColors(gradientColors);
|
||||
set1.setFills(gradientFills);
|
||||
|
||||
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
|
||||
dataSets.add(set1);
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
|
||||
package com.xxmassdeveloper.mpchartexample;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.RectF;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.github.mikephil.charting.charts.HorizontalBarChart;
|
||||
import com.github.mikephil.charting.components.Legend;
|
||||
import com.github.mikephil.charting.components.XAxis;
|
||||
import com.github.mikephil.charting.components.XAxis.XAxisPosition;
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.data.BarData;
|
||||
import com.github.mikephil.charting.data.BarDataSet;
|
||||
import com.github.mikephil.charting.data.BarEntry;
|
||||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class HorizontalBarNegativeChartActivity extends DemoBase implements OnSeekBarChangeListener,
|
||||
OnChartValueSelectedListener {
|
||||
|
||||
private HorizontalBarChart chart;
|
||||
private SeekBar seekBarX, seekBarY;
|
||||
private TextView tvX, tvY;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
setContentView(R.layout.activity_horizontalbarchart);
|
||||
|
||||
setTitle("HorizontalBarChartActivity");
|
||||
|
||||
tvX = findViewById(R.id.tvXMax);
|
||||
tvY = findViewById(R.id.tvYMax);
|
||||
|
||||
seekBarX = findViewById(R.id.seekBar1);
|
||||
seekBarY = findViewById(R.id.seekBar2);
|
||||
|
||||
seekBarY.setOnSeekBarChangeListener(this);
|
||||
seekBarX.setOnSeekBarChangeListener(this);
|
||||
|
||||
chart = findViewById(R.id.chart1);
|
||||
chart.setOnChartValueSelectedListener(this);
|
||||
// chart.setHighlightEnabled(false);
|
||||
|
||||
chart.setDrawBarShadow(false);
|
||||
|
||||
chart.setDrawValueAboveBar(true);
|
||||
|
||||
chart.getDescription().setEnabled(false);
|
||||
|
||||
// if more than 60 entries are displayed in the chart, no values will be
|
||||
// drawn
|
||||
chart.setMaxVisibleValueCount(60);
|
||||
|
||||
// scaling can now only be done on x- and y-axis separately
|
||||
chart.setPinchZoom(false);
|
||||
|
||||
// draw shadows for each bar that show the maximum value
|
||||
// chart.setDrawBarShadow(true);
|
||||
|
||||
chart.setDrawGridBackground(false);
|
||||
|
||||
XAxis xl = chart.getXAxis();
|
||||
xl.setPosition(XAxisPosition.BOTTOM);
|
||||
xl.setTypeface(tfLight);
|
||||
xl.setDrawAxisLine(true);
|
||||
xl.setDrawGridLines(false);
|
||||
xl.setGranularity(10f);
|
||||
|
||||
YAxis yl = chart.getAxisLeft();
|
||||
yl.setTypeface(tfLight);
|
||||
yl.setDrawAxisLine(true);
|
||||
yl.setDrawGridLines(true);
|
||||
// yl.setInverted(true);
|
||||
|
||||
YAxis yr = chart.getAxisRight();
|
||||
yr.setTypeface(tfLight);
|
||||
yr.setDrawAxisLine(true);
|
||||
yr.setDrawGridLines(false);
|
||||
// yr.setInverted(true);
|
||||
|
||||
chart.setFitBars(true);
|
||||
chart.animateY(2500);
|
||||
|
||||
// setting data
|
||||
seekBarY.setProgress(50);
|
||||
seekBarX.setProgress(12);
|
||||
|
||||
Legend l = chart.getLegend();
|
||||
l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
|
||||
l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
|
||||
l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
|
||||
l.setDrawInside(false);
|
||||
l.setFormSize(8f);
|
||||
l.setXEntrySpace(4f);
|
||||
}
|
||||
|
||||
private void setData(int count, float range) {
|
||||
|
||||
float barWidth = 9f;
|
||||
float spaceForBar = 10f;
|
||||
ArrayList<BarEntry> values = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
float val = (float) (Math.random() * range - range / 2);
|
||||
values.add(new BarEntry(i * spaceForBar, val,
|
||||
getResources().getDrawable(R.drawable.star)));
|
||||
}
|
||||
|
||||
BarDataSet set1;
|
||||
|
||||
if (chart.getData() != null &&
|
||||
chart.getData().getDataSetCount() > 0) {
|
||||
set1 = (BarDataSet) chart.getData().getDataSetByIndex(0);
|
||||
set1.setValues(values);
|
||||
chart.getData().notifyDataChanged();
|
||||
chart.notifyDataSetChanged();
|
||||
} else {
|
||||
set1 = new BarDataSet(values, "DataSet 1");
|
||||
|
||||
set1.setDrawIcons(false);
|
||||
|
||||
ArrayList<IBarDataSet> dataSets = new ArrayList<>();
|
||||
dataSets.add(set1);
|
||||
|
||||
BarData data = new BarData(dataSets);
|
||||
data.setValueTextSize(10f);
|
||||
data.setValueTypeface(tfLight);
|
||||
data.setBarWidth(barWidth);
|
||||
chart.setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.bar, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.viewGithub: {
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java"));
|
||||
startActivity(i);
|
||||
break;
|
||||
}
|
||||
case R.id.actionToggleValues: {
|
||||
List<IBarDataSet> sets = chart.getData()
|
||||
.getDataSets();
|
||||
|
||||
for (IBarDataSet iSet : sets) {
|
||||
iSet.setDrawValues(!iSet.isDrawValuesEnabled());
|
||||
}
|
||||
|
||||
chart.invalidate();
|
||||
break;
|
||||
}
|
||||
case R.id.actionToggleIcons: {
|
||||
List<IBarDataSet> sets = chart.getData()
|
||||
.getDataSets();
|
||||
|
||||
for (IBarDataSet iSet : sets) {
|
||||
iSet.setDrawIcons(!iSet.isDrawIconsEnabled());
|
||||
}
|
||||
|
||||
chart.invalidate();
|
||||
break;
|
||||
}
|
||||
case R.id.actionToggleHighlight: {
|
||||
if(chart.getData() != null) {
|
||||
chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled());
|
||||
chart.invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R.id.actionTogglePinch: {
|
||||
if (chart.isPinchZoomEnabled())
|
||||
chart.setPinchZoom(false);
|
||||
else
|
||||
chart.setPinchZoom(true);
|
||||
|
||||
chart.invalidate();
|
||||
break;
|
||||
}
|
||||
case R.id.actionToggleAutoScaleMinMax: {
|
||||
chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled());
|
||||
chart.notifyDataSetChanged();
|
||||
break;
|
||||
}
|
||||
case R.id.actionToggleBarBorders: {
|
||||
for (IBarDataSet set : chart.getData().getDataSets())
|
||||
((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f);
|
||||
|
||||
chart.invalidate();
|
||||
break;
|
||||
}
|
||||
case R.id.animateX: {
|
||||
chart.animateX(2000);
|
||||
break;
|
||||
}
|
||||
case R.id.animateY: {
|
||||
chart.animateY(2000);
|
||||
break;
|
||||
}
|
||||
case R.id.animateXY: {
|
||||
chart.animateXY(2000, 2000);
|
||||
break;
|
||||
}
|
||||
case R.id.actionSave: {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
|
||||
saveToGallery();
|
||||
} else {
|
||||
requestStoragePermission(chart);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
|
||||
tvX.setText(String.valueOf(seekBarX.getProgress()));
|
||||
tvY.setText(String.valueOf(seekBarY.getProgress()));
|
||||
|
||||
setData(seekBarX.getProgress(), seekBarY.getProgress());
|
||||
chart.setFitBars(true);
|
||||
chart.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveToGallery() {
|
||||
saveToGallery(chart, "HorizontalBarChartActivity");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {}
|
||||
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {}
|
||||
|
||||
private final RectF mOnValueSelectedRectF = new RectF();
|
||||
|
||||
@Override
|
||||
public void onValueSelected(Entry e, Highlight h) {
|
||||
|
||||
if (e == null)
|
||||
return;
|
||||
|
||||
RectF bounds = mOnValueSelectedRectF;
|
||||
chart.getBarBounds((BarEntry) e, bounds);
|
||||
|
||||
MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex())
|
||||
.getAxisDependency());
|
||||
|
||||
Log.i("bounds", bounds.toString());
|
||||
Log.i("position", position.toString());
|
||||
|
||||
MPPointF.recycleInstance(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected() {}
|
||||
}
|
|
@ -156,7 +156,6 @@ public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChang
|
|||
dataSet.setValueLinePart1OffsetPercentage(80.f);
|
||||
dataSet.setValueLinePart1Length(0.2f);
|
||||
dataSet.setValueLinePart2Length(0.4f);
|
||||
//dataSet.setUsingSliceColorAsValueLineColor(true);
|
||||
|
||||
//dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
|
||||
dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity;
|
|||
import com.xxmassdeveloper.mpchartexample.FilledLineActivity;
|
||||
import com.xxmassdeveloper.mpchartexample.HalfPieChartActivity;
|
||||
import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity;
|
||||
import com.xxmassdeveloper.mpchartexample.HorizontalBarNegativeChartActivity;
|
||||
import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity;
|
||||
import com.xxmassdeveloper.mpchartexample.LineChartActivity1;
|
||||
import com.xxmassdeveloper.mpchartexample.LineChartActivity2;
|
||||
|
@ -87,40 +88,41 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
|
|||
objects.add(13, new ContentItem("Horizontal", "Render bar chart horizontally."));
|
||||
objects.add(14, new ContentItem("Stacked", "Stacked bar chart."));
|
||||
objects.add(15, new ContentItem("Negative", "Positive and negative values with unique colors."));
|
||||
objects.add(16, new ContentItem("Stacked 2", "Stacked bar chart with negative values."));
|
||||
objects.add(17, new ContentItem("Sine", "Sine function in bar chart format."));
|
||||
objects.add(16, new ContentItem("Negative Horizontal", "demonstrates how to create a HorizontalBarChart with positive and negative values."));
|
||||
objects.add(17, new ContentItem("Stacked 2", "Stacked bar chart with negative values."));
|
||||
objects.add(18, new ContentItem("Sine", "Sine function in bar chart format."));
|
||||
|
||||
////
|
||||
objects.add(18, new ContentItem("Pie Charts"));
|
||||
objects.add(19, new ContentItem("Pie Charts"));
|
||||
|
||||
objects.add(19, new ContentItem("Basic", "Simple pie chart."));
|
||||
objects.add(20, new ContentItem("Value Lines", "Stylish lines drawn outward from slices."));
|
||||
objects.add(21, new ContentItem("Half Pie", "180° (half) pie chart."));
|
||||
objects.add(20, new ContentItem("Basic", "Simple pie chart."));
|
||||
objects.add(21, new ContentItem("Value Lines", "Stylish lines drawn outward from slices."));
|
||||
objects.add(22, new ContentItem("Half Pie", "180° (half) pie chart."));
|
||||
|
||||
////
|
||||
objects.add(22, new ContentItem("Other Charts"));
|
||||
objects.add(23, new ContentItem("Other Charts"));
|
||||
|
||||
objects.add(23, new ContentItem("Combined Chart", "Bar and line chart together."));
|
||||
objects.add(24, new ContentItem("Scatter Plot", "Simple scatter plot."));
|
||||
objects.add(25, new ContentItem("Bubble Chart", "Simple bubble chart."));
|
||||
objects.add(26, new ContentItem("Candlestick", "Simple financial chart."));
|
||||
objects.add(27, new ContentItem("Radar Chart", "Simple web chart."));
|
||||
objects.add(24, new ContentItem("Combined Chart", "Bar and line chart together."));
|
||||
objects.add(25, new ContentItem("Scatter Plot", "Simple scatter plot."));
|
||||
objects.add(26, new ContentItem("Bubble Chart", "Simple bubble chart."));
|
||||
objects.add(27, new ContentItem("Candlestick", "Simple financial chart."));
|
||||
objects.add(28, new ContentItem("Radar Chart", "Simple web chart."));
|
||||
|
||||
////
|
||||
objects.add(28, new ContentItem("Scrolling Charts"));
|
||||
objects.add(29, new ContentItem("Scrolling Charts"));
|
||||
|
||||
objects.add(29, new ContentItem("Multiple", "Various types of charts as fragments."));
|
||||
objects.add(30, new ContentItem("View Pager", "Swipe through different charts."));
|
||||
objects.add(31, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!"));
|
||||
objects.add(32, new ContentItem("Many Bar Charts", "More bars than your screen can handle!"));
|
||||
objects.add(30, new ContentItem("Multiple", "Various types of charts as fragments."));
|
||||
objects.add(31, new ContentItem("View Pager", "Swipe through different charts."));
|
||||
objects.add(32, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!"));
|
||||
objects.add(33, new ContentItem("Many Bar Charts", "More bars than your screen can handle!"));
|
||||
|
||||
////
|
||||
objects.add(33, new ContentItem("Even More Line Charts"));
|
||||
objects.add(34, new ContentItem("Even More Line Charts"));
|
||||
|
||||
objects.add(34, new ContentItem("Dynamic", "Build a line chart by adding points and sets."));
|
||||
objects.add(35, new ContentItem("Realtime", "Add data points in realtime."));
|
||||
objects.add(36, new ContentItem("Hourly", "Uses the current time to add a data point for each hour."));
|
||||
//objects.add(37, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database."));
|
||||
objects.add(35, new ContentItem("Dynamic", "Build a line chart by adding points and sets."));
|
||||
objects.add(36, new ContentItem("Realtime", "Add data points in realtime."));
|
||||
objects.add(37, new ContentItem("Hourly", "Uses the current time to add a data point for each hour."));
|
||||
//objects.add(38, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database."));
|
||||
|
||||
MyAdapter adapter = new MyAdapter(this, objects);
|
||||
|
||||
|
@ -179,57 +181,60 @@ public class MainActivity extends AppCompatActivity implements OnItemClickListen
|
|||
i = new Intent(this, BarChartPositiveNegative.class);
|
||||
break;
|
||||
case 16:
|
||||
i = new Intent(this, StackedBarActivityNegative.class);
|
||||
i = new Intent(this, HorizontalBarNegativeChartActivity.class);
|
||||
break;
|
||||
case 17:
|
||||
i = new Intent(this, StackedBarActivityNegative.class);
|
||||
break;
|
||||
case 18:
|
||||
i = new Intent(this, BarChartActivitySinus.class);
|
||||
break;
|
||||
case 19:
|
||||
case 20:
|
||||
i = new Intent(this, PieChartActivity.class);
|
||||
break;
|
||||
case 20:
|
||||
case 21:
|
||||
i = new Intent(this, PiePolylineChartActivity.class);
|
||||
break;
|
||||
case 21:
|
||||
case 22:
|
||||
i = new Intent(this, HalfPieChartActivity.class);
|
||||
break;
|
||||
case 23:
|
||||
case 24:
|
||||
i = new Intent(this, CombinedChartActivity.class);
|
||||
break;
|
||||
case 24:
|
||||
case 25:
|
||||
i = new Intent(this, ScatterChartActivity.class);
|
||||
break;
|
||||
case 25:
|
||||
case 26:
|
||||
i = new Intent(this, BubbleChartActivity.class);
|
||||
break;
|
||||
case 26:
|
||||
case 27:
|
||||
i = new Intent(this, CandleStickChartActivity.class);
|
||||
break;
|
||||
case 27:
|
||||
case 28:
|
||||
i = new Intent(this, RadarChartActivity.class);
|
||||
break;
|
||||
case 29:
|
||||
case 30:
|
||||
i = new Intent(this, ListViewMultiChartActivity.class);
|
||||
break;
|
||||
case 30:
|
||||
case 31:
|
||||
i = new Intent(this, SimpleChartDemo.class);
|
||||
break;
|
||||
case 31:
|
||||
case 32:
|
||||
i = new Intent(this, ScrollViewActivity.class);
|
||||
break;
|
||||
case 32:
|
||||
case 33:
|
||||
i = new Intent(this, ListViewBarChartActivity.class);
|
||||
break;
|
||||
case 34:
|
||||
case 35:
|
||||
i = new Intent(this, DynamicalAddingActivity.class);
|
||||
break;
|
||||
case 35:
|
||||
case 36:
|
||||
i = new Intent(this, RealtimeLineChartActivity.class);
|
||||
break;
|
||||
case 36:
|
||||
case 37:
|
||||
i = new Intent(this, LineChartTime.class);
|
||||
break;
|
||||
/*case 37:
|
||||
/*case 38:
|
||||
i = new Intent(this, RealmMainActivity.class);
|
||||
break;*/
|
||||
}
|
||||
|
|
|
@ -100,6 +100,8 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
|
||||
protected boolean mClipValuesToContent = false;
|
||||
|
||||
protected boolean mClipDataToContent = true;
|
||||
|
||||
/**
|
||||
* Sets the minimum offset (padding) around the chart, defaults to 15
|
||||
*/
|
||||
|
@ -230,9 +232,12 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
if (mAxisRight.isEnabled() && mAxisRight.isDrawLimitLinesBehindDataEnabled())
|
||||
mAxisRendererRight.renderLimitLines(canvas);
|
||||
|
||||
// make sure the data cannot be drawn outside the content-rect
|
||||
int clipRestoreCount = canvas.save();
|
||||
canvas.clipRect(mViewPortHandler.getContentRect());
|
||||
|
||||
if (isClipDataToContentEnabled()) {
|
||||
// make sure the data cannot be drawn outside the content-rect
|
||||
canvas.clipRect(mViewPortHandler.getContentRect());
|
||||
}
|
||||
|
||||
mRenderer.drawData(canvas);
|
||||
|
||||
|
@ -394,66 +399,70 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
offsets.top = 0.f;
|
||||
offsets.bottom = 0.f;
|
||||
|
||||
// setup offsets for legend
|
||||
if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) {
|
||||
switch (mLegend.getOrientation()) {
|
||||
case VERTICAL:
|
||||
if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled())
|
||||
return;
|
||||
|
||||
switch (mLegend.getHorizontalAlignment()) {
|
||||
case LEFT:
|
||||
offsets.left += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
switch (mLegend.getOrientation()) {
|
||||
case VERTICAL:
|
||||
|
||||
case RIGHT:
|
||||
offsets.right += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
switch (mLegend.getHorizontalAlignment()) {
|
||||
case LEFT:
|
||||
offsets.left += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
|
||||
case CENTER:
|
||||
case RIGHT:
|
||||
offsets.right += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
case CENTER:
|
||||
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case HORIZONTAL:
|
||||
break;
|
||||
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
case HORIZONTAL:
|
||||
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1224,6 +1233,17 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
mClipValuesToContent = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* When disabled, the data and/or highlights will not be clipped to contentRect. Disabling this option can
|
||||
* be useful, when the data lies fully within the content rect, but is drawn in such a way (such as thick lines)
|
||||
* that there is unwanted clipping.
|
||||
*
|
||||
* @param enabled
|
||||
*/
|
||||
public void setClipDataToContent(boolean enabled) {
|
||||
mClipDataToContent = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* When enabled, the values will be clipped to contentRect,
|
||||
* otherwise they can bleed outside the content rect.
|
||||
|
@ -1234,6 +1254,17 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
return mClipValuesToContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* When disabled, the data and/or highlights will not be clipped to contentRect. Disabling this option can
|
||||
* be useful, when the data lies fully within the content rect, but is drawn in such a way (such as thick lines)
|
||||
* that there is unwanted clipping.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isClipDataToContentEnabled() {
|
||||
return mClipDataToContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the border lines in dp.
|
||||
*
|
||||
|
|
|
@ -13,7 +13,6 @@ import android.graphics.Paint.Align;
|
|||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore.Images;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
@ -25,7 +24,6 @@ import android.view.ViewGroup;
|
|||
import android.view.ViewParent;
|
||||
|
||||
import com.github.mikephil.charting.animation.ChartAnimator;
|
||||
import com.github.mikephil.charting.animation.Easing;
|
||||
import com.github.mikephil.charting.animation.Easing.EasingFunction;
|
||||
import com.github.mikephil.charting.components.Description;
|
||||
import com.github.mikephil.charting.components.IMarker;
|
||||
|
@ -54,6 +52,8 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Baseclass of all Chart-Views.
|
||||
|
@ -398,8 +398,23 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
boolean hasText = !TextUtils.isEmpty(mNoDataText);
|
||||
|
||||
if (hasText) {
|
||||
MPPointF c = getCenter();
|
||||
canvas.drawText(mNoDataText, c.x, c.y, mInfoPaint);
|
||||
MPPointF pt = getCenter();
|
||||
|
||||
switch (mInfoPaint.getTextAlign()) {
|
||||
case LEFT:
|
||||
pt.x = 0;
|
||||
canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint);
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
pt.x *= 2.0;
|
||||
canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint);
|
||||
break;
|
||||
|
||||
default:
|
||||
canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -548,6 +563,24 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
invalidate();
|
||||
}
|
||||
|
||||
public void highlightValues(List<Highlight> highs, List<IMarker> markers) {
|
||||
if (highs.size() != markers.size()) throw new IllegalArgumentException("Markers and highs must be mutually corresponding. High size = " + highs.size() + " Markers size = " + markers.size());
|
||||
setMarkers(markers);
|
||||
highlightValues(highs.toArray(new Highlight[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights any y-value at the given x-value in the given DataSet.
|
||||
* Provide -1 as the dataSetIndex to undo all highlighting.
|
||||
* This method will call the listener.
|
||||
* @param x The x-value to highlight
|
||||
* @param dataSetIndex The dataset index to search in
|
||||
* @param dataIndex The data index to search in (only used in CombinedChartView currently)
|
||||
*/
|
||||
public void highlightValue(float x, int dataSetIndex, int dataIndex) {
|
||||
highlightValue(x, dataSetIndex, dataIndex, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights any y-value at the given x-value in the given DataSet.
|
||||
* Provide -1 as the dataSetIndex to undo all highlighting.
|
||||
|
@ -556,7 +589,20 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
* @param dataSetIndex The dataset index to search in
|
||||
*/
|
||||
public void highlightValue(float x, int dataSetIndex) {
|
||||
highlightValue(x, dataSetIndex, true);
|
||||
highlightValue(x, dataSetIndex, -1, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights the value at the given x-value and y-value in the given DataSet.
|
||||
* Provide -1 as the dataSetIndex to undo all highlighting.
|
||||
* This method will call the listener.
|
||||
* @param x The x-value to highlight
|
||||
* @param y The y-value to highlight. Supply `NaN` for "any"
|
||||
* @param dataSetIndex The dataset index to search in
|
||||
* @param dataIndex The data index to search in (only used in CombinedChartView currently)
|
||||
*/
|
||||
public void highlightValue(float x, float y, int dataSetIndex, int dataIndex) {
|
||||
highlightValue(x, y, dataSetIndex, dataIndex, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -568,7 +614,19 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
* @param dataSetIndex The dataset index to search in
|
||||
*/
|
||||
public void highlightValue(float x, float y, int dataSetIndex) {
|
||||
highlightValue(x, y, dataSetIndex, true);
|
||||
highlightValue(x, y, dataSetIndex, -1, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights any y-value at the given x-value in the given DataSet.
|
||||
* Provide -1 as the dataSetIndex to undo all highlighting.
|
||||
* @param x The x-value to highlight
|
||||
* @param dataSetIndex The dataset index to search in
|
||||
* @param dataIndex The data index to search in (only used in CombinedChartView currently)
|
||||
* @param callListener Should the listener be called for this change
|
||||
*/
|
||||
public void highlightValue(float x, int dataSetIndex, int dataIndex, boolean callListener) {
|
||||
highlightValue(x, Float.NaN, dataSetIndex, dataIndex, callListener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -579,7 +637,25 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
* @param callListener Should the listener be called for this change
|
||||
*/
|
||||
public void highlightValue(float x, int dataSetIndex, boolean callListener) {
|
||||
highlightValue(x, Float.NaN, dataSetIndex, callListener);
|
||||
highlightValue(x, Float.NaN, dataSetIndex, -1, callListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights any y-value at the given x-value in the given DataSet.
|
||||
* Provide -1 as the dataSetIndex to undo all highlighting.
|
||||
* @param x The x-value to highlight
|
||||
* @param y The y-value to highlight. Supply `NaN` for "any"
|
||||
* @param dataSetIndex The dataset index to search in
|
||||
* @param dataIndex The data index to search in (only used in CombinedChartView currently)
|
||||
* @param callListener Should the listener be called for this change
|
||||
*/
|
||||
public void highlightValue(float x, float y, int dataSetIndex, int dataIndex, boolean callListener) {
|
||||
|
||||
if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) {
|
||||
highlightValue(null, callListener);
|
||||
} else {
|
||||
highlightValue(new Highlight(x, y, dataSetIndex, dataIndex), callListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -591,12 +667,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
* @param callListener Should the listener be called for this change
|
||||
*/
|
||||
public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) {
|
||||
|
||||
if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) {
|
||||
highlightValue(null, callListener);
|
||||
} else {
|
||||
highlightValue(new Highlight(x, y, dataSetIndex), callListener);
|
||||
}
|
||||
highlightValue(x, y, dataSetIndex, -1, callListener);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -707,7 +778,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
/**
|
||||
* the view that represents the marker
|
||||
*/
|
||||
protected IMarker mMarker;
|
||||
protected List<IMarker> mMarkers;
|
||||
|
||||
/**
|
||||
* draws all MarkerViews on the highlighted positions
|
||||
|
@ -715,7 +786,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
protected void drawMarkers(Canvas canvas) {
|
||||
|
||||
// if there is no marker view or drawing marker is disabled
|
||||
if (mMarker == null || !isDrawMarkersEnabled() || !valuesToHighlight())
|
||||
if (mMarkers == null || !isDrawMarkersEnabled() || !valuesToHighlight())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < mIndicesToHighlight.length; i++) {
|
||||
|
@ -738,10 +809,12 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
continue;
|
||||
|
||||
// callbacks to update the content
|
||||
mMarker.refreshContent(e, highlight);
|
||||
int markerIndex = i % mMarkers.size();
|
||||
IMarker markerItem = mMarkers.get(markerIndex);
|
||||
markerItem.refreshContent(e, highlight);
|
||||
|
||||
// draw the marker
|
||||
mMarker.draw(canvas, pos[0], pos[1]);
|
||||
markerItem.draw(canvas, pos[0], pos[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1162,6 +1235,15 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
mInfoPaint.setTypeface(tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* alignment of the no data text
|
||||
*
|
||||
* @param align
|
||||
*/
|
||||
public void setNoDataTextAlignment(Align align) {
|
||||
mInfoPaint.setTextAlign(align);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this to false to disable all gestures and touches on the chart,
|
||||
* default: true
|
||||
|
@ -1172,22 +1254,25 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
this.mTouchEnabled = enabled;
|
||||
}
|
||||
|
||||
public void setMarkers(List<IMarker> marker) {
|
||||
mMarkers = marker;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the marker that is displayed when a value is clicked on the chart
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
public void setMarker(IMarker marker) {
|
||||
mMarker = marker;
|
||||
setMarkers(Collections.unmodifiableList(Collections.singletonList(marker)));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the marker that is set as a marker view for the chart
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public IMarker getMarker() {
|
||||
return mMarker;
|
||||
public List<IMarker> getMarker() {
|
||||
return mMarkers;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
@ -1196,7 +1281,7 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
}
|
||||
|
||||
@Deprecated
|
||||
public IMarker getMarkerView() {
|
||||
public List<IMarker> getMarkerView() {
|
||||
return getMarker();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import android.graphics.Canvas;
|
|||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.mikephil.charting.components.IMarker;
|
||||
import com.github.mikephil.charting.data.BarData;
|
||||
import com.github.mikephil.charting.data.BubbleData;
|
||||
import com.github.mikephil.charting.data.CandleData;
|
||||
|
@ -236,7 +237,7 @@ public class CombinedChart extends BarLineChartBase<CombinedData> implements Com
|
|||
protected void drawMarkers(Canvas canvas) {
|
||||
|
||||
// if there is no marker view or drawing marker is disabled
|
||||
if (mMarker == null || !isDrawMarkersEnabled() || !valuesToHighlight())
|
||||
if (mMarkers == null || !isDrawMarkersEnabled() || !valuesToHighlight())
|
||||
return;
|
||||
|
||||
for (int i = 0; i < mIndicesToHighlight.length; i++) {
|
||||
|
@ -262,10 +263,11 @@ public class CombinedChart extends BarLineChartBase<CombinedData> implements Com
|
|||
continue;
|
||||
|
||||
// callbacks to update the content
|
||||
mMarker.refreshContent(e, highlight);
|
||||
IMarker markerItem = mMarkers.get(i % mMarkers.size());
|
||||
markerItem.refreshContent(e, highlight);
|
||||
|
||||
// draw the marker
|
||||
mMarker.draw(canvas, pos[0], pos[1]);
|
||||
markerItem.draw(canvas, pos[0], pos[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,6 +60,84 @@ public class HorizontalBarChart extends BarChart {
|
|||
|
||||
private RectF mOffsetsBuffer = new RectF();
|
||||
|
||||
protected void calculateLegendOffsets(RectF offsets) {
|
||||
|
||||
offsets.left = 0.f;
|
||||
offsets.right = 0.f;
|
||||
offsets.top = 0.f;
|
||||
offsets.bottom = 0.f;
|
||||
|
||||
if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled())
|
||||
return;
|
||||
|
||||
switch (mLegend.getOrientation()) {
|
||||
case VERTICAL:
|
||||
|
||||
switch (mLegend.getHorizontalAlignment()) {
|
||||
case LEFT:
|
||||
offsets.left += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
offsets.right += Math.min(mLegend.mNeededWidth,
|
||||
mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getXOffset();
|
||||
break;
|
||||
|
||||
case CENTER:
|
||||
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case HORIZONTAL:
|
||||
|
||||
switch (mLegend.getVerticalAlignment()) {
|
||||
case TOP:
|
||||
offsets.top += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
|
||||
if (mAxisLeft.isEnabled() && mAxisLeft.isDrawLabelsEnabled())
|
||||
offsets.top += mAxisLeft.getRequiredHeightSpace(
|
||||
mAxisRendererLeft.getPaintAxisLabels());
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
offsets.bottom += Math.min(mLegend.mNeededHeight,
|
||||
mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent())
|
||||
+ mLegend.getYOffset();
|
||||
|
||||
if (mAxisRight.isEnabled() && mAxisRight.isDrawLabelsEnabled())
|
||||
offsets.bottom += mAxisRight.getRequiredHeightSpace(
|
||||
mAxisRendererRight.getPaintAxisLabels());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateOffsets() {
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ public class RadarChart extends PieRadarChartBase<RadarData> {
|
|||
super.init();
|
||||
|
||||
mYAxis = new YAxis(AxisDependency.LEFT);
|
||||
mYAxis.setLabelXOffset(10f);
|
||||
|
||||
mWebLineWidth = Utils.convertDpToPixel(1.5f);
|
||||
mInnerWebLineWidth = Utils.convertDpToPixel(0.75f);
|
||||
|
|
|
@ -151,6 +151,39 @@ public abstract class AxisBase extends ComponentBase {
|
|||
*/
|
||||
public float mAxisRange = 0f;
|
||||
|
||||
private int mAxisMinLabels = 2;
|
||||
private int mAxisMaxLabels = 25;
|
||||
|
||||
/**
|
||||
* The minumum number of labels on the axis
|
||||
*/
|
||||
public int getAxisMinLabels() {
|
||||
return mAxisMinLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* The minumum number of labels on the axis
|
||||
*/
|
||||
public void setAxisMinLabels(int labels) {
|
||||
if (labels > 0)
|
||||
mAxisMinLabels = labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of labels on the axis
|
||||
*/
|
||||
public int getAxisMaxLabels() {
|
||||
return mAxisMaxLabels;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of labels on the axis
|
||||
*/
|
||||
public void setAxisMaxLabels(int labels) {
|
||||
if (labels > 0)
|
||||
mAxisMaxLabels = labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
|
@ -314,10 +347,10 @@ public abstract class AxisBase extends ComponentBase {
|
|||
*/
|
||||
public void setLabelCount(int count) {
|
||||
|
||||
if (count > 25)
|
||||
count = 25;
|
||||
if (count < 2)
|
||||
count = 2;
|
||||
if (count > getAxisMaxLabels())
|
||||
count = getAxisMaxLabels();
|
||||
if (count < getAxisMinLabels())
|
||||
count = getAxisMinLabels();
|
||||
|
||||
mLabelCount = count;
|
||||
mForceLabels = false;
|
||||
|
|
|
@ -703,8 +703,7 @@ public class Legend extends ComponentBase {
|
|||
|
||||
width += Utils.calcTextWidth(labelpaint, label);
|
||||
|
||||
if (i < entryCount - 1)
|
||||
maxHeight += labelLineHeight + yEntrySpace;
|
||||
maxHeight += labelLineHeight + yEntrySpace;
|
||||
} else {
|
||||
wasStacked = true;
|
||||
width += formSize;
|
||||
|
|
|
@ -73,6 +73,11 @@ public class YAxis extends AxisBase {
|
|||
*/
|
||||
private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART;
|
||||
|
||||
/**
|
||||
* the horizontal offset of the y-label
|
||||
*/
|
||||
private float mXLabelOffset = 0.0f;
|
||||
|
||||
/**
|
||||
* enum for the position of the y-labels relative to the chart
|
||||
*/
|
||||
|
@ -174,6 +179,22 @@ public class YAxis extends AxisBase {
|
|||
mPosition = pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the horizontal offset of the y-label
|
||||
*/
|
||||
public float getLabelXOffset() {
|
||||
return mXLabelOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the horizontal offset of the y-label
|
||||
*
|
||||
* @param xOffset
|
||||
*/
|
||||
public void setLabelXOffset(float xOffset) {
|
||||
mXLabelOffset = xOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if drawing the top y-axis label entry is enabled
|
||||
*
|
||||
|
@ -406,6 +427,26 @@ public class YAxis extends AxisBase {
|
|||
float min = dataMin;
|
||||
float max = dataMax;
|
||||
|
||||
// Make sure max is greater than min
|
||||
// Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991
|
||||
if (min > max)
|
||||
{
|
||||
if (mCustomAxisMax && mCustomAxisMin)
|
||||
{
|
||||
float t = min;
|
||||
min = max;
|
||||
max = t;
|
||||
}
|
||||
else if (mCustomAxisMax)
|
||||
{
|
||||
min = max < 0f ? max * 1.5f : max * 0.5f;
|
||||
}
|
||||
else if (mCustomAxisMin)
|
||||
{
|
||||
max = min < 0f ? min * 0.5f : min * 1.5f;
|
||||
}
|
||||
}
|
||||
|
||||
float range = Math.abs(max - min);
|
||||
|
||||
// in case all values are equal
|
||||
|
|
|
@ -4,6 +4,7 @@ package com.github.mikephil.charting.data;
|
|||
import android.graphics.Color;
|
||||
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -38,9 +39,9 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet<BarEntry> impl
|
|||
/**
|
||||
* array of labels used to describe the different values of the stacked bars
|
||||
*/
|
||||
private String[] mStackLabels = new String[]{
|
||||
"Stack"
|
||||
};
|
||||
private String[] mStackLabels = new String[]{};
|
||||
|
||||
protected List<Fill> mFills = null;
|
||||
|
||||
public BarDataSet(List<BarEntry> yVals, String label) {
|
||||
super(yVals, label);
|
||||
|
@ -54,8 +55,8 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet<BarEntry> impl
|
|||
@Override
|
||||
public DataSet<BarEntry> copy() {
|
||||
List<BarEntry> entries = new ArrayList<BarEntry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
BarDataSet copied = new BarDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
@ -71,6 +72,67 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet<BarEntry> impl
|
|||
barDataSet.mHighLightAlpha = mHighLightAlpha;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Fill> getFills() {
|
||||
return mFills;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fill getFill(int index) {
|
||||
return mFills.get(index % mFills.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use getFills() instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public List<Fill> getGradients() {
|
||||
return mFills;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use getFill(...) instead.
|
||||
*
|
||||
* @param index
|
||||
*/
|
||||
@Deprecated
|
||||
public Fill getGradient(int index) {
|
||||
return getFill(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start and end color for gradient color, ONLY color that should be used for this DataSet.
|
||||
*
|
||||
* @param startColor
|
||||
* @param endColor
|
||||
*/
|
||||
public void setGradientColor(int startColor, int endColor) {
|
||||
mFills.clear();
|
||||
mFills.add(new Fill(startColor, endColor));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use setFills(...) instead.
|
||||
*
|
||||
* @param gradientColors
|
||||
*/
|
||||
@Deprecated
|
||||
public void setGradientColors(List<Fill> gradientColors) {
|
||||
this.mFills = gradientColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fills for the bars in this dataset.
|
||||
*
|
||||
* @param fills
|
||||
*/
|
||||
public void setFills(List<Fill> fills) {
|
||||
this.mFills = fills;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total number of entries this DataSet represents, including
|
||||
* stacks. All values belonging to a stack are calculated separately.
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.github.mikephil.charting.components.Legend;
|
|||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
|
||||
import com.github.mikephil.charting.model.GradientColor;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
|
@ -29,10 +28,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
*/
|
||||
protected List<Integer> mColors = null;
|
||||
|
||||
protected GradientColor mGradientColor = null;
|
||||
|
||||
protected List<GradientColor> mGradientColors = null;
|
||||
|
||||
/**
|
||||
* List representing all colors that are used for drawing the actual values for this DataSet
|
||||
*/
|
||||
|
@ -146,21 +141,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
return mColors.get(index % mColors.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
public GradientColor getGradientColor() {
|
||||
return mGradientColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GradientColor> getGradientColors() {
|
||||
return mGradientColors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GradientColor getGradientColor(int index) {
|
||||
return mGradientColors.get(index % mGradientColors.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* ###### ###### COLOR SETTING RELATED METHODS ##### ######
|
||||
*/
|
||||
|
@ -236,25 +216,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
mColors.add(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start and end color for gradient color, ONLY color that should be used for this DataSet.
|
||||
*
|
||||
* @param startColor
|
||||
* @param endColor
|
||||
*/
|
||||
public void setGradientColor(int startColor, int endColor) {
|
||||
mGradientColor = new GradientColor(startColor, endColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the start and end color for gradient colors, ONLY color that should be used for this DataSet.
|
||||
*
|
||||
* @param gradientColors
|
||||
*/
|
||||
public void setGradientColors(List<GradientColor> gradientColors) {
|
||||
this.mGradientColors = gradientColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a color with a specific alpha value.
|
||||
*
|
||||
|
@ -534,8 +495,6 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
|
|||
baseDataSet.mFormLineDashEffect = mFormLineDashEffect;
|
||||
baseDataSet.mFormLineWidth = mFormLineWidth;
|
||||
baseDataSet.mFormSize = mFormSize;
|
||||
baseDataSet.mGradientColor = mGradientColor;
|
||||
baseDataSet.mGradientColors = mGradientColors;
|
||||
baseDataSet.mHighlightEnabled = mHighlightEnabled;
|
||||
baseDataSet.mIconsOffset = mIconsOffset;
|
||||
baseDataSet.mValueColors = mValueColors;
|
||||
|
|
|
@ -42,8 +42,8 @@ public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet<BubbleEntry
|
|||
@Override
|
||||
public DataSet<BubbleEntry> copy() {
|
||||
List<BubbleEntry> entries = new ArrayList<BubbleEntry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
BubbleDataSet copied = new BubbleDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
|
|
@ -80,8 +80,8 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet<CandleEntry> im
|
|||
@Override
|
||||
public DataSet<CandleEntry> copy() {
|
||||
List<CandleEntry> entries = new ArrayList<CandleEntry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
CandleDataSet copied = new CandleDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
|
|
@ -399,7 +399,7 @@ public abstract class ChartData<T extends IDataSet<? extends Entry>> {
|
|||
|
||||
// if a DataSet was removed
|
||||
if (removed) {
|
||||
calcMinMax();
|
||||
notifyDataChanged();
|
||||
}
|
||||
|
||||
return removed;
|
||||
|
@ -526,7 +526,7 @@ public abstract class ChartData<T extends IDataSet<? extends Entry>> {
|
|||
boolean removed = set.removeEntry(e);
|
||||
|
||||
if (removed) {
|
||||
calcMinMax();
|
||||
notifyDataChanged();
|
||||
}
|
||||
|
||||
return removed;
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.github.mikephil.charting.data;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.mikephil.charting.components.YAxis;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet;
|
||||
|
||||
|
@ -91,18 +92,26 @@ public class CombinedData extends BarLineScatterCandleBubbleData<IBarLineScatter
|
|||
if (data.getXMin() < mXMin)
|
||||
mXMin = data.getXMin();
|
||||
|
||||
if (data.mLeftAxisMax > mLeftAxisMax)
|
||||
mLeftAxisMax = data.mLeftAxisMax;
|
||||
for (IBarLineScatterCandleBubbleDataSet<? extends Entry> dataset : sets) {
|
||||
if (dataset.getAxisDependency() == YAxis.AxisDependency.LEFT) {
|
||||
if (dataset.getYMax() > mLeftAxisMax) {
|
||||
mLeftAxisMax = dataset.getYMax();
|
||||
}
|
||||
|
||||
if (data.mLeftAxisMin < mLeftAxisMin)
|
||||
mLeftAxisMin = data.mLeftAxisMin;
|
||||
|
||||
if (data.mRightAxisMax > mRightAxisMax)
|
||||
mRightAxisMax = data.mRightAxisMax;
|
||||
|
||||
if (data.mRightAxisMin < mRightAxisMin)
|
||||
mRightAxisMin = data.mRightAxisMin;
|
||||
if (dataset.getYMin() < mLeftAxisMin) {
|
||||
mLeftAxisMin = dataset.getYMin();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (dataset.getYMax() > mRightAxisMax) {
|
||||
mRightAxisMax = dataset.getYMax();
|
||||
}
|
||||
|
||||
if (dataset.getYMin() < mRightAxisMin) {
|
||||
mRightAxisMin = dataset.getYMin();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
/**
|
||||
* the entries that this DataSet represents / holds together
|
||||
*/
|
||||
protected List<T> mValues = null;
|
||||
protected List<T> mEntries;
|
||||
|
||||
/**
|
||||
* maximum y-value in the value array
|
||||
|
@ -45,15 +45,15 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
* label that describes the DataSet can be specified. The label can also be
|
||||
* used to retrieve the DataSet from a ChartData object.
|
||||
*
|
||||
* @param values
|
||||
* @param entries
|
||||
* @param label
|
||||
*/
|
||||
public DataSet(List<T> values, String label) {
|
||||
public DataSet(List<T> entries, String label) {
|
||||
super(label);
|
||||
this.mValues = values;
|
||||
this.mEntries = entries;
|
||||
|
||||
if (mValues == null)
|
||||
mValues = new ArrayList<T>();
|
||||
if (mEntries == null)
|
||||
mEntries = new ArrayList<T>();
|
||||
|
||||
calcMinMax();
|
||||
}
|
||||
|
@ -61,35 +61,36 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
@Override
|
||||
public void calcMinMax() {
|
||||
|
||||
if (mValues == null || mValues.isEmpty())
|
||||
return;
|
||||
|
||||
mYMax = -Float.MAX_VALUE;
|
||||
mYMin = Float.MAX_VALUE;
|
||||
mXMax = -Float.MAX_VALUE;
|
||||
mXMin = Float.MAX_VALUE;
|
||||
|
||||
for (T e : mValues) {
|
||||
if (mEntries == null || mEntries.isEmpty())
|
||||
return;
|
||||
|
||||
for (T e : mEntries) {
|
||||
calcMinMax(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calcMinMaxY(float fromX, float toX) {
|
||||
|
||||
if (mValues == null || mValues.isEmpty())
|
||||
return;
|
||||
|
||||
mYMax = -Float.MAX_VALUE;
|
||||
mYMin = Float.MAX_VALUE;
|
||||
|
||||
if (mEntries == null || mEntries.isEmpty())
|
||||
return;
|
||||
|
||||
int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN);
|
||||
int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP);
|
||||
|
||||
if (indexTo < indexFrom) return;
|
||||
|
||||
for (int i = indexFrom; i <= indexTo; i++) {
|
||||
|
||||
// only recalculate y
|
||||
calcMinMaxY(mValues.get(i));
|
||||
calcMinMaxY(mEntries.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +129,18 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
|
||||
@Override
|
||||
public int getEntryCount() {
|
||||
return mValues.size();
|
||||
return mEntries.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use getEntries() instead.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public List<T> getValues() {
|
||||
return mEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,8 +148,19 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public List<T> getValues() {
|
||||
return mValues;
|
||||
public List<T> getEntries() {
|
||||
return mEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use setEntries(...) instead.
|
||||
*
|
||||
* @param values
|
||||
*/
|
||||
@Deprecated
|
||||
public void setValues(List<T> values) {
|
||||
setEntries(values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,8 +168,8 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public void setValues(List<T> values) {
|
||||
mValues = values;
|
||||
public void setEntries(List<T> entries) {
|
||||
mEntries = entries;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
@ -169,8 +192,8 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
public String toString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(toSimpleString());
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
buffer.append(mValues.get(i).toString() + " ");
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
buffer.append(mEntries.get(i).toString() + " ");
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
@ -183,7 +206,7 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
*/
|
||||
public String toSimpleString() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mValues.size() +
|
||||
buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mEntries.size() +
|
||||
"\n");
|
||||
return buffer.toString();
|
||||
}
|
||||
|
@ -214,23 +237,23 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
if (e == null)
|
||||
return;
|
||||
|
||||
if (mValues == null) {
|
||||
mValues = new ArrayList<T>();
|
||||
if (mEntries == null) {
|
||||
mEntries = new ArrayList<T>();
|
||||
}
|
||||
|
||||
calcMinMax(e);
|
||||
|
||||
if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) {
|
||||
if (mEntries.size() > 0 && mEntries.get(mEntries.size() - 1).getX() > e.getX()) {
|
||||
int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP);
|
||||
mValues.add(closestIndex, e);
|
||||
mEntries.add(closestIndex, e);
|
||||
} else {
|
||||
mValues.add(e);
|
||||
mEntries.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
mValues.clear();
|
||||
mEntries.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
@ -240,9 +263,9 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
if (e == null)
|
||||
return false;
|
||||
|
||||
List<T> values = getValues();
|
||||
List<T> values = getEntries();
|
||||
if (values == null) {
|
||||
values = new ArrayList<T>();
|
||||
values = new ArrayList<>();
|
||||
}
|
||||
|
||||
calcMinMax(e);
|
||||
|
@ -257,11 +280,11 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
if (e == null)
|
||||
return false;
|
||||
|
||||
if (mValues == null)
|
||||
if (mEntries == null)
|
||||
return false;
|
||||
|
||||
// remove the entry
|
||||
boolean removed = mValues.remove(e);
|
||||
boolean removed = mEntries.remove(e);
|
||||
|
||||
if (removed) {
|
||||
calcMinMax();
|
||||
|
@ -272,7 +295,7 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
|
||||
@Override
|
||||
public int getEntryIndex(Entry e) {
|
||||
return mValues.indexOf(e);
|
||||
return mEntries.indexOf(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -280,7 +303,7 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
|
||||
int index = getEntryIndex(xValue, closestToY, rounding);
|
||||
if (index > -1)
|
||||
return mValues.get(index);
|
||||
return mEntries.get(index);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -291,24 +314,24 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
|
||||
@Override
|
||||
public T getEntryForIndex(int index) {
|
||||
return mValues.get(index);
|
||||
return mEntries.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEntryIndex(float xValue, float closestToY, Rounding rounding) {
|
||||
|
||||
if (mValues == null || mValues.isEmpty())
|
||||
if (mEntries == null || mEntries.isEmpty())
|
||||
return -1;
|
||||
|
||||
int low = 0;
|
||||
int high = mValues.size() - 1;
|
||||
int high = mEntries.size() - 1;
|
||||
int closest = high;
|
||||
|
||||
while (low < high) {
|
||||
int m = (low + high) / 2;
|
||||
|
||||
final float d1 = mValues.get(m).getX() - xValue,
|
||||
d2 = mValues.get(m + 1).getX() - xValue,
|
||||
final float d1 = mEntries.get(m).getX() - xValue,
|
||||
d2 = mEntries.get(m + 1).getX() - xValue,
|
||||
ad1 = Math.abs(d1), ad2 = Math.abs(d2);
|
||||
|
||||
if (ad2 < ad1) {
|
||||
|
@ -335,10 +358,10 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
}
|
||||
|
||||
if (closest != -1) {
|
||||
float closestXValue = mValues.get(closest).getX();
|
||||
float closestXValue = mEntries.get(closest).getX();
|
||||
if (rounding == Rounding.UP) {
|
||||
// If rounding up, and found x-value is lower than specified x, and we can go upper...
|
||||
if (closestXValue < xValue && closest < mValues.size() - 1) {
|
||||
if (closestXValue < xValue && closest < mEntries.size() - 1) {
|
||||
++closest;
|
||||
}
|
||||
} else if (rounding == Rounding.DOWN) {
|
||||
|
@ -350,23 +373,23 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
|
||||
// Search by closest to y-value
|
||||
if (!Float.isNaN(closestToY)) {
|
||||
while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue)
|
||||
while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue)
|
||||
closest -= 1;
|
||||
|
||||
float closestYValue = mValues.get(closest).getY();
|
||||
float closestYValue = mEntries.get(closest).getY();
|
||||
int closestYIndex = closest;
|
||||
|
||||
while (true) {
|
||||
closest += 1;
|
||||
if (closest >= mValues.size())
|
||||
if (closest >= mEntries.size())
|
||||
break;
|
||||
|
||||
final Entry value = mValues.get(closest);
|
||||
final Entry value = mEntries.get(closest);
|
||||
|
||||
if (value.getX() != closestXValue)
|
||||
break;
|
||||
|
||||
if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) {
|
||||
if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) {
|
||||
closestYValue = closestToY;
|
||||
closestYIndex = closest;
|
||||
}
|
||||
|
@ -385,22 +408,22 @@ public abstract class DataSet<T extends Entry> extends BaseDataSet<T> {
|
|||
List<T> entries = new ArrayList<T>();
|
||||
|
||||
int low = 0;
|
||||
int high = mValues.size() - 1;
|
||||
int high = mEntries.size() - 1;
|
||||
|
||||
while (low <= high) {
|
||||
int m = (high + low) / 2;
|
||||
T entry = mValues.get(m);
|
||||
T entry = mEntries.get(m);
|
||||
|
||||
// if we have a match
|
||||
if (xValue == entry.getX()) {
|
||||
while (m > 0 && mValues.get(m - 1).getX() == xValue)
|
||||
while (m > 0 && mEntries.get(m - 1).getX() == xValue)
|
||||
m--;
|
||||
|
||||
high = mValues.size();
|
||||
high = mEntries.size();
|
||||
|
||||
// loop over all "equal" entries
|
||||
for (; m < high; m++) {
|
||||
entry = mValues.get(m);
|
||||
entry = mEntries.get(m);
|
||||
if (entry.getX() == xValue) {
|
||||
entries.add(entry);
|
||||
} else {
|
||||
|
|
|
@ -85,8 +85,8 @@ public class LineDataSet extends LineRadarDataSet<Entry> implements ILineDataSet
|
|||
@Override
|
||||
public DataSet<Entry> copy() {
|
||||
List<Entry> entries = new ArrayList<Entry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
LineDataSet copied = new LineDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.List;
|
|||
*/
|
||||
public abstract class LineRadarDataSet<T extends Entry> extends LineScatterCandleRadarDataSet<T> implements ILineRadarDataSet<T> {
|
||||
|
||||
// TODO: Move to using `Fill` class
|
||||
/**
|
||||
* the color that is used for filling the line surface
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
package com.github.mikephil.charting.data;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IPieDataSet;
|
||||
|
||||
|
@ -46,6 +48,18 @@ public class PieData extends ChartData<IPieDataSet> {
|
|||
return mDataSets.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IPieDataSet> getDataSets() {
|
||||
List<IPieDataSet> dataSets = super.getDataSets();
|
||||
|
||||
if (dataSets.size() < 1) {
|
||||
Log.e("MPAndroidChart",
|
||||
"Found multiple data sets while pie chart only allows one");
|
||||
}
|
||||
|
||||
return dataSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* The PieData object can only have one DataSet. Use getDataSet() method instead.
|
||||
*
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.github.mikephil.charting.data;
|
|||
|
||||
import com.github.mikephil.charting.interfaces.datasets.IPieDataSet;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -22,13 +23,14 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
|
|||
|
||||
private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE;
|
||||
private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE;
|
||||
private boolean mUsingSliceColorAsValueLineColor = false;
|
||||
private int mValueLineColor = 0xff000000;
|
||||
private boolean mUseValueColorForLine = false;
|
||||
private float mValueLineWidth = 1.0f;
|
||||
private float mValueLinePart1OffsetPercentage = 75.f;
|
||||
private float mValueLinePart1Length = 0.3f;
|
||||
private float mValueLinePart2Length = 0.4f;
|
||||
private boolean mValueLineVariableLength = true;
|
||||
private Integer mHighlightColor = null;
|
||||
|
||||
public PieDataSet(List<PieEntry> yVals, String label) {
|
||||
super(yVals, label);
|
||||
|
@ -38,8 +40,8 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
|
|||
@Override
|
||||
public DataSet<PieEntry> copy() {
|
||||
List<PieEntry> entries = new ArrayList<>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
PieDataSet copied = new PieDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
@ -135,15 +137,23 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
|
|||
}
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice, use slice colors as line color if true
|
||||
* This method is deprecated.
|
||||
* Use isUseValueColorForLineEnabled() instead.
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean isUsingSliceColorAsValueLineColor() {
|
||||
return mUsingSliceColorAsValueLineColor;
|
||||
return isUseValueColorForLineEnabled();
|
||||
}
|
||||
|
||||
public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLineColor) {
|
||||
this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor;
|
||||
/**
|
||||
* This method is deprecated.
|
||||
* Use setUseValueColorForLine(...) instead.
|
||||
*
|
||||
* @param enabled
|
||||
*/
|
||||
@Deprecated
|
||||
public void setUsingSliceColorAsValueLineColor(boolean enabled) {
|
||||
setUseValueColorForLine(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,6 +168,17 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
|
|||
this.mValueLineColor = valueLineColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseValueColorForLineEnabled()
|
||||
{
|
||||
return mUseValueColorForLine;
|
||||
}
|
||||
|
||||
public void setUseValueColorForLine(boolean enabled)
|
||||
{
|
||||
mUseValueColorForLine = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice, indicates line width
|
||||
*/
|
||||
|
@ -218,6 +239,21 @@ public class PieDataSet extends DataSet<PieEntry> implements IPieDataSet {
|
|||
this.mValueLineVariableLength = valueLineVariableLength;
|
||||
}
|
||||
|
||||
/** Gets the color for the highlighted sector */
|
||||
@Override
|
||||
@Nullable
|
||||
public Integer getHighlightColor()
|
||||
{
|
||||
return mHighlightColor;
|
||||
}
|
||||
|
||||
/** Sets the color for the highlighted sector (null for using entry color) */
|
||||
public void setHighlightColor(@Nullable Integer color)
|
||||
{
|
||||
this.mHighlightColor = color;
|
||||
}
|
||||
|
||||
|
||||
public enum ValuePosition {
|
||||
INSIDE_SLICE,
|
||||
OUTSIDE_SLICE
|
||||
|
|
|
@ -102,8 +102,8 @@ public class RadarDataSet extends LineRadarDataSet<RadarEntry> implements IRadar
|
|||
@Override
|
||||
public DataSet<RadarEntry> copy() {
|
||||
List<RadarEntry> entries = new ArrayList<RadarEntry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
RadarDataSet copied = new RadarDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
|
|
@ -48,8 +48,8 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet<Entry> impleme
|
|||
@Override
|
||||
public DataSet<Entry> copy() {
|
||||
List<Entry> entries = new ArrayList<Entry>();
|
||||
for (int i = 0; i < mValues.size(); i++) {
|
||||
entries.add(mValues.get(i).copy());
|
||||
for (int i = 0; i < mEntries.size(); i++) {
|
||||
entries.add(mEntries.get(i).copy());
|
||||
}
|
||||
ScatterDataSet copied = new ScatterDataSet(entries, getLabel());
|
||||
copy(copied);
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
|
||||
package com.github.mikephil.charting.data.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Implemented according to modified Douglas Peucker {@link}
|
||||
* http://psimpl.sourceforge.net/douglas-peucker.html
|
||||
*/
|
||||
public class ApproximatorN
|
||||
{
|
||||
public float[] reduceWithDouglasPeucker(float[] points, float resultCount) {
|
||||
|
||||
int pointCount = points.length / 2;
|
||||
|
||||
// if a shape has 2 or less points it cannot be reduced
|
||||
if (resultCount <= 2 || resultCount >= pointCount)
|
||||
return points;
|
||||
|
||||
boolean[] keep = new boolean[pointCount];
|
||||
|
||||
// first and last always stay
|
||||
keep[0] = true;
|
||||
keep[pointCount - 1] = true;
|
||||
|
||||
int currentStoredPoints = 2;
|
||||
|
||||
ArrayList<Line> queue = new ArrayList<>();
|
||||
Line line = new Line(0, pointCount - 1, points);
|
||||
queue.add(line);
|
||||
|
||||
do {
|
||||
line = queue.remove(queue.size() - 1);
|
||||
|
||||
// store the key
|
||||
keep[line.index] = true;
|
||||
|
||||
// check point count tolerance
|
||||
currentStoredPoints += 1;
|
||||
|
||||
if (currentStoredPoints == resultCount)
|
||||
break;
|
||||
|
||||
// split the polyline at the key and recurse
|
||||
Line left = new Line(line.start, line.index, points);
|
||||
if (left.index > 0) {
|
||||
int insertionIndex = insertionIndex(left, queue);
|
||||
queue.add(insertionIndex, left);
|
||||
}
|
||||
|
||||
Line right = new Line(line.index, line.end, points);
|
||||
if (right.index > 0) {
|
||||
int insertionIndex = insertionIndex(right, queue);
|
||||
queue.add(insertionIndex, right);
|
||||
}
|
||||
} while (queue.isEmpty());
|
||||
|
||||
float[] reducedEntries = new float[currentStoredPoints * 2];
|
||||
|
||||
for (int i = 0, i2 = 0, r2 = 0; i < currentStoredPoints; i++, r2 += 2) {
|
||||
if (keep[i]) {
|
||||
reducedEntries[i2++] = points[r2];
|
||||
reducedEntries[i2++] = points[r2 + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return reducedEntries;
|
||||
}
|
||||
|
||||
private static float distanceToLine(
|
||||
float ptX, float ptY, float[]
|
||||
fromLinePoint1, float[] fromLinePoint2) {
|
||||
float dx = fromLinePoint2[0] - fromLinePoint1[0];
|
||||
float dy = fromLinePoint2[1] - fromLinePoint1[1];
|
||||
|
||||
float dividend = Math.abs(
|
||||
dy * ptX -
|
||||
dx * ptY -
|
||||
fromLinePoint1[0] * fromLinePoint2[1] +
|
||||
fromLinePoint2[0] * fromLinePoint1[1]);
|
||||
double divisor = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
return (float)(dividend / divisor);
|
||||
}
|
||||
|
||||
private static class Line {
|
||||
int start;
|
||||
int end;
|
||||
|
||||
float distance = 0;
|
||||
int index = 0;
|
||||
|
||||
Line(int start, int end, float[] points) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
||||
float[] startPoint = new float[]{points[start * 2], points[start * 2 + 1]};
|
||||
float[] endPoint = new float[]{points[end * 2], points[end * 2 + 1]};
|
||||
|
||||
if (end <= start + 1) return;
|
||||
|
||||
for (int i = start + 1, i2 = i * 2; i < end; i++, i2 += 2) {
|
||||
float distance = distanceToLine(
|
||||
points[i2], points[i2 + 1],
|
||||
startPoint, endPoint);
|
||||
|
||||
if (distance > this.distance) {
|
||||
this.index = i;
|
||||
this.distance = distance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean equals(final Line rhs) {
|
||||
return (start == rhs.start) && (end == rhs.end) && index == rhs.index;
|
||||
}
|
||||
|
||||
boolean lessThan(final Line rhs) {
|
||||
return distance < rhs.distance;
|
||||
}
|
||||
}
|
||||
|
||||
private static int insertionIndex(Line line, ArrayList<Line> queue) {
|
||||
int min = 0;
|
||||
int max = queue.size();
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
int midIndex = min + (max - min) / 2;
|
||||
Line midLine = queue.get(midIndex);
|
||||
|
||||
if (midLine.equals(line)) {
|
||||
return midIndex;
|
||||
}
|
||||
else if (line.lessThan(midLine)) {
|
||||
// perform search in left half
|
||||
max = midIndex;
|
||||
}
|
||||
else {
|
||||
// perform search in right half
|
||||
min = midIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import java.text.DecimalFormat;
|
|||
|
||||
/**
|
||||
* This IValueFormatter is just for convenience and simply puts a "%" sign after
|
||||
* each value. (Recommeded for PieChart)
|
||||
* each value. (Recommended for PieChart)
|
||||
*
|
||||
* @author Philipp Jahoda
|
||||
*/
|
||||
|
@ -16,9 +16,11 @@ public class PercentFormatter extends ValueFormatter
|
|||
|
||||
public DecimalFormat mFormat;
|
||||
private PieChart pieChart;
|
||||
private boolean percentSignSeparated;
|
||||
|
||||
public PercentFormatter() {
|
||||
mFormat = new DecimalFormat("###,###,##0.0");
|
||||
percentSignSeparated = true;
|
||||
}
|
||||
|
||||
// Can be used to remove percent signs if the chart isn't in percent mode
|
||||
|
@ -27,9 +29,15 @@ public class PercentFormatter extends ValueFormatter
|
|||
this.pieChart = pieChart;
|
||||
}
|
||||
|
||||
// Can be used to remove percent signs if the chart isn't in percent mode
|
||||
public PercentFormatter(PieChart pieChart, boolean percentSignSeparated) {
|
||||
this(pieChart);
|
||||
this.percentSignSeparated = percentSignSeparated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormattedValue(float value) {
|
||||
return mFormat.format(value) + " %";
|
||||
return mFormat.format(value) + (percentSignSeparated ? " %" : "%");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -60,10 +60,18 @@ public class Highlight {
|
|||
*/
|
||||
private float mDrawY;
|
||||
|
||||
public Highlight(float x, float y, int dataSetIndex, int dataIndex) {
|
||||
this.mX = x;
|
||||
this.mY = y;
|
||||
this.mDataSetIndex = dataSetIndex;
|
||||
this.mDataIndex = dataIndex;
|
||||
}
|
||||
|
||||
public Highlight(float x, float y, int dataSetIndex) {
|
||||
this.mX = x;
|
||||
this.mY = y;
|
||||
this.mDataSetIndex = dataSetIndex;
|
||||
this.mDataIndex = -1;
|
||||
}
|
||||
|
||||
public Highlight(float x, int dataSetIndex, int stackIndex) {
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
package com.github.mikephil.charting.interfaces.datasets;
|
||||
|
||||
import com.github.mikephil.charting.data.BarEntry;
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by philipp on 21/10/15.
|
||||
*/
|
||||
public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet<BarEntry> {
|
||||
|
||||
List<Fill> getFills();
|
||||
|
||||
Fill getFill(int index);
|
||||
|
||||
/**
|
||||
* Returns true if this DataSet is stacked (stacksize > 1) or not.
|
||||
*
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.github.mikephil.charting.data.DataSet;
|
|||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.formatter.ValueFormatter;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.github.mikephil.charting.model.GradientColor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -285,28 +284,6 @@ public interface IDataSet<T extends Entry> {
|
|||
*/
|
||||
int getColor();
|
||||
|
||||
/**
|
||||
* Returns the Gradient color model
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
GradientColor getGradientColor();
|
||||
|
||||
/**
|
||||
* Returns the Gradient colors
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<GradientColor> getGradientColors();
|
||||
|
||||
/**
|
||||
* Returns the Gradient colors
|
||||
*
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
GradientColor getGradientColor(int index);
|
||||
|
||||
/**
|
||||
* Returns the color at the given index of the DataSet's color array.
|
||||
* Performs a IndexOutOfBounds check by modulus.
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.github.mikephil.charting.interfaces.datasets;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.github.mikephil.charting.data.PieDataSet;
|
||||
import com.github.mikephil.charting.data.PieEntry;
|
||||
|
||||
|
@ -35,16 +37,16 @@ public interface IPieDataSet extends IDataSet<PieEntry> {
|
|||
PieDataSet.ValuePosition getXValuePosition();
|
||||
PieDataSet.ValuePosition getYValuePosition();
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice, use slice colors as line color if true
|
||||
* */
|
||||
boolean isUsingSliceColorAsValueLineColor();
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice, indicates line color
|
||||
* */
|
||||
int getValueLineColor();
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice and enabled, line will have the same color as the slice
|
||||
* */
|
||||
boolean isUseValueColorForLineEnabled();
|
||||
|
||||
/**
|
||||
* When valuePosition is OutsideSlice, indicates line width
|
||||
* */
|
||||
|
@ -70,5 +72,11 @@ public interface IPieDataSet extends IDataSet<PieEntry> {
|
|||
* */
|
||||
boolean isValueLineVariableLength();
|
||||
|
||||
/**
|
||||
* Gets the color for the highlighted sector
|
||||
* */
|
||||
@Nullable
|
||||
Integer getHighlightColor();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -580,12 +580,19 @@ public class BarLineChartTouchListener extends ChartTouchListener<BarLineChartBa
|
|||
|
||||
MPPointF trans = getTrans(e.getX(), e.getY());
|
||||
|
||||
mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y);
|
||||
float scaleX = mChart.isScaleXEnabled() ? 1.4f : 1f;
|
||||
float scaleY = mChart.isScaleYEnabled() ? 1.4f : 1f;
|
||||
|
||||
mChart.zoom(scaleX, scaleY, trans.x, trans.y);
|
||||
|
||||
if (mChart.isLogEnabled())
|
||||
Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: "
|
||||
+ trans.y);
|
||||
|
||||
if (l != null) {
|
||||
l.onChartScale(e, scaleX, scaleY);
|
||||
}
|
||||
|
||||
MPPointF.recycleInstance(trans);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ public interface OnChartGestureListener {
|
|||
void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY);
|
||||
|
||||
/**
|
||||
* Callbacks when the chart is scaled / zoomed via pinch zoom gesture.
|
||||
* Callbacks when the chart is scaled / zoomed via pinch zoom / double-tap gesture.
|
||||
*
|
||||
* @param me
|
||||
* @param scaleX scalefactor on the x-axis
|
||||
|
|
|
@ -1,28 +1,69 @@
|
|||
package com.github.mikephil.charting.model;
|
||||
|
||||
public class GradientColor {
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
|
||||
private int startColor;
|
||||
private int endColor;
|
||||
|
||||
public GradientColor(int startColor, int endColor) {
|
||||
this.startColor = startColor;
|
||||
this.endColor = endColor;
|
||||
/**
|
||||
* Deprecated. Use `Fill`
|
||||
*/
|
||||
@Deprecated
|
||||
public class GradientColor extends Fill
|
||||
{
|
||||
/**
|
||||
* Deprecated. Use `Fill.getGradientColors()`
|
||||
*/
|
||||
@Deprecated
|
||||
public int getStartColor()
|
||||
{
|
||||
return getGradientColors()[0];
|
||||
}
|
||||
|
||||
public int getStartColor() {
|
||||
return startColor;
|
||||
/**
|
||||
* Deprecated. Use `Fill.setGradientColors(...)`
|
||||
*/
|
||||
@Deprecated
|
||||
public void setStartColor(int startColor)
|
||||
{
|
||||
if (getGradientColors() == null || getGradientColors().length != 2)
|
||||
{
|
||||
setGradientColors(new int[]{
|
||||
startColor,
|
||||
getGradientColors() != null && getGradientColors().length > 1
|
||||
? getGradientColors()[1]
|
||||
: 0
|
||||
});
|
||||
} else
|
||||
{
|
||||
getGradientColors()[0] = startColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void setStartColor(int startColor) {
|
||||
this.startColor = startColor;
|
||||
/**
|
||||
* Deprecated. Use `Fill.getGradientColors()`
|
||||
*/
|
||||
@Deprecated
|
||||
public int getEndColor()
|
||||
{
|
||||
return getGradientColors()[1];
|
||||
}
|
||||
|
||||
public int getEndColor() {
|
||||
return endColor;
|
||||
/**
|
||||
* Deprecated. Use `Fill.setGradientColors(...)`
|
||||
*/
|
||||
@Deprecated
|
||||
public void setEndColor(int endColor)
|
||||
{
|
||||
if (getGradientColors() == null || getGradientColors().length != 2)
|
||||
{
|
||||
setGradientColors(new int[]{
|
||||
getGradientColors() != null && getGradientColors().length > 0
|
||||
? getGradientColors()[0]
|
||||
: 0,
|
||||
endColor
|
||||
});
|
||||
} else
|
||||
{
|
||||
getGradientColors()[1] = endColor;
|
||||
}
|
||||
}
|
||||
|
||||
public void setEndColor(int endColor) {
|
||||
this.endColor = endColor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,9 +174,12 @@ public abstract class AxisRenderer extends Renderer {
|
|||
double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval)));
|
||||
int intervalSigDigit = (int) (interval / intervalMagnitude);
|
||||
if (intervalSigDigit > 5) {
|
||||
// Use one order of magnitude higher, to avoid intervals like 0.9 or
|
||||
// 90
|
||||
interval = Math.floor(10 * intervalMagnitude);
|
||||
// Use one order of magnitude higher, to avoid intervals like 0.9 or 90
|
||||
// if it's 0.0 after floor(), we use the old value
|
||||
interval = Math.floor(10.0 * intervalMagnitude) == 0.0
|
||||
? interval
|
||||
: Math.floor(10.0 * intervalMagnitude);
|
||||
|
||||
}
|
||||
|
||||
int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0;
|
||||
|
@ -214,11 +217,14 @@ public abstract class AxisRenderer extends Renderer {
|
|||
double f;
|
||||
int i;
|
||||
|
||||
if (interval != 0.0) {
|
||||
if (interval != 0.0 && last != first) {
|
||||
for (f = first; f <= last; f += interval) {
|
||||
++n;
|
||||
}
|
||||
}
|
||||
else if (last == first && n == 0) {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
mAxis.mEntryCount = n;
|
||||
|
||||
|
|
|
@ -15,12 +15,11 @@ import com.github.mikephil.charting.highlight.Highlight;
|
|||
import com.github.mikephil.charting.highlight.Range;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
import android.graphics.LinearGradient;
|
||||
import com.github.mikephil.charting.model.GradientColor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -145,13 +144,15 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
|
|||
|
||||
trans.pointValuesToPixel(buffer.buffer);
|
||||
|
||||
final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty();
|
||||
final boolean isSingleColor = dataSet.getColors().size() == 1;
|
||||
final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency());
|
||||
|
||||
if (isSingleColor) {
|
||||
mRenderPaint.setColor(dataSet.getColor());
|
||||
}
|
||||
|
||||
for (int j = 0; j < buffer.size(); j += 4) {
|
||||
for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) {
|
||||
|
||||
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
|
||||
continue;
|
||||
|
@ -162,38 +163,24 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
|
|||
if (!isSingleColor) {
|
||||
// Set the color for the currently drawn value. If the index
|
||||
// is out of bounds, reuse colors.
|
||||
mRenderPaint.setColor(dataSet.getColor(j / 4));
|
||||
mRenderPaint.setColor(dataSet.getColor(pos));
|
||||
}
|
||||
|
||||
if (dataSet.getGradientColor() != null) {
|
||||
GradientColor gradientColor = dataSet.getGradientColor();
|
||||
mRenderPaint.setShader(
|
||||
new LinearGradient(
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 3],
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 1],
|
||||
gradientColor.getStartColor(),
|
||||
gradientColor.getEndColor(),
|
||||
android.graphics.Shader.TileMode.MIRROR));
|
||||
if (isCustomFill) {
|
||||
dataSet.getFill(pos)
|
||||
.fillRect(
|
||||
c, mRenderPaint,
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 1],
|
||||
buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3],
|
||||
isInverted ? Fill.Direction.DOWN : Fill.Direction.UP);
|
||||
}
|
||||
|
||||
if (dataSet.getGradientColors() != null) {
|
||||
mRenderPaint.setShader(
|
||||
new LinearGradient(
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 3],
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 1],
|
||||
dataSet.getGradientColor(j / 4).getStartColor(),
|
||||
dataSet.getGradientColor(j / 4).getEndColor(),
|
||||
android.graphics.Shader.TileMode.MIRROR));
|
||||
else {
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3], mRenderPaint);
|
||||
}
|
||||
|
||||
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3], mRenderPaint);
|
||||
|
||||
if (drawBorder) {
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3], mBarBorderPaint);
|
||||
|
|
|
@ -108,7 +108,7 @@ public class BubbleChartRenderer extends BarLineScatterCandleBubbleRenderer {
|
|||
if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf))
|
||||
break;
|
||||
|
||||
final int color = dataSet.getColor((int) entry.getX());
|
||||
final int color = dataSet.getColor(j);
|
||||
|
||||
mRenderPaint.setColor(color);
|
||||
c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint);
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.github.mikephil.charting.highlight.Highlight;
|
|||
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
|
||||
import com.github.mikephil.charting.utils.Fill;
|
||||
import com.github.mikephil.charting.utils.MPPointF;
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.Utils;
|
||||
|
@ -111,13 +112,15 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
|
|||
|
||||
trans.pointValuesToPixel(buffer.buffer);
|
||||
|
||||
final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty();
|
||||
final boolean isSingleColor = dataSet.getColors().size() == 1;
|
||||
final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency());
|
||||
|
||||
if (isSingleColor) {
|
||||
mRenderPaint.setColor(dataSet.getColor());
|
||||
}
|
||||
|
||||
for (int j = 0; j < buffer.size(); j += 4) {
|
||||
for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) {
|
||||
|
||||
if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3]))
|
||||
break;
|
||||
|
@ -131,8 +134,20 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
|
|||
mRenderPaint.setColor(dataSet.getColor(j / 4));
|
||||
}
|
||||
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3], mRenderPaint);
|
||||
if (isCustomFill) {
|
||||
dataSet.getFill(pos)
|
||||
.fillRect(
|
||||
c, mRenderPaint,
|
||||
buffer.buffer[j],
|
||||
buffer.buffer[j + 1],
|
||||
buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3],
|
||||
isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT);
|
||||
}
|
||||
else {
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
buffer.buffer[j + 3], mRenderPaint);
|
||||
}
|
||||
|
||||
if (drawBorder) {
|
||||
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
|
||||
|
@ -200,7 +215,8 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
|
|||
// calculate the correct offset depending on the draw position of the value
|
||||
float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue);
|
||||
posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus));
|
||||
negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus);
|
||||
negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus)
|
||||
- (buffer.buffer[j + 2] - buffer.buffer[j]);
|
||||
|
||||
if (isInverted) {
|
||||
posOffset = -posOffset - valueTextWidth;
|
||||
|
|
|
@ -90,6 +90,7 @@ public class LegendRenderer extends Renderer {
|
|||
for (int i = 0; i < data.getDataSetCount(); i++) {
|
||||
|
||||
IDataSet dataSet = data.getDataSetByIndex(i);
|
||||
if (dataSet == null) continue;
|
||||
|
||||
List<Integer> clrs = dataSet.getColors();
|
||||
int entryCount = dataSet.getEntryCount();
|
||||
|
@ -100,10 +101,19 @@ public class LegendRenderer extends Renderer {
|
|||
IBarDataSet bds = (IBarDataSet) dataSet;
|
||||
String[] sLabels = bds.getStackLabels();
|
||||
|
||||
for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) {
|
||||
int minEntries = Math.min(clrs.size(), bds.getStackSize());
|
||||
|
||||
for (int j = 0; j < minEntries; j++) {
|
||||
String label;
|
||||
if (sLabels.length > 0) {
|
||||
int labelIndex = j % minEntries;
|
||||
label = labelIndex < sLabels.length ? sLabels[labelIndex] : null;
|
||||
} else {
|
||||
label = null;
|
||||
}
|
||||
|
||||
computedEntries.add(new LegendEntry(
|
||||
sLabels[j % sLabels.length],
|
||||
label,
|
||||
dataSet.getForm(),
|
||||
dataSet.getFormSize(),
|
||||
dataSet.getFormLineWidth(),
|
||||
|
|
|
@ -323,10 +323,14 @@ public class LineChartRenderer extends LineRadarRenderer {
|
|||
// more than 1 color
|
||||
if (dataSet.getColors().size() > 1) {
|
||||
|
||||
if (mLineBuffer.length <= pointsPerEntryPair * 2)
|
||||
mLineBuffer = new float[pointsPerEntryPair * 4];
|
||||
int numberOfFloats = pointsPerEntryPair * 2;
|
||||
|
||||
for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) {
|
||||
if (mLineBuffer.length <= numberOfFloats)
|
||||
mLineBuffer = new float[numberOfFloats * 2];
|
||||
|
||||
int max = mXBounds.min + mXBounds.range;
|
||||
|
||||
for (int j = mXBounds.min; j < max; j++) {
|
||||
|
||||
Entry e = dataSet.getEntryForIndex(j);
|
||||
if (e == null) continue;
|
||||
|
@ -357,16 +361,26 @@ public class LineChartRenderer extends LineRadarRenderer {
|
|||
mLineBuffer[3] = mLineBuffer[1];
|
||||
}
|
||||
|
||||
// Determine the start and end coordinates of the line, and make sure they differ.
|
||||
float firstCoordinateX = mLineBuffer[0];
|
||||
float firstCoordinateY = mLineBuffer[1];
|
||||
float lastCoordinateX = mLineBuffer[numberOfFloats - 2];
|
||||
float lastCoordinateY = mLineBuffer[numberOfFloats - 1];
|
||||
|
||||
if (firstCoordinateX == lastCoordinateX &&
|
||||
firstCoordinateY == lastCoordinateY)
|
||||
continue;
|
||||
|
||||
trans.pointValuesToPixel(mLineBuffer);
|
||||
|
||||
if (!mViewPortHandler.isInBoundsRight(mLineBuffer[0]))
|
||||
if (!mViewPortHandler.isInBoundsRight(firstCoordinateX))
|
||||
break;
|
||||
|
||||
// make sure the lines don't do shitty things outside
|
||||
// bounds
|
||||
if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2])
|
||||
|| (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler
|
||||
.isInBoundsBottom(mLineBuffer[3])))
|
||||
if (!mViewPortHandler.isInBoundsLeft(lastCoordinateX) ||
|
||||
!mViewPortHandler.isInBoundsTop(Math.max(firstCoordinateY, lastCoordinateY)) ||
|
||||
!mViewPortHandler.isInBoundsBottom(Math.min(firstCoordinateY, lastCoordinateY)))
|
||||
continue;
|
||||
|
||||
// get the color that is set for this line-segment
|
||||
|
|
|
@ -258,7 +258,7 @@ public class PieChartRenderer extends DataRenderer {
|
|||
}
|
||||
|
||||
// Don't draw if it's highlighted, unless the chart uses rounded slices
|
||||
if (mChart.needsHighlight(j) && !drawRoundedSlices) {
|
||||
if (dataSet.isHighlightEnabled() && mChart.needsHighlight(j) && !drawRoundedSlices) {
|
||||
angle += sliceAngle * phaseX;
|
||||
continue;
|
||||
}
|
||||
|
@ -468,7 +468,9 @@ public class PieChartRenderer extends DataRenderer {
|
|||
|
||||
int entryCount = dataSet.getEntryCount();
|
||||
|
||||
mValueLinePaint.setColor(dataSet.getValueLineColor());
|
||||
boolean isUseValueColorForLineEnabled = dataSet.isUseValueColorForLineEnabled();
|
||||
int valueLineColor = dataSet.getValueLineColor();
|
||||
|
||||
mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth()));
|
||||
|
||||
final float sliceSpace = getSliceSpace(dataSet);
|
||||
|
@ -565,12 +567,15 @@ public class PieChartRenderer extends DataRenderer {
|
|||
labelPty = pt2y;
|
||||
}
|
||||
|
||||
if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) {
|
||||
int lineColor = ColorTemplate.COLOR_NONE;
|
||||
|
||||
if (dataSet.isUsingSliceColorAsValueLineColor()) {
|
||||
mValueLinePaint.setColor(dataSet.getColor(j));
|
||||
}
|
||||
if (isUseValueColorForLineEnabled)
|
||||
lineColor = dataSet.getColor(j);
|
||||
else if (valueLineColor != ColorTemplate.COLOR_NONE)
|
||||
lineColor = valueLineColor;
|
||||
|
||||
if (lineColor != ColorTemplate.COLOR_NONE) {
|
||||
mValueLinePaint.setColor(lineColor);
|
||||
c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint);
|
||||
c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint);
|
||||
}
|
||||
|
@ -825,8 +830,7 @@ public class PieChartRenderer extends DataRenderer {
|
|||
continue;
|
||||
|
||||
IPieDataSet set = mChart.getData()
|
||||
.getDataSetByIndex(indices[i]
|
||||
.getDataSetIndex());
|
||||
.getDataSetByIndex(indices[i].getDataSetIndex());
|
||||
|
||||
if (set == null || !set.isHighlightEnabled())
|
||||
continue;
|
||||
|
@ -857,7 +861,10 @@ public class PieChartRenderer extends DataRenderer {
|
|||
|
||||
final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f;
|
||||
|
||||
mRenderPaint.setColor(set.getColor(index));
|
||||
Integer highlightColor = set.getHighlightColor();
|
||||
if (highlightColor == null)
|
||||
highlightColor = set.getColor(index);
|
||||
mRenderPaint.setColor(highlightColor);
|
||||
|
||||
final float sliceSpaceAngleOuter = visibleAngleCount == 1 ?
|
||||
0.f :
|
||||
|
|
|
@ -119,12 +119,17 @@ public class YAxisRenderer extends AxisRenderer {
|
|||
? mYAxis.mEntryCount
|
||||
: (mYAxis.mEntryCount - 1);
|
||||
|
||||
float xOffset = mYAxis.getLabelXOffset();
|
||||
|
||||
// draw
|
||||
for (int i = from; i < to; i++) {
|
||||
|
||||
String text = mYAxis.getFormattedLabel(i);
|
||||
|
||||
c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint);
|
||||
c.drawText(text,
|
||||
fixedPosition + xOffset,
|
||||
positions[i * 2 + 1] + offset,
|
||||
mAxisLabelPaint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,11 +142,16 @@ public class YAxisRendererHorizontalBarChart extends YAxisRenderer {
|
|||
? mYAxis.mEntryCount
|
||||
: (mYAxis.mEntryCount - 1);
|
||||
|
||||
float xOffset = mYAxis.getLabelXOffset();
|
||||
|
||||
for (int i = from; i < to; i++) {
|
||||
|
||||
String text = mYAxis.getFormattedLabel(i);
|
||||
|
||||
c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisLabelPaint);
|
||||
c.drawText(text,
|
||||
positions[i * 2],
|
||||
fixedPosition - offset + xOffset,
|
||||
mAxisLabelPaint);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,9 +52,11 @@ public class YAxisRendererRadarChart extends YAxisRenderer {
|
|||
double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval)));
|
||||
int intervalSigDigit = (int) (interval / intervalMagnitude);
|
||||
if (intervalSigDigit > 5) {
|
||||
// Use one order of magnitude higher, to avoid intervals like 0.9 or
|
||||
// 90
|
||||
interval = Math.floor(10 * intervalMagnitude);
|
||||
// Use one order of magnitude higher, to avoid intervals like 0.9 or 90
|
||||
// if it's 0.0 after floor(), we use the old value
|
||||
interval = Math.floor(10.0 * intervalMagnitude) == 0.0
|
||||
? interval
|
||||
: Math.floor(10.0 * intervalMagnitude);
|
||||
}
|
||||
|
||||
boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled();
|
||||
|
@ -161,6 +163,8 @@ public class YAxisRendererRadarChart extends YAxisRenderer {
|
|||
? mYAxis.mEntryCount
|
||||
: (mYAxis.mEntryCount - 1);
|
||||
|
||||
float xOffset = mYAxis.getLabelXOffset();
|
||||
|
||||
for (int j = from; j < to; j++) {
|
||||
|
||||
float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor;
|
||||
|
@ -169,7 +173,7 @@ public class YAxisRendererRadarChart extends YAxisRenderer {
|
|||
|
||||
String label = mYAxis.getFormattedLabel(j);
|
||||
|
||||
c.drawText(label, pOut.x + 10, pOut.y, mAxisLabelPaint);
|
||||
c.drawText(label, pOut.x + xOffset, pOut.y, mAxisLabelPaint);
|
||||
}
|
||||
MPPointF.recycleInstance(center);
|
||||
MPPointF.recycleInstance(pOut);
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
package com.github.mikephil.charting.utils;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class Fill
|
||||
{
|
||||
public enum Type
|
||||
{
|
||||
EMPTY, COLOR, LINEAR_GRADIENT, DRAWABLE
|
||||
}
|
||||
|
||||
public enum Direction
|
||||
{
|
||||
DOWN, UP, RIGHT, LEFT
|
||||
}
|
||||
|
||||
/**
|
||||
* the type of fill
|
||||
*/
|
||||
private Type mType = Type.EMPTY;
|
||||
|
||||
/**
|
||||
* the color that is used for filling
|
||||
*/
|
||||
@Nullable
|
||||
private Integer mColor = null;
|
||||
|
||||
private Integer mFinalColor = null;
|
||||
|
||||
/**
|
||||
* the drawable to be used for filling
|
||||
*/
|
||||
@Nullable
|
||||
protected Drawable mDrawable;
|
||||
|
||||
@Nullable
|
||||
private int[] mGradientColors;
|
||||
|
||||
@Nullable
|
||||
private float[] mGradientPositions;
|
||||
|
||||
/**
|
||||
* transparency used for filling
|
||||
*/
|
||||
private int mAlpha = 255;
|
||||
|
||||
public Fill()
|
||||
{
|
||||
}
|
||||
|
||||
public Fill(int color)
|
||||
{
|
||||
this.mType = Type.COLOR;
|
||||
this.mColor = color;
|
||||
calculateFinalColor();
|
||||
}
|
||||
|
||||
public Fill(int startColor, int endColor)
|
||||
{
|
||||
this.mType = Type.LINEAR_GRADIENT;
|
||||
this.mGradientColors = new int[]{startColor, endColor};
|
||||
}
|
||||
|
||||
public Fill(@NonNull int[] gradientColors)
|
||||
{
|
||||
this.mType = Type.LINEAR_GRADIENT;
|
||||
this.mGradientColors = gradientColors;
|
||||
}
|
||||
|
||||
public Fill(@NonNull int[] gradientColors, @NonNull float[] gradientPositions)
|
||||
{
|
||||
this.mType = Type.LINEAR_GRADIENT;
|
||||
this.mGradientColors = gradientColors;
|
||||
this.mGradientPositions = gradientPositions;
|
||||
}
|
||||
|
||||
public Fill(@NonNull Drawable drawable)
|
||||
{
|
||||
this.mType = Type.DRAWABLE;
|
||||
this.mDrawable = drawable;
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
public void setType(Type type)
|
||||
{
|
||||
this.mType = type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getColor()
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
|
||||
public void setColor(int color)
|
||||
{
|
||||
this.mColor = color;
|
||||
calculateFinalColor();
|
||||
}
|
||||
|
||||
public int[] getGradientColors()
|
||||
{
|
||||
return mGradientColors;
|
||||
}
|
||||
|
||||
public void setGradientColors(int[] colors)
|
||||
{
|
||||
this.mGradientColors = colors;
|
||||
}
|
||||
|
||||
public float[] getGradientPositions()
|
||||
{
|
||||
return mGradientPositions;
|
||||
}
|
||||
|
||||
public void setGradientPositions(float[] positions)
|
||||
{
|
||||
this.mGradientPositions = positions;
|
||||
}
|
||||
|
||||
public void setGradientColors(int startColor, int endColor)
|
||||
{
|
||||
this.mGradientColors = new int[]{startColor, endColor};
|
||||
}
|
||||
|
||||
public int getAlpha()
|
||||
{
|
||||
return mAlpha;
|
||||
}
|
||||
|
||||
public void setAlpha(int alpha)
|
||||
{
|
||||
this.mAlpha = alpha;
|
||||
calculateFinalColor();
|
||||
}
|
||||
|
||||
private void calculateFinalColor()
|
||||
{
|
||||
if (mColor == null)
|
||||
{
|
||||
mFinalColor = null;
|
||||
} else
|
||||
{
|
||||
int alpha = (int) Math.floor(((mColor >> 24) / 255.0) * (mAlpha / 255.0) * 255.0);
|
||||
mFinalColor = (alpha << 24) | (mColor & 0xffffff);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillRect(Canvas c, Paint paint,
|
||||
float left, float top, float right, float bottom,
|
||||
Direction gradientDirection)
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case EMPTY:
|
||||
return;
|
||||
|
||||
case COLOR:
|
||||
{
|
||||
if (mFinalColor == null) return;
|
||||
|
||||
if (isClipPathSupported())
|
||||
{
|
||||
int save = c.save();
|
||||
|
||||
c.clipRect(left, top, right, bottom);
|
||||
c.drawColor(mFinalColor);
|
||||
|
||||
c.restoreToCount(save);
|
||||
}
|
||||
else
|
||||
{
|
||||
// save
|
||||
Paint.Style previous = paint.getStyle();
|
||||
int previousColor = paint.getColor();
|
||||
|
||||
// set
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(mFinalColor);
|
||||
|
||||
c.drawRect(left, top, right, bottom, paint);
|
||||
|
||||
// restore
|
||||
paint.setColor(previousColor);
|
||||
paint.setStyle(previous);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LINEAR_GRADIENT:
|
||||
{
|
||||
if (mGradientColors == null) return;
|
||||
|
||||
LinearGradient gradient = new LinearGradient(
|
||||
(int) (gradientDirection == Direction.RIGHT
|
||||
? right
|
||||
: gradientDirection == Direction.LEFT
|
||||
? left
|
||||
: left),
|
||||
(int) (gradientDirection == Direction.UP
|
||||
? bottom
|
||||
: gradientDirection == Direction.DOWN
|
||||
? top
|
||||
: top),
|
||||
(int) (gradientDirection == Direction.RIGHT
|
||||
? left
|
||||
: gradientDirection == Direction.LEFT
|
||||
? right
|
||||
: left),
|
||||
(int) (gradientDirection == Direction.UP
|
||||
? top
|
||||
: gradientDirection == Direction.DOWN
|
||||
? bottom
|
||||
: top),
|
||||
mGradientColors,
|
||||
mGradientPositions,
|
||||
android.graphics.Shader.TileMode.MIRROR);
|
||||
|
||||
paint.setShader(gradient);
|
||||
|
||||
c.drawRect(left, top, right, bottom, paint);
|
||||
}
|
||||
break;
|
||||
|
||||
case DRAWABLE:
|
||||
{
|
||||
if (mDrawable == null) return;
|
||||
|
||||
mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom);
|
||||
mDrawable.draw(c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void fillPath(Canvas c, Path path, Paint paint,
|
||||
@Nullable RectF clipRect)
|
||||
{
|
||||
switch (mType)
|
||||
{
|
||||
case EMPTY:
|
||||
return;
|
||||
|
||||
case COLOR:
|
||||
{
|
||||
if (mFinalColor == null) return;
|
||||
|
||||
if (clipRect != null && isClipPathSupported())
|
||||
{
|
||||
int save = c.save();
|
||||
|
||||
c.clipPath(path);
|
||||
c.drawColor(mFinalColor);
|
||||
|
||||
c.restoreToCount(save);
|
||||
}
|
||||
else
|
||||
{
|
||||
// save
|
||||
Paint.Style previous = paint.getStyle();
|
||||
int previousColor = paint.getColor();
|
||||
|
||||
// set
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(mFinalColor);
|
||||
|
||||
c.drawPath(path, paint);
|
||||
|
||||
// restore
|
||||
paint.setColor(previousColor);
|
||||
paint.setStyle(previous);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LINEAR_GRADIENT:
|
||||
{
|
||||
if (mGradientColors == null) return;
|
||||
|
||||
LinearGradient gradient = new LinearGradient(
|
||||
0,
|
||||
0,
|
||||
c.getWidth(),
|
||||
c.getHeight(),
|
||||
mGradientColors,
|
||||
mGradientPositions,
|
||||
android.graphics.Shader.TileMode.MIRROR);
|
||||
|
||||
paint.setShader(gradient);
|
||||
|
||||
c.drawPath(path, paint);
|
||||
}
|
||||
break;
|
||||
|
||||
case DRAWABLE:
|
||||
{
|
||||
if (mDrawable == null) return;
|
||||
|
||||
ensureClipPathSupported();
|
||||
|
||||
int save = c.save();
|
||||
c.clipPath(path);
|
||||
|
||||
mDrawable.setBounds(
|
||||
clipRect == null ? 0 : (int) clipRect.left,
|
||||
clipRect == null ? 0 : (int) clipRect.top,
|
||||
clipRect == null ? c.getWidth() : (int) clipRect.right,
|
||||
clipRect == null ? c.getHeight() : (int) clipRect.bottom);
|
||||
mDrawable.draw(c);
|
||||
|
||||
c.restoreToCount(save);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isClipPathSupported()
|
||||
{
|
||||
return Utils.getSDKInt() >= 18;
|
||||
}
|
||||
|
||||
private void ensureClipPathSupported()
|
||||
{
|
||||
if (Utils.getSDKInt() < 18)
|
||||
{
|
||||
throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " +
|
||||
"this code was run on API level " + Utils.getSDKInt() + ".");
|
||||
}
|
||||
}
|
||||
}
|
32
README.md
32
README.md
|
@ -23,23 +23,9 @@
|
|||
1. [License](#licence)
|
||||
1. [Creators](#creators)
|
||||
|
||||
## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart)
|
||||
## [Coding Newsletter](https://weeklycoding.com)
|
||||
|
||||
<img align="left" width="190" height="190" style="margin:0px 15px 0px 0px" src="https://raw.github.com/PhilJay/MPChart/master/design/other/left.png">
|
||||
<img align="right" width="90" height="90" style="margin:0px 15px 0px 0px" src="https://raw.github.com/PhilJay/MPChart/master/design/other/right.png">
|
||||
|
||||
MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend
|
||||
<a href="https://scichart.com/android-chart-features?source=MPAndroidChart" target="_blank">SciChart Android</a>.
|
||||
|
||||
<img align="right" width="270" height="60" style="margin:0px 0px 0px 0px" src="https://raw.github.com/PhilJay/MPChart/master/design/other/bottom.png">
|
||||
|
||||
All MPAndroidChart users are entitled to a special **discount of 5%** off the <a href="https://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART&source=MPAndroidChart" target="_blank">SciChart store</a>, using the following discount code: **MPANDROIDCHART**
|
||||
|
||||
<br/>
|
||||
|
||||
## [Daily Coding Newsletter](https://philjay.substack.com/subscribe)
|
||||
|
||||
Sign up for my [daily coding newsletter](https://philjay.substack.com/subscribe) to get quick updates on Kotlin and Android development related topics.
|
||||
Sign up for my [coding newsletter](https://weeklycoding.com) to get quick updates on Kotlin and Android development related topics.
|
||||
|
||||
<h2 id="quick-start">Quick Start :chart_with_upwards_trend:</h2>
|
||||
|
||||
|
@ -53,7 +39,7 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha'
|
||||
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -70,7 +56,7 @@ dependencies {
|
|||
<dependency>
|
||||
<groupId>com.github.PhilJay</groupId>
|
||||
<artifactId>MPAndroidChart</artifactId>
|
||||
<version>v3.1.0-alpha</version>
|
||||
<version>v3.1.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -78,9 +64,9 @@ dependencies {
|
|||
|
||||
<h2 id="documentation">Documentation :notebook_with_decorative_cover:</h2>
|
||||
|
||||
See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart.
|
||||
See the [**documentation**](https://weeklycoding.com/mpandroidchart/) for examples and general use of MPAndroidChart.
|
||||
|
||||
See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0-alpha/javadoc/) for more advanced documentation.
|
||||
See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/) for more advanced documentation.
|
||||
|
||||
<br/>
|
||||
|
||||
|
@ -96,7 +82,7 @@ Download the [MPAndroidChart Example App](https://play.google.com/store/apps/det
|
|||
|
||||
This repository's issue tracker is only for bugs and feature requests. The maintainers ask that you refrain from asking questions about how to use MPAndroidChart through the issue tracker.
|
||||
|
||||
Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer.
|
||||
Please read the [**documentation**](https://weeklycoding.com/mpandroidchart/) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer.
|
||||
|
||||
<br/>
|
||||
|
||||
|
@ -133,7 +119,7 @@ If you like this library, please tell others about it :two_hearts: :two_hearts:
|
|||
[](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart)
|
||||
[](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart)
|
||||
|
||||
You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**daily coding newsletter**](https://philjay.substack.com/subscribe).
|
||||
You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**coding newsletter**](https://weeklycoding.com).
|
||||
|
||||
<br/>
|
||||
|
||||
|
@ -209,7 +195,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah
|
|||
|
||||
<h1 id="license">License :page_facing_up:</h1>
|
||||
|
||||
Copyright 2018 Philipp Jahoda
|
||||
Copyright 2019 Philipp Jahoda
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
|
@ -2,9 +2,10 @@ buildscript {
|
|||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
|
||||
}
|
||||
}
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Sat Mar 16 11:37:10 CET 2019
|
||||
#Sat Apr 27 15:48:29 CEST 2019
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||
|
|
Loading…
Add table
Reference in a new issue