android画布在三角形中绘制文本

时间:2017-04-24 05:33:21

标签: android canvas android-custom-view android-drawable android-bitmap

enter image description here

在此图片中,我希望文字完全位于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();
}

}

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

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情

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);

答案 1 :(得分:1)

根据想要文本的高度,可以使用类似三角形的属性来首先确定文本的最大宽度。在您的情况下,大小=三角形的底边,大小=三角形的高度/高度。让我们定义两个变量: 更正:高度不等于基准。您需要计算海拔高度才能使用以下解决方案。

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

比方说,我们希望文本位于三角形中心的一半位置:

float textYHeight = triangleHeight/2; 

由于相似三角形的边成比例,因此我们使用以下公式计算出三角形的宽度: baseOfTriangleA / baseOfTriangleB = HeightOfTriangleA / 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));