Android:在画布上彼此相邻的拱形中绘制两个字符串

时间:2015-09-29 14:48:42

标签: android canvas

为什么这个问题不重复:参考问题解释了如何将单个字符串添加到曲线路径..我正在尝试找出如何添加两个不同字体的字符串/样式到弯曲的路径

我有两个字符串需要在圆圈的上半部分以不同的样式绘制。

我尝试了几件事,但我设法实现的是将每个字符串绘制在彼此之上或相反的两端(它们之间存在巨大差距)。

这是我想要实现的一个例子:

Arched text

这是我到目前为止的代码:

public class LabeledImageView extends ImageView
{
    Path path;
    Paint infoTextPaint;
    Paint titleTextPaint;

    String stringTitle = "Test name ";
    String stringInfo = "0/20";

    public LabeledImageView(Context context)
    {
        super(context);
    }

    public LabeledImageView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    public LabeledImageView(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    @SuppressLint("NewApi")
    public LabeledImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void buildArch()
    {
        int textColor = Color.WHITE;

        float cx = (float) getWidth() / 2.0f;
        float cy = (float) getHeight() / 2.0f;

        Point textSizePoint;
        float rInn;
        float rOut;
        float endX;

        float varTextSize = 14.0f;

        CFTextView temp = new CFTextView(getContext());//CFTextView is a TextView that uses a custom font
        temp.setSingleLine(true);
        temp.setTypeface(null, Typeface.BOLD);
        temp.setText(stringTitle + stringInfo);
        temp.setLayoutParams(
                new ViewGroup.LayoutParams(
                        (int) ((cx / 2.0f) * Math.PI),
                        ViewGroup.LayoutParams.WRAP_CONTENT
                )
        );
        temp.setPadding(0, 0, 0, 0);

        do
        {
            temp.setTextSize(varTextSize);

            textSizePoint = Utils.measureView(
                    getContext(),
                    (int) ((cx / 2.0f) * Math.PI),
                    temp,
                    true
            );//This method forces the view to draw and returns a Point with the final size of the view

            rInn = (float) getWidth() / 2.0f;
            rOut = rInn + textSizePoint.y;

            endX = (float) textSizePoint.x / 2.0f;

            varTextSize--;
        }while(endX >= rOut);

        float textSize = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP,
                varTextSize,
                Resources.getSystem().getDisplayMetrics()
        );

        float smallTextSize = TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_SP,
                varTextSize - 2 > 2 ? varTextSize - 2 : varTextSize,
                Resources.getSystem().getDisplayMetrics()
        );

        float angle = 90.0f - (float) Math.toDegrees(Math.acos(endX / rOut));

        float startAngle = -(angle + 90.0f);
        float sweepAngle = 2.0f * angle;

        titleTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        titleTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        titleTextPaint.setColor(textColor);
        titleTextPaint.setTextSize(textSize);
        titleTextPaint.setTextAlign(Paint.Align.CENTER);
        titleTextPaint.setTypeface(
                FontManager.getFontUrl(
                        getContext(),
                        Typeface.BOLD
                )//FontManager.getFontUrl returns a custom TypeFace
        );

        infoTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        infoTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        infoTextPaint.setColor(textColor);
        infoTextPaint.setTextSize(smallTextSize);
        infoTextPaint.setTextAlign(Paint.Align.CENTER);
        infoTextPaint.setTypeface(
                FontManager.getFontUrl(
                        getContext(),
                        Typeface.NORMAL
                )//FontManager.getFontUrl returns a custom TypeFace
        );

        path = new Path();
        float r = rInn;
        r += textSize * 0.1f;
        RectF segment = new RectF(cx - r, cy - r, cx + r, cy + r);
        path.addArc(segment, startAngle, sweepAngle);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        if(path == null && getWidth() > 0)
        {
            buildArch();
        }

        if(path != null)
        {
            canvas.drawTextOnPath(
                    stringTitle,
                    path,
                    0,
                    0,
                    titleTextPaint
            );

            canvas.drawTextOnPath(
                    stringInfo,
                    path,
                    0,
                    0,
                    infoTextPaint
            );
        }
    }
}

有没有办法在Android上实现这一目标?

1 个答案:

答案 0 :(得分:0)

当我准备在这个问题上获得赏金时,我有了一个想法......它有效:D

我计算了标题文本大小的一半,并将其作为水平偏移量添加到stringInfo的绘制调用中,并将信息文本大小的一半减去相对于{的绘制调用的水平偏移量{1}}。

以下是完整代码:

stringTitle