Skip to content

Commit

Permalink
Improved negative offset for horz bar chart
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgindi committed Jan 22, 2020
1 parent 67f82f1 commit ff5deba
Show file tree
Hide file tree
Showing 4 changed files with 303 additions and 5 deletions.
3 changes: 2 additions & 1 deletion MPChartExample/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
<activity android:name="LineChartActivity2"></activity>
<activity android:name=".LineChartTime"></activity>
<activity android:name="BarChartActivity"></activity>
<activity android:name="HorizontalBarChartActivity"></activity>
<activity android:name="HorizontalBarChartActivity"></activity>
<activity android:name=".HorizontalBarNegativeChartActivity"></activity>
<activity android:name="PieChartActivity"></activity>
<activity android:name="PiePolylineChartActivity"></activity>
<activity android:name="MultiLineChartActivity"></activity>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@

package com.xxmassdeveloper.mpchartexample;

import android.annotation.SuppressLint;
import android.graphics.RectF;
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 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 {

protected HorizontalBarChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
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);

tvX = findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);

mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);

mChart = (HorizontalBarChart) findViewById(R.id.chart1);
mChart.setOnChartValueSelectedListener(this);
// mChart.setHighlightEnabled(false);

mChart.setDrawBarShadow(false);

mChart.setDrawValueAboveBar(true);

mChart.getDescription().setEnabled(false);

// if more than 60 entries are displayed in the chart, no values will be
// drawn
mChart.setMaxVisibleValueCount(60);

// scaling can now only be done on x- and y-axis separately
mChart.setPinchZoom(false);

// draw shadows for each bar that show the maximum value
// mChart.setDrawBarShadow(true);

mChart.setDrawGridBackground(false);

XAxis xl = mChart.getXAxis();
xl.setPosition(XAxisPosition.BOTTOM);
xl.setTypeface(mTfLight);
xl.setDrawAxisLine(true);
xl.setDrawGridLines(false);
xl.setGranularity(10f);

YAxis yl = mChart.getAxisLeft();
yl.setTypeface(mTfLight);
yl.setDrawAxisLine(true);
yl.setDrawGridLines(true);
yl.setDrawZeroLine(true); // draw a zero line
// yl.setInverted(true);

YAxis yr = mChart.getAxisRight();
yr.setTypeface(mTfLight);
yr.setDrawAxisLine(true);
yr.setDrawGridLines(false);
// yr.setInverted(true);

setData(12, 50);
mChart.setFitBars(true);
mChart.animateY(2500);

// setting data
mSeekBarY.setProgress(50);
mSeekBarX.setProgress(12);

mSeekBarY.setOnSeekBarChangeListener(this);
mSeekBarX.setOnSeekBarChangeListener(this);

Legend l = mChart.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);
}

@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.actionToggleValues: {
List<IBarDataSet> sets = mChart.getData()
.getDataSets();

for (IBarDataSet iSet : sets) {

IBarDataSet set = (BarDataSet) iSet;
set.setDrawValues(!set.isDrawValuesEnabled());
}

mChart.invalidate();
break;
}
case R.id.actionToggleIcons: {
List<IBarDataSet> sets = mChart.getData()
.getDataSets();

for (IBarDataSet iSet : sets) {

IBarDataSet set = (BarDataSet) iSet;
set.setDrawIcons(!set.isDrawIconsEnabled());
}

mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if(mChart.getData() != null) {
mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled());
mChart.invalidate();
}
break;
}
case R.id.actionTogglePinch: {
if (mChart.isPinchZoomEnabled())
mChart.setPinchZoom(false);
else
mChart.setPinchZoom(true);

mChart.invalidate();
break;
}
case R.id.actionToggleAutoScaleMinMax: {
mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled());
mChart.notifyDataSetChanged();
break;
}
case R.id.actionToggleBarBorders: {
for (IBarDataSet set : mChart.getData().getDataSets())
((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f);

mChart.invalidate();
break;
}
case R.id.animateX: {
mChart.animateX(3000);
break;
}
case R.id.animateY: {
mChart.animateY(3000);
break;
}
case R.id.animateXY: {

mChart.animateXY(3000, 3000);
break;
}
case R.id.actionSave: {
if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) {
Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!",
Toast.LENGTH_SHORT).show();
} else
Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT)
.show();
break;
}
}
return true;
}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

tvX.setText("" + (mSeekBarX.getProgress() + 1));
tvY.setText("" + (mSeekBarY.getProgress()));

setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress());
mChart.setFitBars(true);
mChart.invalidate();
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub

}

private void setData(int count, float range) {

float barWidth = 9f;
float spaceForBar = 10f;
ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();

for (int i = 0; i < count; i++) {
float val = (float) (Math.random() * range - range / 2);
yVals1.add(new BarEntry(i * spaceForBar, val,
getResources().getDrawable(R.drawable.star)));
}

BarDataSet set1;

if (mChart.getData() != null &&
mChart.getData().getDataSetCount() > 0) {
set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0);
set1.setValues(yVals1);
mChart.getData().notifyDataChanged();
mChart.notifyDataSetChanged();
} else {
set1 = new BarDataSet(yVals1, "DataSet 1");

set1.setDrawIcons(false);

ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
dataSets.add(set1);

BarData data = new BarData(dataSets);
data.setValueTextSize(10f);
data.setValueTypeface(mTfLight);
data.setBarWidth(barWidth);
mChart.setData(data);
}
}

protected RectF mOnValueSelectedRectF = new RectF();
@SuppressLint("NewApi")
@Override
public void onValueSelected(Entry e, Highlight h) {

if (e == null)
return;

RectF bounds = mOnValueSelectedRectF;
mChart.getBarBounds((BarEntry) e, bounds);

MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex())
.getAxisDependency());

Log.i("bounds", bounds.toString());
Log.i("position", position.toString());

MPPointF.recycleInstance(position);
}

@Override
public void onNothingSelected() {
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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;
Expand Down Expand Up @@ -131,6 +132,9 @@ protected void onCreate(Bundle savedInstanceState) {
objects.add(new ContentItem(
"BarChart positive / negative",
"This demonstrates how to create a BarChart with positive and negative values in different colors."));
objects.add(new ContentItem(
"HorizontalBarChart positive / negative",
"This demonstrates how to create a HorizontalBarChart with positive and negative values."));

ContentItem realm = new ContentItem(
"Realm.io Database",
Expand Down Expand Up @@ -274,18 +278,22 @@ public void onItemClick(AdapterView<?> av, View v, int pos, long arg3) {
startActivity(i);
break;
case 28:
i = new Intent(this, RealmMainActivity.class);
i = new Intent(this, HorizontalBarNegativeChartActivity.class);
startActivity(i);
break;
case 29:
i = new Intent(this, LineChartTime.class);
i = new Intent(this, RealmMainActivity.class);
startActivity(i);
break;
case 30:
i = new Intent(this, FilledLineActivity.class);
i = new Intent(this, LineChartTime.class);
startActivity(i);
break;
case 31:
i = new Intent(this, FilledLineActivity.class);
startActivity(i);
break;
case 32:
i = new Intent(this, HalfPieChartActivity.class);
startActivity(i);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ public void drawValues(Canvas c) {
// 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;
Expand Down

0 comments on commit ff5deba

Please sign in to comment.