5

我想沿着屏幕高度垂直绘制画布月的文本。

油漆初始化:

   this.paint = new Paint();
   this.paint.setAntiAlias(true);
   this.paint.setDither(true);
   this.paint.setSubpixelText(true);
   this.paint.setColor(color_text_dark);
   this.paint.setTextAlign(Align.RIGHT);

绘画:

   // Set the scale to the widest month
   float scale = getHeight() / this.max_month_width;
   String month_string = FULL_MONTH_NAME_FORMATTER.
                         format(active_month_calendar.getTime());
   canvas.save();
   canvas.translate(getWidth(), 0);
   canvas.rotate(-90);
   canvas.scale(scale, scale);
   canvas.drawText(month_string, 0, 0, this.paint);
   canvas.restore();

结果在hdpi屏幕上看起来不错,但在xhdpi屏幕上非常丑陋和像素化。

我在各种设备上做了更多的测试,明白什么结果取决于安卓版本,而不是屏幕密度和分辨率。

代码在 2.x 平台上运行良好,但在 4.0.3+ 上无法运行。假设,Android draw 实现在这里被改变了。你可以在这里看到完整的代码。

hdpi 2.3.5版(也测试了2.2

hdpi

xhdpi 4.2版(也测试4.1 4.0.3

xhdpi

尝试绘制抗锯齿的不同变体,亚像素文本没有效果。我该如何解决这个问题?

4

2 回答 2

10

问题是您正在以一种尺寸绘制文本并将结果放大。一旦确定了文本的宽度,就应该调用 Paint.measureText(),通过 Paint.setTextSize() 相应地调整大小。一旦测量正确,您就可以调用 Canvas.drawText()。

另一种方法是根本不测量文本并立即调用:

paint.setTextSize(paint.getSize() * scale)

但是,不能保证文本适合这种情况。

您的其他转换调用都不应该导致插值,因此它应该给您非常清晰的线条。

编辑

这是一个代码示例和比较屏幕截图:

canvas.save();
canvas.scale(10, 10);
canvas.drawText("Hello", 0, 10, mTextPaint);
canvas.restore();
float textSize = mTextPaint.getTextSize();
mTextPaint.setTextSize(textSize * 10);
canvas.drawText("Hello", 0, 300, mTextPaint);
mTextPaint.setTextSize(textSize);

你的渲染方法在上面,我的在下面

于 2013-01-27T00:18:16.227 回答
2

我没有足够的声誉来评论 Krylez 的出色答案,但我想回复 mcfly soft 关于路径的评论/问题。

路径与文本的想法相同。与其缩放和平移绘制路径的画布,不如将相同的缩放和平移放入矩阵并将其传递给 Path.transform:

// instead of this:
canvas.scale(sX, sY);
canvas.translate(trX, trY);
canvas.drawPath(path);

// do this:
matrix.postScale(sX, sY);
matrix.postTranslate(trX, trY);
path.transform(matrix);
canvas.drawPath(path);
于 2015-09-21T06:41:09.523 回答