Compare commits

..

53 commits

Author SHA1 Message Date
yoksnod
a6c3808fd5
Merge pull request #2 from yoksnod/marker-interface-improvements
Added jitpack integration
2020-02-12 14:54:18 +03:00
Dmitry Donskoy
941579e10f Added jitpack integration 2020-02-12 14:53:16 +03:00
yoksnod
21c811ff9a
Merge pull request #1 from yoksnod/marker-interface-improvements
Modified and expanded, made more flexible  marker interaction interface
2020-02-12 14:49:13 +03:00
Dmitry Donskoy
f3a2ec21c9 Modified and expanded, made more flexible marker interaction interface 2020-02-12 14:47:18 +03:00
Daniel Cohen Gindi
9347dd1af7
Merge pull request #4802 from oatrice/fix_crash_solid_color_barchart
fix NPE when use solid color with barchart
2020-02-09 07:34:02 +02:00
Anirut Teerabut
90e523042c
Update BarChartRenderer.java 2020-02-07 22:09:57 +07:00
Anirut Teerabut
33240f9225
Update HorizontalBarChartRenderer.java 2020-02-07 22:09:07 +07:00
Anirut Teerabut
4b67673da9
Update BarChartRenderer.java 2020-02-07 22:03:20 +07:00
Anirut Teerabut
cef967fd71 fix NPE when use solid color with barchart 2020-02-07 17:53:40 +07:00
Daniel Cohen Gindi
eae977306e Merge branch 'fill'
* fill:
  Implement a more generic Fill class instead of GradientColor
