android canvas 在三角形中绘制文字

android canvas draw text in the triangle

在此图片中,我希望文本完全位于 CYAN 颜色的三角形中。
我已经创建了自己的 ImageView

public class BookImageView extends android.support.v7.widget.AppCompatImageView {

private static final Float DISCOUNT_SIDE_SIZE = 0.33333F;

private Bitmap bitmap;

private Paint drawPaint = new Paint();
private Paint trianglePaint = new Paint();

{
    trianglePaint.setColor(Constants.DISCOUNT_COLOR);
    trianglePaint.setStyle(Paint.Style.FILL);
    trianglePaint.setShadowLayer(10.0f, 10.0f, 10.0f, Color.parseColor("#7f000000"));
    trianglePaint.setAntiAlias(true);

    drawPaint.setColor(Color.BLACK);
    drawPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
    drawPaint.setShadowLayer(1f, 0f, 1f, Color.BLACK);
}

// Constractors ...    

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (bitmap != null) {
        Bitmap tempBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.RGB_565);
        Canvas tempCanvas = new Canvas(tempBitmap);
        tempCanvas.drawBitmap(bitmap, 0, 0, null);

        Path path = new Path();
        path.setFillType(Path.FillType.EVEN_ODD);

        float size = bitmap.getWidth() * DISCOUNT_SIDE_SIZE;

        path.lineTo(size, 0);
        path.lineTo(0, size);
        path.lineTo(0, 0);
        path.close();

        tempCanvas.drawPath(path, trianglePaint);

        float scale = getResources().getDisplayMetrics().density;

        drawPaint.setTextSize((int) (14 * scale));

        Rect textBounds = new Rect();
        drawPaint.getTextBounds("50%", 0, "50%".length(), textBounds);
        int x = (int) (size / 2) - textBounds.width() / 2;
        int y = (int) (size / 2) - textBounds.height() / 2;

        tempCanvas.save();
        tempCanvas.rotate(-45, x, y);
        tempCanvas.drawText("50%", x, y, drawPaint);
        tempCanvas.restore();

        setImageDrawable(new BitmapDrawable(getContext().getResources(), tempBitmap));
    }
}

@Override
public void setImageBitmap(Bitmap bitmap) {
    this.bitmap = bitmap;
    invalidate();
}

}

我该怎么做才能解决这个问题?

你可以试试这样的

1) 测量文本的宽度 使用 measureText

2) 从您正在绘制的点开始计算剩余的绘制宽度

3) 现在,您可以根据用例缩短文本长度或根据需要缩放文本

    int textWidthRequired = (int) drawPaint.measureText(textToDraw);
    int widthRemainingToDraw = totalWidth/2 - textDrawX;
    if(textWidthRequired > widthRemainingToDraw){
        //handling 
    }
    // draw text
   tempCanvas.drawText(textToDraw,textDrawX, textDrawY, drawPaint);

根据您希望文字的高度,您可以使用相似三角形的属性首先确定文字的最大宽度。在您的例子中,大小 = 三角形的底边,大小 = 三角形的 height/altitude。让我们定义两个变量: 更正:高度不等于基地。您需要计算海拔高度才能使用以下解决方案。

float triangleBase = size; // triangle base
float triangleAltitude = size; // Calculate this.

假设我们希望文本位于三角形中心的中间位置:

float textYHeight = triangleHeight/2; 

由于相似三角形的边是成正比的,我们用下面的公式算出此时三角形的宽度: baseOfTriangleA/baseOfTriangleB = altitudeOfTriangleA/altitudeOfTriangleB;

float triangleWidthAtTextYLocation = (textYHeight * triangleBase)/triangleAltitude;

现在我们知道三角形在这个位置的宽度是多少,我们可以迭代不同的文本比例,直到文本宽度小于值 triangleWidthAtTextYlocation。

        float scale = getResources().getDisplayMetrics().density;

        int scaleFactor = 0;
        drawPaint.setTextSize((int) (scaleFactor * scale));
        Rect textBounds = new Rect();
        drawPaint.getTextBounds("50%", 0, "50%".length(), textBounds);
        while(textBounds.length < triangleWidthAtTextYLocation){
             // Re-measure the text until it exceeds the width
             scaleFactor++;
             drawPaint.setTextSize((int) (scaleFactor * scale));
             drawPaint.getTextBounds("50%", 0, "50%".length(), textBounds);
         }

         // Once we know the scaleFactor that puts it over the width of the triangle
         // at that location, we reduce it by 1 to be just under that width:
         scaleFactor = Maths.abs(scaleFactor - 1);
         // final text size:
         drawPaint.setTextSize((int) (scaleFactor * scale));