如何找到相对文本大小
How to find the relative Text Size
我正在尝试在不同大小的图像上绘制文本。图像显示在 ImageView
中,然后绘制在 Canvas
中。虽然 Canvas
保留了图像的原始高度和宽度,但图像在 ImageView
中确实显得小了很多,因此这使得为 Canvas
选择合适的文本大小变得非常繁琐,因为 ImageView
给出了文本在图像上的显示方式的错误认知。
为了解决这个问题,我决定使用交叉乘法为 Canvas
上的文本找到合适的文本大小,它应该像在 Canvas
上一样出现ImageView
。这是我的尝试:
textSize = topTextView.getTextSize();
imageViewArea = ((img.getWidth()) * (img.getHeight()));
canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
x = (((textSize)/(imageViewArea)) * (canvasArea));
第一行获取显示在 ImageView
上的文本的大小。第 2 行和第 3 行计算 ImageView
和 Canvas
的面积。第三行基本上将它们放在一起并(理想情况下)输出一个浮点值,该值是 Canvas
.
上绘制的文本的大小
然而,它并不接近它应该的样子。当文本绘制在小图像上时,文本难以理解。在中型图像上绘制时又薄又丑。基本上,它看起来与预览中的完全不同。
我的假设是:交叉乘法不是可行的方法。
有什么建议吗?
public Bitmap createMeme(ImageView img){
BitmapDrawable bitmapDrawable = ((BitmapDrawable) img.getDrawable());
Bitmap bitmap = bitmapDrawable.getBitmap();
Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
String topText = topTextView.getText().toString();
String bottomText = bottomTextView.getText().toString();
topText = topText.toUpperCase();
bottomText = bottomText.toUpperCase();
Canvas canvas = new Canvas(mutableBitmap);
TextPaint topFillPaint = new TextPaint();
TextPaint bottomFillPaint = new TextPaint();
TextPaint topStrokePaint = new TextPaint();
TextPaint bottomStrokePaint = new TextPaint();
Typeface typeface = getResources().getFont(R.font.impact);
textSize = topTextView.getTextSize();
imageViewArea = ((img.getWidth()) * (img.getHeight()));
canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
val = textSize * sqrt(canvasArea / imageViewArea);
x = (float)val;
topFillPaint.setColor(Color.WHITE);
topFillPaint.setTextSize(x);
topFillPaint.setTypeface(typeface);
topStrokePaint.setStyle(Paint.Style.STROKE);
topStrokePaint.setStrokeWidth(4);
topStrokePaint.setTextSize(x);
topStrokePaint.setColor(Color.BLACK);
topStrokePaint.setTypeface(typeface);
bottomFillPaint.setColor(Color.WHITE);
bottomFillPaint.setTextSize(x);
bottomFillPaint.setTypeface(typeface);
bottomStrokePaint.setStyle(Paint.Style.STROKE);
bottomStrokePaint.setStrokeWidth(4);
bottomStrokePaint.setColor(Color.BLACK);
bottomStrokePaint.setTextSize(x);
bottomStrokePaint.setTypeface(typeface);
StaticLayout topFillLayout = new StaticLayout(topText, topFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout topStrokeLayout = new StaticLayout(topText, topStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout bottomFillLayout = new StaticLayout(bottomText, bottomFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout bottomStrokeLayout = new StaticLayout(bottomText, bottomStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
topFillLayout.draw(canvas);
topStrokeLayout.draw(canvas);
canvas.translate(0, canvas.getHeight() - 50);
bottomFillLayout.draw(canvas);
bottomStrokeLayout.draw(canvas);
return mutableBitmap;
}
输出
所以我上传了 4 张不同尺寸的图片,以查看每张图片的文字大小。这是我的发现:
274 x 184
topTextSize: 0, bottomTextSize: 0
3704 x 2469
topTextSize: 237.58, bottomTextSize: 237.58
640 x 480
topTextSize: 0, bottomTextSize: 0
2560 x 1920
topTextSize: 168, bottomTextSize: 168
对于 2
和 4
,位图上仅显示顶部文本
例如,这是尺寸为 274 x 184
的图像的值:
textSize = 168
imageViewArea = 1728000
canvasArea = 50416
x = 0
您计算的比例是面积比,而不是长度比。如果沿每边将图像缩放 2,则面积比将为 4(或 1/4,具体取决于您考虑的方向)。字体大小应该是一个长度,因此你应该使用一个长度比例。
如果您知道缩放是统一的(高度与宽度的缩放比例相同),只需根据宽度或高度(而不是面积)计算比率。如果不是,您将需要一种可以在一个方向上拉伸字体的文本呈现方法。如果您想使用某种保留面积比的平均字体大小,只需使用 x = textSize * sqrt(canvasArea / imageViewArea)
.
题外话:你的代码片段中有很多不必要的括号。就我个人而言,我认为这会使阅读代码变得更加困难。因此,我建议删除不必要的括号(除非它们是故意用来传达某种含义的)。
我正在尝试在不同大小的图像上绘制文本。图像显示在 ImageView
中,然后绘制在 Canvas
中。虽然 Canvas
保留了图像的原始高度和宽度,但图像在 ImageView
中确实显得小了很多,因此这使得为 Canvas
选择合适的文本大小变得非常繁琐,因为 ImageView
给出了文本在图像上的显示方式的错误认知。
为了解决这个问题,我决定使用交叉乘法为 Canvas
上的文本找到合适的文本大小,它应该像在 Canvas
上一样出现ImageView
。这是我的尝试:
textSize = topTextView.getTextSize();
imageViewArea = ((img.getWidth()) * (img.getHeight()));
canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
x = (((textSize)/(imageViewArea)) * (canvasArea));
第一行获取显示在 ImageView
上的文本的大小。第 2 行和第 3 行计算 ImageView
和 Canvas
的面积。第三行基本上将它们放在一起并(理想情况下)输出一个浮点值,该值是 Canvas
.
然而,它并不接近它应该的样子。当文本绘制在小图像上时,文本难以理解。在中型图像上绘制时又薄又丑。基本上,它看起来与预览中的完全不同。
我的假设是:交叉乘法不是可行的方法。
有什么建议吗?
public Bitmap createMeme(ImageView img){
BitmapDrawable bitmapDrawable = ((BitmapDrawable) img.getDrawable());
Bitmap bitmap = bitmapDrawable.getBitmap();
Bitmap mutableBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
String topText = topTextView.getText().toString();
String bottomText = bottomTextView.getText().toString();
topText = topText.toUpperCase();
bottomText = bottomText.toUpperCase();
Canvas canvas = new Canvas(mutableBitmap);
TextPaint topFillPaint = new TextPaint();
TextPaint bottomFillPaint = new TextPaint();
TextPaint topStrokePaint = new TextPaint();
TextPaint bottomStrokePaint = new TextPaint();
Typeface typeface = getResources().getFont(R.font.impact);
textSize = topTextView.getTextSize();
imageViewArea = ((img.getWidth()) * (img.getHeight()));
canvasArea = ((canvas.getWidth()) * (canvas.getHeight()));
val = textSize * sqrt(canvasArea / imageViewArea);
x = (float)val;
topFillPaint.setColor(Color.WHITE);
topFillPaint.setTextSize(x);
topFillPaint.setTypeface(typeface);
topStrokePaint.setStyle(Paint.Style.STROKE);
topStrokePaint.setStrokeWidth(4);
topStrokePaint.setTextSize(x);
topStrokePaint.setColor(Color.BLACK);
topStrokePaint.setTypeface(typeface);
bottomFillPaint.setColor(Color.WHITE);
bottomFillPaint.setTextSize(x);
bottomFillPaint.setTypeface(typeface);
bottomStrokePaint.setStyle(Paint.Style.STROKE);
bottomStrokePaint.setStrokeWidth(4);
bottomStrokePaint.setColor(Color.BLACK);
bottomStrokePaint.setTextSize(x);
bottomStrokePaint.setTypeface(typeface);
StaticLayout topFillLayout = new StaticLayout(topText, topFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout topStrokeLayout = new StaticLayout(topText, topStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout bottomFillLayout = new StaticLayout(bottomText, bottomFillPaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
StaticLayout bottomStrokeLayout = new StaticLayout(bottomText, bottomStrokePaint, canvas.getWidth(), Layout.Alignment.ALIGN_CENTER,
0.8f, 0.0f, false);
topFillLayout.draw(canvas);
topStrokeLayout.draw(canvas);
canvas.translate(0, canvas.getHeight() - 50);
bottomFillLayout.draw(canvas);
bottomStrokeLayout.draw(canvas);
return mutableBitmap;
}
输出
所以我上传了 4 张不同尺寸的图片,以查看每张图片的文字大小。这是我的发现:
274 x 184
topTextSize: 0, bottomTextSize: 03704 x 2469
topTextSize: 237.58, bottomTextSize: 237.58640 x 480
topTextSize: 0, bottomTextSize: 02560 x 1920
topTextSize: 168, bottomTextSize: 168
对于 2
和 4
,位图上仅显示顶部文本
例如,这是尺寸为 274 x 184
的图像的值:
textSize = 168
imageViewArea = 1728000
canvasArea = 50416
x = 0
您计算的比例是面积比,而不是长度比。如果沿每边将图像缩放 2,则面积比将为 4(或 1/4,具体取决于您考虑的方向)。字体大小应该是一个长度,因此你应该使用一个长度比例。
如果您知道缩放是统一的(高度与宽度的缩放比例相同),只需根据宽度或高度(而不是面积)计算比率。如果不是,您将需要一种可以在一个方向上拉伸字体的文本呈现方法。如果您想使用某种保留面积比的平均字体大小,只需使用 x = textSize * sqrt(canvasArea / imageViewArea)
.
题外话:你的代码片段中有很多不必要的括号。就我个人而言,我认为这会使阅读代码变得更加困难。因此,我建议删除不必要的括号(除非它们是故意用来传达某种含义的)。