Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create vertically aligned superscript and subscript in TextView

In the example of image below:

enter image description here

How can I make both the superscript and subscript numbers to be aligned to produce a common scientific notation like below

enter image description here

in TextView? If there is a way using Spannable or ReplacementSpan I would like to see a working example. Thank you.

like image 913
Neoh Avatar asked Jun 02 '14 08:06

Neoh


People also ask

How do you create a superscript in CSS?

In HTML, there is the use of <sub> and <sup> tags to define the subscript and superscript text. The superscript text appears in a smaller font and the half character above the normal line. It is generally used to write mathematical equations (like x2 + y2 = r2), footnotes, and many more.

How do you specify a subscript of text in CSS?

Explanation: In CSS, the vertical-align property is used to make the text superscript or subscript. The "sub" of vertical-align property is used to make the text subscript in CSS. The subscript text appears in a smaller font and the half character below the normal line.

How do you superscript in text?

Use keyboard shortcuts to apply superscript or subscript Select the text or number that you want. For superscript, press Ctrl, Shift, and the Plus sign (+) at the same time. For subscript, press Ctrl and the Equal sign (=) at the same time.

How do I add a newline to a TextView in Android?

Just add a \n to your text. This can be done directly in your layout file, or in a string resource and will cleanly break the text in your TextView to the next line.


1 Answers

You might want to try something like this.

It's basicall a ReplacementSpan that takes the text it's applied on, separates it into two parts, and draws them on the canvas. The size factor and y translation are somewhat hand-picked. I hope it's useful (or at least that you or someone else can build on it).

public class SuperSubSpan extends ReplacementSpan
{
    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end, FontMetricsInt fm)
    {
        text = text.subSequence(start, end);
        String[] parts = text.toString().split(",");

        Paint p = getSuperSubPaint(paint);
        return (int) Math.max(p.measureText(parts[0]), p.measureText(parts[1]));
    }

    private static TextPaint getSuperSubPaint(Paint src)
    {
        TextPaint paint = new TextPaint(src);
        paint.setTextSize(src.getTextSize() / 2.5f);
        return paint;
    }

    @Override
    public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)
    {
        text = text.subSequence(start, end);
        String[] parts = text.toString().split(",");

        Paint p = getSuperSubPaint(paint);

        float width1 = p.measureText(parts[0]);
        float width2 = p.measureText(parts[1]);
        float maxWidth = Math.max(width1, width2);

        canvas.drawText(parts[0], x + (maxWidth - width1), y - (bottom - top) / 3f, p);
        canvas.drawText(parts[1], x + (maxWidth - width2), y + (bottom - top) / 10f, p);
    }
}

Then use it as:

Spannable str = new SpannableString("9,4Be -> 2000,127Jo");
str.setSpan(new SuperSubSpan(), 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new SuperSubSpan(), 9, 17, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.setText(str);

which produces the following result:

Sample

A slightly better solution would be to have a special format for these strings (e.g. "{9,4}Be -> {2000,127}Jo") and have a regular expression process the string and add the corresponding SuperSubSpans, just so that you don't need to this manually. But the actual Span part would be more or less the same.

like image 184
matiash Avatar answered Oct 11 '22 11:10

matiash