接下来看刻度线的绘制,根据厘米可以计算出中间的格数,根据厘米占用屏幕宽度和所占格数可以计算出每一格所占屏幕宽度:
mLineInterval = (mTotalWidth - 2 * mDividRuleLeftMargin - 2 * mFirstLineMargin) / (DEFAULT_COUNT * 10 - 1);有了每一格所占宽度,我们只需要在绘制刻度线的时候不断将画布右移对应宽度即可:
/** * 绘制刻度线 * @param canvas */ private void drawLines(Canvas canvas) { canvas.save(); canvas.translate(mLineStartX, 0); int top = mMaxLineTop; for (int i = 0; i <= DEFAULT_COUNT * 10; i++) { if (i % 10 == 0) { top = mMaxLineTop; } else if (i % 5 == 0) { top = mMiddleLineTop; } else { top = mMinLineTop; } canvas.drawLine(0, mRuleBottom, 0, top, mLinePaint); canvas.translate(mLineInterval, 0); } canvas.restore(); }由于刻度尺上分三种长短的刻度线,我们也做对应处理,10的整数倍的刻度线最长,5的整数倍的刻度线中等长度,其余较短;此时绘制出的刻度尺效果为:
此时刻度尺的基本样子就出来了,对应文字大家有兴趣可以自己加上;
俗话说,条条大路通罗马,我们除了使用canvas.translate ,还能不能使用别的方式进行实现呢,答案当然是可以,比如在绘制的时候根据for循环里的 i 值也可以直接计算出每一根刻度线的位置,然后直接进行绘制,相比之下,这两种方式的优劣大家也可以自行比较一下,好了,canvas.translate() 就说这么多;
二、canvas.scale( ) - 画布的缩放:
关于scale,android 提供了以下两个接口:
/** * Preconcat the current matrix with the specified scale. * * @param sx The amount to scale in X * @param sy The amount to scale in Y */ public native void scale(float sx, float sy); /** * Preconcat the current matrix with the specified scale. * * @param sx The amount to scale in X * @param sy The amount to scale in Y * @param px The x-coord for the pivot point (unchanged by the scale) * @param py The y-coord for the pivot point (unchanged by the scale) */ public final void scale(float sx, float sy, float px, float py) { translate(px, py); scale(sx, sy); translate(-px, -py); }我们先看下scale(float sx , float sy),我们还是以上面的正方形作为栗子,调用canvas.scale(float sx , float sy)之后看下效果; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLUE); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint); canvas.scale(0.5f, 0.5f); mPaint.setColor(Color.YELLOW); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint); }我们将画布在x,y方向上均缩放为 0.5 倍,使用默认基准点(原点 0,0),效果如下:
效果就相当于用个钉子钉在(0,0)处,然后把矩形的x,y缩放为一半,我们再来看看第二个接口scale(float sx , float sy, float px,float py):
前两个参数为将画布在x、y方向上缩放的倍数,而px和py 分别为缩放的基准点,从源码上可以非常清楚的看出和scale(float sx , float sy)的差别:
translate(px, py); scale(sx, sy); translate(-px, -py);即先将画布平移px,py,然后scale,scale结束之后再将画布平移回原基准点;我们再在之前的基础上绘制一个同样的矩形,x , y 均缩放为 0.5 倍,缩放中心为矩形的中心:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.BLUE); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint); // 保存画布状态 canvas.save(); canvas.scale(0.5f, 0.5f); mPaint.setColor(Color.YELLOW); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint); // 画布状态回滚 canvas.restore(); canvas.scale(0.5f, 0.5f, 200, 200); mPaint.setColor(Color.BLACK); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint); }一起来看下效果:
效果就相当于用个钉子钉在矩形的中心,然后进行缩放;
根据上面android 的实现,我们其实可以使用以下代码实现同样的效果:
// 先将画布平移到矩形的中心 canvas.translate(200, 200); // 将画布进行缩放 canvas.scale(0.5f, 0.5f); // 将画布移回原基准点 canvas.translate(-200, -200); mPaint.setColor(Color.BLACK); canvas.drawRect(new Rect(0, 0, 400, 400), mPaint);到此为止,我们也就了解了对画布的缩放,基于canvas.scale(),我们一起完成一个小例子:
上面是网络上找的一张让人产生视觉误差的静态图,我们模拟绘制出上面的效果;
思路非常的简单:
1. 绘制一个和屏幕等宽的正方形;
2. 将画布以正方形中心为基准点进行缩放;
3. 在缩放的过程中绘制原正方形;
注:每次绘制都得使用canvas.save() 和 canvas.restore()进行画布的锁定和回滚,以免除对后面绘制的影响(后面会单独讲)