Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing Text direction for LeadingMarginSpan2

Tags:

java

android

I'm using LeadingSpanMargin2 as suggested to style my TextView so that it would flow around an Image, the problem is the text I set is dynamic and can be rtl or ltr.

I tried anything I could think of to fix the leadingMargin so that it would be either right or left in both cases, to no avail.

Also the I've tried FlowTextView widget posted in github and it doesn't work well in rtl cases, so please do not suggest that.

Many thanks.

Here's the code I use, which was suggested in another answer:

public void setFlowText(CharSequence text, int width , int height, TextView messageView)
{
    float textLineHeight = messageView.getPaint().getTextSize();

    // Set the span according to the number of lines and width of the image
    int lines = (int)Math.ceil(height / textLineHeight);
    //For an html text you can use this line: SpannableStringBuilder ss = (SpannableStringBuilder)Html.fromHtml(text);
    SpannableString ss = new SpannableString(text);
    ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    //ss.setSpan(new AlignmentSpan.Standard(Alignment.ALIGN_OPPOSITE), 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    messageView.setText(ss);

    // Align the text with the image by removing the rule that the text is to the right of the image
    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)messageView.getLayoutParams();
    int[]rules = params.getRules();
    rules[RelativeLayout.RIGHT_OF] = 0;
}

public class MyLeadingMarginSpan2 implements LeadingMarginSpan2 {
    private int margin;
    private int lines;
    private boolean wasDrawCalled = false;
    private int drawLineCount = 0;

    public MyLeadingMarginSpan2(int lines, int margin) {
        this.margin = margin;
        this.lines = lines;
    }

    @Override
    public int getLeadingMargin(boolean first) {
        boolean isFirstMargin = first;
        // a different algorithm for api 21+
        if (Build.VERSION.SDK_INT >= 21) {
            this.drawLineCount = this.wasDrawCalled ? this.drawLineCount + 1 : 0;
            this.wasDrawCalled = false;
            isFirstMargin = this.drawLineCount <= this.lines;
        }

        return isFirstMargin ? this.margin : 0;
    }

    @Override
    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {
        this.wasDrawCalled = true;
    }

    @Override
    public int getLeadingMarginLineCount() {
        return this.lines;
    }
}
like image 790
Ramin Avatar asked Nov 10 '22 08:11

Ramin


1 Answers

For the some unknown reason you can get left margin by passing:

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 

and to get right margin you need to pass:

ss.setSpan(new MyLeadingMarginSpan2(lines, width), 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

I don't know what is going on there, but this works!

like image 157
Viktor Yakunin Avatar answered Nov 14 '22 23:11

Viktor Yakunin