如何在画布上为android自定义视图绘制一个段落

时间:2013-01-18 07:28:25

标签: android android-canvas

我要在画布上绘制大量文本..我能够设置文本,但所有文本都显示在一行。所以我无法读取所有文本..我想设置文本作为画布上的段落。任何人都可以告诉我实现此功能的方法。

我尝试使用getLineCount(),getLineBound(),但由于我的视图不包含这些方法,因此它会在这些行上提示错误。

1 个答案:

答案 0 :(得分:2)

您可能必须找到可以在画布宽度内容纳的最长子字符串并重复此字符串,直到您的整个“冗长”字符串被分成较小的字符串。递归有助于

您可以尝试这样的事情:

class Font
{
    private TextPaint tp = new TextPaint();
    private Paint p = new Paint();

    int getCharWidth(char ch, int fontSize)
    {
        tp.setTextSize(fontSize);
        Rect r = new Rect();
        tp.getTextBounds(String.valueOf(ch), 0, 1, r);
        return r.width();
    }

    int getHeight(int fontSize)
    {
        tp.setTextSize(fontSize);
        Rect r = new Rect();
        tp.getTextBounds(String.valueOf('A'), 0, 1, r);
        return r.height();
    }

    int getStringWidth(String str, int fontSize)
    {
        p.setTextSize(fontSize);
        tp.setTextSize(fontSize);
        Rect r = new Rect();
        tp.getTextBounds(str, 0, str.length(), r);          
        return r.width();//you may also try p.measureText(str);
    }
}

public String getLongestSubString(int width, int fontSize, String text)
{   
    int maxCharPerLine = width / (new Font()).getCharWidth('A', fontSize);
    int stringWidth = (new Font()).getStringWidth(text, fontSize);
    int posOfSpace = text.lastIndexOf(' ');
    if( stringWidth <= width || maxCharPerLine >= text.length())
        return text;
    String temp = text.substring(0, (posOfSpace == -1) ? (maxCharPerLine > text.length() ? text.length() : maxCharPerLine) : posOfSpace);
    return getLongestSubString(width, fontSize, temp);
}

public ArrayList<String> breakTextToLines(int width, int fontSize, String text)
{
    if(text == null)
        return null;
    ArrayList<String> lines = new ArrayList<String>();

    text = text.replace("\n", " ");

    int length = -1;
    String tempText = "";

    do
    {
        if( !tempText.endsWith(" ") && tempText.length() > 0)
            length += tempText.length();
        else
            length += tempText.length() + 1;

        if( length >= text.length())
            break;

        tempText = getLongestSubString(width, fontSize, text.substring(length));
        lines.add(tempText);
    }
    while(length < text.length());

    return lines;
}

现在,一旦你将字符串列表(使用方法breakTextToLines(int,int,String))分解为现在可以放入画布的较小字符串,就可以开始绘制过程,如下所示

int fontSize = 20;
float lineSpaceFactor = 0.5f;
int lineHeight = (new Font()).getHeight(fontSize);
int lineSpace = (int)(lineSpaceFactor * lineHeight);

int width = 256;//your canvas width can go here
int height = 256;//your canvas height can go here
String string = "Need a lengthy string? why not Dr Zoidberg maybe? woop woop woop!!!";//your lengthy string can go here
Canvas canvas = new Canvas(bitmap);//your canvas or bitmap source goes here
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextAlign(Align.CENTER);
paint.setTextSize(fontSize);

ArrayList<String> lines = breakTextToLines(width, fontSize, string);
int numOfLines = lines.size();
int overallHeight = numOfLines * (lineHeight + lineSpace);

int yLoc = (height - overallHeight) / 2;
yLoc += lineSpace;

for(String line : lines)
{
    int xLoc = textureWidth /2 ;       
    canvas.drawText(text, xLoc, yLoc, paint);

    yLoc += (lineHeight + lineSpace);       
}
//your canvas would now be drawn with the paragraph broken into lines and centre aligned 

希望这有帮助。