Java android canvas drawText从宽度设置字体大小?
我想使用Java android canvas drawText从宽度设置字体大小?,java,android,android-canvas,Java,Android,Android Canvas,我想使用在画布上绘制一定宽度的文本。drawtext 例如,无论输入文本是什么,文本的宽度应始终为400px 如果输入文本较长,则会减小字体大小;如果输入文本较短,则会相应增大字体大小。请尝试以下操作: /** * Retrieve the maximum text size to fit in a given width. * @param str (String): Text to check for size. * @param maxWidth (float): Maximum a
在画布上绘制一定宽度的文本。drawtext
例如,无论输入文本是什么,文本的宽度应始终为400px
如果输入文本较长,则会减小字体大小;如果输入文本较短,则会相应增大字体大小。请尝试以下操作:
/**
* Retrieve the maximum text size to fit in a given width.
* @param str (String): Text to check for size.
* @param maxWidth (float): Maximum allowed width.
* @return (int): The desired text size.
*/
private int determineMaxTextSize(String str, float maxWidth)
{
int size = 0;
Paint paint = new Paint();
do {
paint.setTextSize(++ size);
} while(paint.measureText(str) < maxWidth);
return size;
} //End getMaxTextSize()
/**
*检索适合给定宽度的最大文本大小。
*@param str(字符串):用于检查大小的文本。
*@param maxWidth(float):允许的最大宽度。
*@return(int):所需的文本大小。
*/
私有int determineMextSize(字符串str,float maxWidth)
{
int size=0;
油漆=新油漆();
做{
油漆。setTextSize(++尺寸);
}while(paint.measureText(str)
这里有一个更有效的方法:
/**
* Sets the text size for a Paint object so a given string of text will be a
* given width.
*
* @param paint
* the Paint to set the text size for
* @param desiredWidth
* the desired width
* @param text
* the text that should be that width
*/
private static void setTextSizeForWidth(Paint paint, float desiredWidth,
String text) {
// Pick a reasonably large value for the test. Larger values produce
// more accurate results, but may cause problems with hardware
// acceleration. But there are workarounds for that, too; refer to
// http://stackoverflow.com/questions/6253528/font-size-too-large-to-fit-in-cache
final float testTextSize = 48f;
// Get the bounds of the text, using our testTextSize.
paint.setTextSize(testTextSize);
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
// Calculate the desired size as a proportion of our testTextSize.
float desiredTextSize = testTextSize * desiredWidth / bounds.width();
// Set the paint for that size.
paint.setTextSize(desiredTextSize);
}
然后,您需要做的就是setTextSizeForWidth(paint,400,str)代码>(400为问题中的示例宽度)
为了获得更高的效率,您可以将Rect
设置为静态类成员,避免每次实例化它。但是,这可能会带来并发性问题,并且可能会阻碍代码的清晰性。看起来不错,但对我来说不起作用,我需要获得视图中可能绘制的最大文本大小,但这种方法取决于您设置的第一个文本大小,每次你设置不同的尺寸,你会得到不同的结果,不能说这是正确的答案在每种情况下
所以我尝试了另一种方法:
private float calculateMaxTextSize(String text, Paint paint, int maxWidth, int maxHeight) {
if (text == null || paint == null) return 0;
Rect bound = new Rect();
float size = 1.0f;
float step= 1.0f;
while (true) {
paint.getTextBounds(text, 0, text.length(), bound);
if (bound.width() < maxWidth && bound.height() < maxHeight) {
size += step;
paint.setTextSize(size);
} else {
return size - step;
}
}
}
private float calculateMaxSize(字符串文本、油漆、int-maxWidth、int-maxHeight){
if(text==null | | paint==null)返回0;
Rect-bound=新的Rect();
浮子尺寸=1.0f;
浮动步长=1.0f;
while(true){
paint.getTextBounds(text,0,text.length(),bound);
if(bound.width()
很简单,我增加文本大小,直到文本矩形边界的尺寸足够接近maxWidth
和maxHeight
,以减少循环重复,只需将step
更改为更大的值(精度与速度),也许这不是实现这一点的最佳方法,但它是有效的。只是出于好奇,为什么要返回尺寸/2
?我想有一个很好的理由我现在想不起来,但是size-1
对我来说更有意义:/告诉你真相,我记不清了。我知道我试过使用-1
,但认为我没有得到我想要的东西。这不起作用。。我正在做的是将maxwidth设置为我手机的屏幕宽度,即560px,但当我设置它时,它不适合屏幕,它比这个大得多。字体大小并没有相应地改变。哦,现在我正在传递不同的字符串值并绘制不同的字符串。我的错。它与size
而不是size/2
一起工作。请编辑您的答案。这里面有一个bug。您不处理str没有字符或只有空格的情况。你因为它而永远迭代。将此添加为第一行<代码>如果(str==null | | str.trim().length()==0)返回0代码>啊,见鬼!:-)很高兴能帮上忙。我能知道你从哪里选的400吗?因为我试过你的方法,但我的一些文本会从画布上消失,比如一两个字母。我试过bitmap.getwidth(),它更好,但仍然不够有效。@Chisko:当然,因为我从1997年开始编写Java,我想它是合适的。☺ 当一个方法是静态的时,无论类有多少个实例,每个JVM都只有一个副本。但对于非静态方法,类的每个实例都有一个副本,因此可以有多个局部变量副本,我相信字节码本身也是如此。我承认这在你的Android应用程序中可能是相当学术的,如果你只创建了一个实例,不管你把代码放在哪个类中,但这是一个好习惯。我强烈推荐布洛赫的书以获取更多信息。更直接地回答你的问题:还有谁会使用这种方法?类的其他实例。假设您编写了一个小部件并将setTextSizeForWidth
放入其中,您的应用程序就有三个这样的小部件。如果您的小部件的类使此方法成为静态的,则将有一个副本。如果没有,就有三个。三个副本一次只能使用一个方法,但每次都会为两个浮点分配新内存,直到垃圾回收后才会释放。同样,在这种情况下是次要的,但对于较大对象的较大集合,它可能会很快导致问题。这与@slybloty的答案具有相同的效率问题。我也不明白你在我的解决方案中遇到的问题;关键是,不同的宽度会有不同的文本大小。如果我记得rightfloat desiredTextSize=testTextSize*desiredWidth/bounds.width(),那么你能留下一条注释,并举例说明它没有返回正确大小的参数吗?老实说,你的解决方案是有效的,但不是我所期望的
返回一个可接受的值,但不一定是最大大小,毫无疑问,您的解决方案更有效,但我认为结果与所需的宽度
有很大的关系,而不是像我所需要的那样精确,因为您试图适应最大高度和最大宽度?尝试float desiredTextSize=testTextSize*Math.min(desiredWidth/bounds.width(),desiredHeight/bounds.height())
。在任何情况下,都要注意解决方案中的整数;它们将导致浮点值只包含整数值,而整数值可能没有您需要的那么精确。