2020-01-24 12:53:07 +02:00
Daniel Cohen Gindi
c0e7f56b5d Implement a more generic Fill class instead of GradientColor
Support HorizontalBarChart too.
2020-01-24 12:52:27 +02:00
Daniel Cohen Gindi
351e341ee7 Fixed merge residue 2020-01-24 11:42:03 +02:00
Daniel Cohen Gindi
f05337768d Finalized vertical line collision check 2020-01-23 15:45:57 +02:00
Daniel Cohen Gindi
f8d068d377
Merge pull request #4787 from danielgindi/feature/catching_up_to_ios
Feature/catching up to ios
2020-01-23 15:38:53 +02:00
Daniel Cohen Gindi
5e4a32eb41 Corrected check for line in vertical bounds
https://github.com/danielgindi/Charts/pull/4100
2020-01-23 12:09:06 +02:00
Daniel Cohen Gindi
1de836ac65 Remove unexpected dash line during linear animation
https://github.com/danielgindi/Charts/pull/4094
2020-01-23 11:19:07 +02:00
Daniel Cohen Gindi
0668d30a6b Fixed a bug where a pie slice without highlight enabled is hidden
https://github.com/danielgindi/Charts/pull/3969
2020-01-23 10:54:28 +02:00
Daniel Cohen Gindi
34fefd28e1 maxHeight didn't account for the last label
https://github.com/danielgindi/Charts/pull/3900
2020-01-23 10:18:28 +02:00
Daniel Cohen Gindi
45240c3723 Improved negative offset for horz bar chart
https://github.com/danielgindi/Charts/pull/3854
2020-01-22 16:01:42 +02:00
Daniel Cohen Gindi
14456f475f Renamed values -> entries for consistency
https://github.com/danielgindi/Charts/pull/3847
2020-01-22 14:24:37 +02:00
Daniel Cohen Gindi
e02e9be2fa Multiple colors for valueline
https://github.com/danielgindi/Charts/pull/3709
2020-01-22 14:13:31 +02:00
Daniel Cohen Gindi
fcc5af71ce Call onChartScale listener after double-tap-zoom
https://github.com/danielgindi/Charts/pull/3770
2020-01-22 13:49:10 +02:00
Daniel Cohen Gindi
13aee592b1 Improve min/max calculation
https://github.com/danielgindi/Charts/pull/3650
2020-01-22 13:43:42 +02:00
Daniel Cohen Gindi
c97c8d247f Fixed index out of bounds issue when using stacked bar chart
b03cf16ec4
2020-01-22 13:23:12 +02:00
Daniel Cohen Gindi
ae59e7a19e This is for the inline bubble selection
https://github.com/danielgindi/Charts/pull/3548
2020-01-22 13:12:04 +02:00
Daniel Cohen Gindi
7752efef7e Support for labelXOffset for YAxis label 2020-01-22 13:04:11 +02:00
Daniel Cohen Gindi
58545bbbfa Add option to disable clipping data to contentRect
https://github.com/danielgindi/Charts/pull/3360
2020-01-22 12:46:37 +02:00
Daniel Cohen Gindi
4ce14e6cc9 Add a warning message if pie chart has more than one data set
https://github.com/danielgindi/Charts/pull/3286
2020-01-22 12:42:32 +02:00
Daniel Cohen Gindi
8df9eda7af Call notifyDataChanged for an opportunity for subclasses 2020-01-22 12:39:03 +02:00
Daniel Cohen Gindi
34c3ceaa05 Reset min/max when clearing ChartDataSet
https://github.com/danielgindi/Charts/pull/3265
2020-01-22 12:29:47 +02:00
Daniel Cohen Gindi
ea816e8d6d Added dataIndex param for highlightValue (combined charts)
https://github.com/danielgindi/Charts/pull/2852
2020-01-22 12:25:34 +02:00
Daniel Cohen Gindi
bafb0fbbe4 Use correct color index for bubble chart
https://github.com/danielgindi/Charts/pull/3202
2020-01-22 12:16:48 +02:00
Daniel Cohen Gindi
4549ae17b7 Select correct axis for legend distance calculation in horz bar chart
https://github.com/danielgindi/Charts/pull/2214
2020-01-22 12:15:02 +02:00
Daniel Cohen Gindi
912427e543 Custom text alignment for no-data
https://github.com/danielgindi/Charts/pull/3199
2020-01-22 12:07:37 +02:00
Daniel Cohen Gindi
3f5475077e Avoid race condition for interval/intervalMagnitude
https://github.com/danielgindi/Charts/pull/2377
2020-01-22 11:59:43 +02:00
Daniel Cohen Gindi
2e725e49d3 Make min/max axis labels configurable
https://github.com/danielgindi/Charts/pull/2894
2020-01-22 11:54:08 +02:00
Daniel Cohen Gindi
a4ca1f3fba Fixed axis label disappearing when zooming in
https://github.com/danielgindi/Charts/pull/3132
2020-01-22 11:47:45 +02:00
Daniel Cohen Gindi
634a690d6a Added an implementation of Douglas Peucker with resultCount input
https://github.com/danielgindi/Charts/pull/2848
2020-01-22 11:44:27 +02:00
Daniel Cohen Gindi
1987d7eb64 Consider axis dependency in Combined chart
https://github.com/danielgindi/Charts/pull/2874
2020-01-22 11:04:57 +02:00
Daniel Cohen Gindi
6ebf3fa57a Added highlightColor parameter for pie charts
https://github.com/danielgindi/Charts/pull/2961
2020-01-22 10:27:55 +02:00
Daniel Cohen Gindi
95027fa6a7 Safe guards
These will be even more important when moving to Kotlin ranges
2020-01-22 09:55:00 +02:00
Philipp Jahoda
d86f39cc91
Update README.md 2020-01-20 11:15:12 +01:00
Philipp Jahoda
cb26ed4ef4
Update FUNDING.yml 2019-10-08 14:15:52 +02:00
Philipp Jahoda
dc59171524
Create FUNDING.yml 2019-10-08 14:15:21 +02:00
Philipp Jahoda
726616d079 Merge branch 'master' of github.com:PhilJay/MPAndroidChart 2019-04-27 17:38:41 +02:00
Philipp Jahoda
fffe9a297e Update gradle 2019-04-27 17:38:37 +02:00
Philipp Jahoda
2340e12800
Merge pull request #4512 from duchampdev/percent_formatter_sign_spacing
PercentFormatter: make space between number and percent sign optional
2019-04-27 17:37:13 +02:00
duchampdev
c5667d4f14 fix little typo 2019-04-27 16:06:37 +02:00
duchampdev
0563fb48b0 PercentFormatter: make space between number and percent sign optional 2019-04-27 16:06:10 +02:00
Philipp Jahoda
ed8876cef2
Update README.md 2019-04-07 16:37:14 +02:00
Philipp Jahoda
12b4351d0c
Update README.md 2019-04-07 16:27:59 +02:00
Philipp Jahoda
adb56e75bd
Update README.md 2019-04-07 16:20:14 +02:00
Philipp Jahoda
e95c1eb26a
Update README.md 2019-03-20 17:56:58 +01:00
50 changed files with 1663 additions and 401 deletions

12
.github/FUNDING.yml vendored Normal file
View 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']

View file

@ -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" />

View file

@ -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);

View file

@ -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() {}
}

View file

@ -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);

View file

@ -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;*/
}

View file

@ -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.
*

View file

@ -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();
}

View file

@ -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]);
}
}

View file

@ -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() {

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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();
}
}
}
}
}

View file

@ -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 {

View file

@ -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);

View file

@ -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
*/

View file

@ -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.
*

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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

View file

@ -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) {

View file

@ -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.
*

View file

@ -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.

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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(),

View file

@ -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

View file

@ -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 :

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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() + ".");
}
}
}

View file

@ -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:
[![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart)
[![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](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.

View file

@ -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'
}
}

View file

@ -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