我想在画布月份的文字垂直沿屏幕高度绘制。
Paint init:
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 一个上非常难看和像素化。
我在各种设备上做了更多测试,并了解结果取决于Android版本,而不是屏幕密度和分辨率。
代码在2.x平台上运行良好,但在4.0.3+上不起作用。假设,这里改变了Android绘图实现。 完整代码,您可以看到here。
hdpi 版本 2.3.5 (同时测试 2.2 )
xhdpi 版本 4.2 (同时测试 4.1 , 4.0.3 )
尝试绘制抗锯齿的不同变体,子像素文本无效。我该如何解决这个问题?
答案 0 :(得分: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);
答案 1 :(得分: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);