Q:

Android: Draw two strings in an arch next to each other on a canvas

Why this question is not a duplicate: The reference question explains how to add a single string to a curved path.. I'm trying to find out how to to add two strings with different fonts/styles to a curved path

I have two string that need to be drawn with different styles on the upper part of a circle.
I have tried a couple of things but all I manage to achieve is to draw each string on top of each other or on opposite ends (with a huge gap between them).
This is an example of what I'm trying to achieve:

Here is the code I have so far:
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
            );
        }
    }
}

Is there a way to achieve this on Android?

A:

As I was about to set a bounty on this question I got an idea.. and it worked :D
I calculated half the size of the title text and added it as an horizontal offset to the draw call for the stringInfo and subtracted half the size of the info text to the horizontal offset to the draw call for the stringTitle.
Here is the full code:
public class LabeledImageView extends ImageView
{
    Path path;
    Paint infoTextPaint;
    Paint titleTextPaint;

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

    float titleHorizontalOffset = 0.0f;//Added this line
    float infoHorizontalOffset = 0.0f;//Added this line

    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;

        titleHorizontalOffset = endX;//Added this line

        temp.setTypeface(null, Typeface.NORMAL);
        temp.setText(stringInfo);
        temp.setTextSize(smallTextSize);
        infoHorizontalOffset = Utils.measureView(
                getContext(),
                (int) ((cx / 2.0f) * Math.PI),
                temp,
                true
        ).x;//Added this line

        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,
                    -titleHorizontalOffset,//Changed this line
                    0,
                    titleTextPaint
            );

            canvas.drawTextOnPath(
                    stringInfo,
                    path,
                    infoHorizontalOffset - titleHorizontalOffset,//Changed this line
                    0,
                    infoTextPaint
            );
        }
    }
}

