santaevpavel / OutlineSpan

Android library for outlining text
Apache License 2.0
19 stars 2 forks source link

OutlineSpan with StaticLayout and less width #3

Open mianaliasjad opened 3 years ago

mianaliasjad commented 3 years ago

I am using this OutlineSpan with StaticLayout.

It works fine when I pass the width to the static layout by measuring like that

StaticLayout.getDesiredWidth(txt, textPaint);

But When i set less width than the actual width that will wrap the text then It is the property of static layout that it automatically increases the number of lines of the text and keeps the width the one that we provide.

But when I use OutlineSpan and decrease the width it doesn't increase the number of lines instead it just draw the text with its complete width that will wrap the text.

In short, using OutlineSpan and StaticLayout with less width does not affect anything it just draws the text with actual width.

I hope you will understand my problem if you have worked with StaticLayout. Otherwise please ask me questions. Thanks

mianaliasjad commented 3 years ago

Screenshot_20200730_160809 This is the desired behavior and it is achieved when I don't use OutlineSpan.

Screenshot_20200730_160755 This is what happens when I use OutlineSpan with StaticLayout. You can see grey background shows that width is set less but OutlineSpan is still drawing text on canvas by taking complete width.

Don't get confused there was \n in this text that's why are you is in second line. If \n was not there it would still be in one big line going out of grey area.

santaevpavel commented 3 years ago

Hello @mianaliasjad, can you provide your layout file (xml) and code that outline your text?

mianaliasjad commented 3 years ago

@santaevpavel there no xml file. As i told earlier i am drawing text myself in onDraw(Canvas c) of view using StaticLayout

santaevpavel commented 3 years ago

@mianaliasjad ok, can you provide body of your onDraw(Canvas) method? I need it to reproduce the issue

mianaliasjad commented 3 years ago

    @Override
    protected void onDraw(Canvas canvas) {

        String txt = "This is the text";

        final Spannable spannableString = new SpannableString(txt);

        final OutlineSpan outLineSpan = new OutlineSpan(textBorderPaint, textPaint.getFontMetricsInt());
        spannableString.setSpan(outLineSpan, 0, txt.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

        final float w2 = StaticLayout.getDesiredWidth(txt, textPaint) * 0.5f; //here i am taking half of actual required width for this text

        StaticLayout staticLayout = new StaticLayout(spannableString, textPaint, (int) w2, Layout.Alignment.ALIGN_NORMAL, 1, lineSpacing, false);

        staticLayout.draw(canvas);
    }

In this code the class OutlineSpan is as following its functionality is same as yours but I have made a few changes according to my need:

public class OutlineSpan extends ReplacementSpan{

    private TextPaint borderPaint;
    private Paint.FontMetricsInt fontMetricsInt;

    public OutlineSpan(TextPaint borderPaint, Paint.FontMetricsInt fontMetricsInt){
        this.borderPaint = borderPaint;
        this.fontMetricsInt=fontMetricsInt;
    }

    @Override
    public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {

        if (fm != null) {

            fm.top=fontMetricsInt.top;

            fm.leading=fontMetricsInt.leading;
            fm.bottom=fontMetricsInt.bottom;
            fm.descent=fontMetricsInt.descent;

            fm.ascent=fontMetricsInt.ascent;
        }

        return (int)paint.measureText(text.toString().substring(start,end));
    }

    @Override
    public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {

        canvas.drawText(text, start, end, x, y, borderPaint); //first draw text with border paint then draw simple text
        canvas.drawText(text, start, end, x, y, paint);
    }
}

Now just play with the width that we pass to StaticLayout. No matter what you set when OutlineSpan is used it draws text by taking the actual width that it requires.

Let me know if you still have any confusion in this code. Thanks

santaevpavel commented 3 years ago

@mianaliasjad Hi, sorry for delay. I was in vacation. Is this issue actual?

mianaliasjad commented 3 years ago

@santaevpavel yes it is. Have you looked at it? I am using it because I want to draw text with the border. But if I don't use it then I have to draw two different static layouts in order to draw a border also.