LineChart比PieChart逻辑简单,主要技术点就是双指缩放逻辑。
public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) {
float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX()));
float low = chart.getLowestVisibleX(); //mXAxis.mAxisMinimum
float high = chart.getHighestVisibleX(); //mXAxis.mAxisMaximum
Entry entryFrom = dataSet.getEntryForXValue(low, Float.NaN, DataSet.Rounding.DOWN);
Entry entryTo = dataSet.getEntryForXValue(high, Float.NaN, DataSet.Rounding.UP);
min = entryFrom == null ? 0 : dataSet.getEntryIndex(entryFrom);
max = entryTo == null ? 0 : dataSet.getEntryIndex(entryTo);
range = (int) ((max - min) * phaseX);
}
for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) {
Entry e = dataSet.getEntryForIndex(j);
if (e == null) continue;
mLineBuffer[0] = e.getX();
mLineBuffer[1] = e.getY() * phaseY;
if (j < mXBounds.max) {
e = dataSet.getEntryForIndex(j + 1);
if (e == null) break;
mLineBuffer[2] = e.getX();
mLineBuffer[3] = e.getY() * phaseY;
} else {
mLineBuffer[2] = mLineBuffer[0];
mLineBuffer[3] = mLineBuffer[1];
}
trans.pointValuesToPixel(mLineBuffer);
canvas.drawLines(mLineBuffer, 0, pointsPerEntryPair * 2, mRenderPaint);
}
protected boolean init(ILineDataSet set) {
int size = set.getCircleColorCount();
boolean changeRequired = false;
if (circleBitmaps == null) {
circleBitmaps = new Bitmap[size];
changeRequired = true;
} else if (circleBitmaps.length != size) {
circleBitmaps = new Bitmap[size];
changeRequired = true;
}
return changeRequired;
}
(2)以数据点位图为画布,绘制圆形位图
protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransparentCircleHole) {
int colorCount = set.getCircleColorCount();
float circleRadius = set.getCircleRadius();
float circleHoleRadius = set.getCircleHoleRadius();
for (int i = 0; i < colorCount; i++) {
Bitmap.Config conf = Bitmap.Config.ARGB_4444;
Bitmap circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1), (int) (circleRadius * 2.1), conf);
Canvas canvas = new Canvas(circleBitmap);
circleBitmaps[i] = circleBitmap;
mRenderPaint.setColor(set.getCircleColor(i));
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(set.getCircleColor(i));
paint.setAntiAlias(true);
canvas.drawCircle(
circleRadius,
circleRadius,
circleRadius,
paint);
}
}
(3) 把数据点位图绘制到坐标系画布上。
protected void drawCircles(Canvas c) {
Bitmap circleBitmap = imageCache.getBitmap(j);
if (circleBitmap != null) {
c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, mRenderPaint);
}
}
3.1(1~13)初始化Matrix
初始化就不详细介绍了.给大家展示一下日志
mMatrixValueToPx 坐标系原始矩阵(不改变)
mMatrixOffests 坐标系偏移量矩阵(不改变)
mMatrixTouch 手势缩放变换矩阵
E/mmnn ( 2441): init mMatrix = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): onSizChanged
E/mmnn ( 2441): refresh mMatrixTouch = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): notifyDataSetChanged
E/mmnn ( 2441): calculateOffsets
E/mmnn ( 2441): calculateOffsets mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]}
E/mmnn ( 2441): calculateOffsets mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]}
E/mmnn ( 2441): calculateOffsets mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]}
protected void drawLinear(Canvas c, ILineDataSet dataSet) {
for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) {
trans.pointValuesToPixel(mLineBuffer);
}
canvas.drawLines(mLineBuffer, 0, size, mRenderPaint);
}
以第0个点为例
E/mmnn ( 2441): pts0.0
E/mmnn ( 2441): mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixTouch = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]} pts39.0
3.3手势控制变换刷新矩阵(方法14,15)
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
saveTouchStart(event);
break;
case MotionEvent.ACTION_POINTER_DOWN:
if (event.getPointerCount() >= 2) {
saveTouchStart(event);
}
mTouchMode = X_ZOOM;
break;
case MotionEvent.ACTION_MOVE:
performZoom(event);
break;
case MotionEvent.ACTION_UP:
mChart.calculateOffsets();
mChart.postInvalidate();
mTouchMode = NONE;
break;
case MotionEvent.ACTION_POINTER_UP:
mTouchMode = POST_ZOOM;
break;
case MotionEvent.ACTION_CANCEL:
mTouchMode = NONE;
break;
}
mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true);
return true;
}
private void performZoom(MotionEvent event) {
mMatrix.set(mSavedMatrix);
mMatrix.postScale(scaleX, 1f, t.x, t.y);
}
E/mmnn ( 2441): ACTION_DOWN
E/mmnn ( 2441): refresh mMatrixTouch = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): pts0.0
E/mmnn ( 2441): mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixTouch = Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]} pts39.0
E/mmnn ( 2441): ACTION_MOVE
E/mmnn ( 2441): performZoom X_ZOOM mMatrix = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): refresh mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): pts0.0
E/mmnn ( 2441): mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} pts-87.966156
E/mmnn ( 2441): mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]} pts-48.966156
E/mmnn ( 2441): ACTION_POINTER_UP
E/mmnn ( 2441): refresh mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): pts0.0
E/mmnn ( 2441): mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} pts-87.966156
E/mmnn ( 2441): mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]} pts-48.966156
E/mmnn ( 2441): ACTION_UP
E/mmnn ( 2441): calculateOffsets
E/mmnn ( 2441): calculateOffsets mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]}
E/mmnn ( 2441): calculateOffsets mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]}
E/mmnn ( 2441): refresh mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
E/mmnn ( 2441): pts0.0
E/mmnn ( 2441): mMatrixValueToPx = Matrix{[37.944443, 0.0, 0.0][0.0, -1.4998698, -74.99349][0.0, 0.0, 1.0]} pts0.0
E/mmnn ( 2441): mMatrixTouch = Matrix{[1.223548, 0.0, -87.966156][0.0, 1.0, 0.0][0.0, 0.0, 1.0]} pts-87.966156
E/mmnn ( 2441): mMatrixOffset = Matrix{[1.0, 0.0, 39.0][0.0, 1.0, 922.4219][0.0, 0.0, 1.0]} pts-48.966156