Add feature to move the viewport to a specified position animated
This commit is contained in:
parent
014c688633
commit
72cabd15aa
9 changed files with 318 additions and 51 deletions
|
@ -23,12 +23,10 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency;
|
|||
import com.github.mikephil.charting.data.Entry;
|
||||
import com.github.mikephil.charting.data.LineData;
|
||||
import com.github.mikephil.charting.data.LineDataSet;
|
||||
import com.github.mikephil.charting.data.filter.Approximator;
|
||||
import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
|
||||
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
|
||||
import com.github.mikephil.charting.utils.ColorTemplate;
|
||||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -228,6 +226,7 @@ public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListe
|
|||
mChart.animateXY(3000, 3000);
|
||||
break;
|
||||
}
|
||||
|
||||
case R.id.actionSave: {
|
||||
if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) {
|
||||
Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!",
|
||||
|
@ -327,6 +326,9 @@ public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListe
|
|||
@Override
|
||||
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
|
||||
Log.i("Entry selected", e.toString());
|
||||
|
||||
//mChart.centerViewToAnimated(e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000);
|
||||
//mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,6 +26,8 @@ import com.github.mikephil.charting.highlight.ChartHighlighter;
|
|||
import com.github.mikephil.charting.highlight.Highlight;
|
||||
import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider;
|
||||
import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet;
|
||||
import com.github.mikephil.charting.jobs.AnimatedMoveViewJob;
|
||||
import com.github.mikephil.charting.jobs.AnimatedZoomJob;
|
||||
import com.github.mikephil.charting.jobs.MoveViewJob;
|
||||
import com.github.mikephil.charting.listener.BarLineChartTouchListener;
|
||||
import com.github.mikephil.charting.listener.OnDrawListener;
|
||||
|
@ -683,6 +685,28 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
postInvalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms by the specified scale factor to the specified values on the specified axis.
|
||||
* STILL WORK IN PROGRESS
|
||||
*
|
||||
* @param scaleX
|
||||
* @param scaleY
|
||||
* @param xValue
|
||||
* @param yValue
|
||||
* @param axis
|
||||
* @param duration
|
||||
*/
|
||||
private void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) {
|
||||
|
||||
PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis);
|
||||
|
||||
float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY();
|
||||
float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX();
|
||||
|
||||
Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue - xsInView / 2f, yValue + valsInView / 2f, (float) bounds.x, (float) bounds.y, duration);
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all zooming and dragging and makes the chart fit exactly it's
|
||||
* bounds.
|
||||
|
@ -774,11 +798,7 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
Runnable job = new MoveViewJob(mViewPortHandler, xIndex, 0f,
|
||||
getTransformer(AxisDependency.LEFT), this);
|
||||
|
||||
if (mViewPortHandler.hasChartDimens()) {
|
||||
post(job);
|
||||
} else {
|
||||
mJobs.add(job);
|
||||
}
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -795,16 +815,12 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f,
|
||||
getTransformer(axis), this);
|
||||
|
||||
if (mViewPortHandler.hasChartDimens()) {
|
||||
post(job);
|
||||
} else {
|
||||
mJobs.add(job);
|
||||
}
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will move the left side of the current viewport to the specified
|
||||
* x-index on the x-axis, and center the viewport to the specified y-value
|
||||
* x-value on the x-axis, and center the viewport to the specified y-value
|
||||
* on the y-axis.
|
||||
* This also refreshes the chart by calling invalidate().
|
||||
*
|
||||
|
@ -819,23 +835,41 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
Runnable job = new MoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f,
|
||||
getTransformer(axis), this);
|
||||
|
||||
if (mViewPortHandler.hasChartDimens()) {
|
||||
post(job);
|
||||
} else {
|
||||
mJobs.add(job);
|
||||
}
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will move the left side of the current viewport to the specified x-position
|
||||
* and center the viewport to the specified y-position animated.
|
||||
* This also refreshes the chart by calling invalidate().
|
||||
*
|
||||
* @param xIndex
|
||||
* @param yValue
|
||||
* @param axis
|
||||
* @param duration the duration of the animation in milliseconds
|
||||
*/
|
||||
public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) {
|
||||
|
||||
PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis);
|
||||
|
||||
float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY();
|
||||
|
||||
Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f,
|
||||
getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration);
|
||||
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will move the center of the current viewport to the specified
|
||||
* x-index and y-value.
|
||||
* x-value and y-value.
|
||||
* This also refreshes the chart by calling invalidate().
|
||||
*
|
||||
* @param xIndex
|
||||
* @param yValue
|
||||
* @param axis - which axis should be used as a reference for the y-axis
|
||||
*/
|
||||
public void centerViewTo(int xIndex, float yValue, AxisDependency axis) {
|
||||
public void centerViewTo(float xIndex, float yValue, AxisDependency axis) {
|
||||
|
||||
float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY();
|
||||
float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX();
|
||||
|
@ -844,11 +878,30 @@ public abstract class BarLineChartBase<T extends BarLineScatterCandleBubbleData<
|
|||
xIndex - xsInView / 2f, yValue + valsInView / 2f,
|
||||
getTransformer(axis), this);
|
||||
|
||||
if (mViewPortHandler.hasChartDimens()) {
|
||||
post(job);
|
||||
} else {
|
||||
mJobs.add(job);
|
||||
}
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will move the center of the current viewport to the specified
|
||||
* x-value and y-value animated.
|
||||
*
|
||||
* @param xIndex
|
||||
* @param yValue
|
||||
* @param axis
|
||||
* @param duration the duration of the animation in milliseconds
|
||||
*/
|
||||
public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) {
|
||||
|
||||
PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis);
|
||||
|
||||
float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY();
|
||||
float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX();
|
||||
|
||||
Runnable job = new AnimatedMoveViewJob(mViewPortHandler,
|
||||
xIndex - xsInView / 2f, yValue + valsInView / 2f,
|
||||
getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration);
|
||||
|
||||
postJob(job);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1630,6 +1630,21 @@ public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Ent
|
|||
mJobs.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Either posts a job immediately if the chart has already setup it's
|
||||
* dimensions or adds the job to the execution queue.
|
||||
*
|
||||
* @param job
|
||||
*/
|
||||
protected void postJob(Runnable job) {
|
||||
|
||||
if (mViewPortHandler.hasChartDimens()) {
|
||||
post(job);
|
||||
} else {
|
||||
mJobs.add(job);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all jobs that are scheduled to be executed after
|
||||
* onSizeChanged(...).
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package com.github.mikephil.charting.jobs;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
/**
|
||||
* Created by Philipp Jahoda on 19/02/16.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public abstract class AnimatedJob extends Job implements ValueAnimator.AnimatorUpdateListener {
|
||||
|
||||
protected ObjectAnimator animator;
|
||||
|
||||
protected float phase;
|
||||
|
||||
protected float xOrigin;
|
||||
protected float yOrigin;
|
||||
|
||||
public AnimatedJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) {
|
||||
super(viewPortHandler, xValue, yValue, trans, v);
|
||||
this.xOrigin = xOrigin;
|
||||
this.yOrigin = yOrigin;
|
||||
animator = ObjectAnimator.ofFloat(this, "phase", 0f, 1f);
|
||||
animator.setDuration(duration);
|
||||
animator.addUpdateListener(this);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public void run() {
|
||||
animator.start();
|
||||
}
|
||||
|
||||
public float getPhase() {
|
||||
return phase;
|
||||
}
|
||||
|
||||
public void setPhase(float phase) {
|
||||
this.phase = phase;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.github.mikephil.charting.jobs;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
/**
|
||||
* Created by Philipp Jahoda on 19/02/16.
|
||||
*/
|
||||
public class AnimatedMoveViewJob extends AnimatedJob {
|
||||
|
||||
public AnimatedMoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) {
|
||||
super(viewPortHandler, xValue, yValue, trans, v, xOrigin, yOrigin, duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
|
||||
pts[0] = xOrigin + (xValue - xOrigin) * phase;
|
||||
pts[1] = yOrigin + (yValue - yOrigin) * phase;
|
||||
|
||||
mTrans.pointValuesToPixel(pts);
|
||||
mViewPortHandler.centerViewPort(pts, view);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.github.mikephil.charting.jobs;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.charts.BarLineChartBase;
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
/**
|
||||
* Created by Philipp Jahoda on 19/02/16.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
public class AnimatedZoomJob extends AnimatedJob implements Animator.AnimatorListener {
|
||||
|
||||
protected float zoomOriginX;
|
||||
protected float zoomOriginY;
|
||||
|
||||
protected float zoomCenterX;
|
||||
protected float zoomCenterY;
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) {
|
||||
super(viewPortHandler, scaleX, scaleY, trans, v, xOrigin, yOrigin, duration);
|
||||
|
||||
this.zoomCenterX = zoomCenterX;
|
||||
this.zoomCenterY = zoomCenterY;
|
||||
this.zoomOriginX = zoomOriginX;
|
||||
this.zoomOriginY = zoomOriginY;
|
||||
this.animator.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
|
||||
float scaleX = xOrigin + (xValue - xOrigin) * phase;
|
||||
float scaleY = yOrigin + (yValue - yOrigin) * phase;
|
||||
|
||||
pts[0] = zoomOriginX + (zoomCenterX - zoomOriginX) * phase;
|
||||
pts[1] = zoomOriginY + (zoomCenterY - zoomOriginY) * phase;
|
||||
|
||||
mTrans.pointValuesToPixel(pts);
|
||||
|
||||
//Matrix save = mViewPortHandler.zoomAndCenter(xValue * phase, yValue * phase, zoomCenterX * phase, zoomCenterY * phase);
|
||||
|
||||
mViewPortHandler.zoomAndCenter(scaleX, scaleY, pts, view);//zoomOriginX + (zoomCenterX - zoomOriginX) * phase, zoomOriginY + (zoomCenterY - zoomOriginY) * phase);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
((BarLineChartBase) view).calculateOffsets();
|
||||
view.postInvalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animator animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
|
||||
}
|
||||
}
|
35
MPChartLib/src/com/github/mikephil/charting/jobs/Job.java
Normal file
35
MPChartLib/src/com/github/mikephil/charting/jobs/Job.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
package com.github.mikephil.charting.jobs;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.github.mikephil.charting.utils.Transformer;
|
||||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
/**
|
||||
* Runnable that is used for viewport modifications since they cannot be
|
||||
* executed at any time. This can be used to delay the execution of viewport
|
||||
* modifications until the onSizeChanged(...) method of the chartview is called.
|
||||
*
|
||||
* @author Philipp Jahoda
|
||||
*/
|
||||
public abstract class Job implements Runnable {
|
||||
|
||||
protected float[] pts = new float[2];
|
||||
|
||||
protected ViewPortHandler mViewPortHandler;
|
||||
protected float xValue = 0f;
|
||||
protected float yValue = 0f;
|
||||
protected Transformer mTrans;
|
||||
protected View view;
|
||||
|
||||
public Job(ViewPortHandler viewPortHandler, float xValue, float yValue,
|
||||
Transformer trans, View v) {
|
||||
|
||||
this.mViewPortHandler = viewPortHandler;
|
||||
this.xValue = xValue;
|
||||
this.yValue = yValue;
|
||||
this.mTrans = trans;
|
||||
this.view = v;
|
||||
}
|
||||
}
|
|
@ -7,36 +7,19 @@ import com.github.mikephil.charting.utils.Transformer;
|
|||
import com.github.mikephil.charting.utils.ViewPortHandler;
|
||||
|
||||
/**
|
||||
* Runnable that is used for viewport modifications since they cannot be
|
||||
* executed at any time. This can be used to delay the execution of viewport
|
||||
* modifications until the onSizeChanged(...) method of the chartview is called.
|
||||
*
|
||||
* @author Philipp Jahoda
|
||||
* Created by Philipp Jahoda on 19/02/16.
|
||||
*/
|
||||
public class MoveViewJob implements Runnable {
|
||||
public class MoveViewJob extends Job {
|
||||
|
||||
protected ViewPortHandler mViewPortHandler;
|
||||
protected float xIndex = 0f;
|
||||
protected float yValue = 0f;
|
||||
protected Transformer mTrans;
|
||||
protected View view;
|
||||
|
||||
public MoveViewJob(ViewPortHandler viewPortHandler, float xIndex, float yValue,
|
||||
Transformer trans, View v) {
|
||||
|
||||
this.mViewPortHandler = viewPortHandler;
|
||||
this.xIndex = xIndex;
|
||||
this.yValue = yValue;
|
||||
this.mTrans = trans;
|
||||
this.view = v;
|
||||
public MoveViewJob(ViewPortHandler viewPortHandler, float xIndex, float yValue, Transformer trans, View v) {
|
||||
super(viewPortHandler, xIndex, yValue, trans, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
float[] pts = new float[] {
|
||||
xIndex, yValue
|
||||
};
|
||||
pts[0] = xValue;
|
||||
pts[1] = yValue;
|
||||
|
||||
mTrans.pointValuesToPixel(pts);
|
||||
mViewPortHandler.centerViewPort(pts, view);
|
||||
|
|
|
@ -223,13 +223,46 @@ public class ViewPortHandler {
|
|||
Matrix save = new Matrix();
|
||||
save.set(mMatrixTouch);
|
||||
|
||||
// Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y);
|
||||
|
||||
save.postScale(scaleX, scaleY, x, y);
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
public Matrix zoom(float scaleX, float scaleY) {
|
||||
|
||||
Matrix save = new Matrix();
|
||||
save.set(mMatrixTouch);
|
||||
|
||||
save.setScale(scaleX, scaleY);
|
||||
|
||||
return save;
|
||||
}
|
||||
|
||||
/**
|
||||
* Zooms by the specified scale factors and moves the viewport to the specified values.
|
||||
*
|
||||
* @param scaleX
|
||||
* @param scaleY
|
||||
* @param pts
|
||||
* @param view
|
||||
* @return
|
||||
*/
|
||||
public synchronized Matrix zoomAndCenter(float scaleX, float scaleY, float[] pts, final View view) {
|
||||
|
||||
Matrix save = new Matrix();
|
||||
save.set(mMatrixTouch);
|
||||
|
||||
final float x = pts[0] - offsetLeft();
|
||||
final float y = pts[1] - offsetTop();
|
||||
|
||||
PointF center = getContentCenter();
|
||||
|
||||
save.setScale(scaleX, scaleY, center.x, center.y);
|
||||
save.postTranslate(-x, -y);
|
||||
|
||||
return refresh(save, view, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all zooming and dragging and makes the chart fit exactly it's
|
||||
* bounds.
|
||||
|
|
Loading…
Add table
Reference in a new issue