Justifying text inside a TextView in android

一笑奈何 提交于 2019-12-01 07:36:41

So, after looking a bit more at this: https://github.com/ufo22940268/android-justifiedtextview and TextView in general, I discovered that my main problem was my approach.

Using the approach of scaling the width of the " " characters was sound in theory, but after doing so, the width of the line changes again, as it seems that the width of the line is NOT the sum of its parts.

I have changed my approach and took inspiration from the link above, and so in my new approach I draw each character by itself, instead of drawing the whole line. If the text needs to be justified (based on a custom "justify" boolean attribute) then it will draw the line and justify it, else it will just draw the line.

Edit: I have changed the code now so that it also supports RTL texts. I will upload the code somewhere in the next few days.

Here's the result:

Here's the code:

public class DTextView extends AppCompatTextView {


    private boolean justify;
    private float textAreaWidth;
    private float spaceCharSize;
    private float lineY;

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

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

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

    /**
     * @param attrs the attributes from the xml
     *              This function loads all the parameters from the xml
     */
    private void init(AttributeSet attrs) {

        TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.DTextView, 0, 0);

        justify = ta.getBoolean(R.styleable.DTextView_justify, false);

        ta.recycle();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawText(canvas);
    }

    private void drawText(Canvas canvas) {
        TextPaint paint = getPaint();
        paint.setColor(getCurrentTextColor());
        paint.drawableState = getDrawableState();
        textAreaWidth = getMeasuredWidth() - (getPaddingLeft() + getPaddingRight());

        spaceCharSize = paint.measureText(" ");

        String text = getText().toString();
        lineY = getTextSize();

        Layout textLayout = getLayout();

        if (textLayout == null)
            return;

        Paint.FontMetrics fm = paint.getFontMetrics();
        int textHeight = (int) Math.ceil(fm.descent - fm.ascent);
        textHeight = (int) (textHeight * getLineSpacingMultiplier() + textLayout.getSpacingAdd());

        for (int i = 0; i < textLayout.getLineCount(); i++) {

            int lineStart = textLayout.getLineStart(i);
            int lineEnd = textLayout.getLineEnd(i);

            float lineWidth = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, paint);
            String line = text.substring(lineStart, lineEnd);

            if (line.charAt(line.length() - 1) == ' ') {
                line = line.substring(0, line.length() - 1);
            }

            if (justify && i < textLayout.getLineCount() - 1) {
                drawLineJustified(canvas, line, lineWidth);
            } else {
                canvas.drawText(line, 0, lineY, paint);
            }

            lineY += textHeight;
        }

    }

    private void drawLineJustified(Canvas canvas, String line, float lineWidth) {
        TextPaint paint = getPaint();

        float emptySpace = textAreaWidth - lineWidth;
        int spaces = line.split(" ").length - 1;
        float newSpaceSize = (emptySpace / spaces) + spaceCharSize;

        float charX = 0;

        for (int i = 0; i < line.length(); i++) {
            String character = String.valueOf(line.charAt(i));
            float charWidth = StaticLayout.getDesiredWidth(character, paint);
            if (!character.equals(" ")) {
                canvas.drawText(character, charX, lineY, paint);
            }

            if (character.equals(" ") && i != line.length() - 1)
                charX += newSpaceSize;
            else
                charX += charWidth;
        }

    }
}

and the XML:

<il.co.drapp.views.text.DTextView
                android:layout_width="match_parent"
                android:inputType="textMultiLine|textNoSuggestions"
                app:justify="true"
                android:id="@+id/justifyText"
                android:text="@string/article_dummy_text"
                android:layout_height="wrap_content" />

Thanks to Aditya Vyas-Lakhan for the links

LIBRARY: https://github.com/bluejamesbond/TextJustify-Android

SUPPORTS: Android 2.0 to 5.X

SCREENSHOT

Try this way to justify text, it works for me

public class MainActivity extends Activity {

    private JustifiedTextView mJTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mJTv=(JustifiedTextView) findViewById(R.id.activity_main_jtv_text);
        mJTv.setText(getResources().getString(R.string.test));
        mJTv.setTextSize(TypedValue.COMPLEX_UNIT_SP,20);
        mJTv.setLineSpacing(15);
        mJTv.setBackgroundColor(Color.RED);
        mJTv.setAlignment(Align.LEFT);
        mJTv.setTypeFace(Typeface.createFromAsset(getAssets(), "fonts/naskh_bold.ttf"));

    }
}

XML

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main_jsv"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ir.noghteh.JustifiedTextView
        android:id="@+id/activity_main_jtv_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:padding="25dp"
        xmlns:noghteh="http://noghteh.ir"
        noghteh:text="@string/hello_world"
        noghteh:textColor="@color/text"
        noghteh:textSize="18sp"
       >
    </ir.noghteh.JustifiedTextView>

</ScrollView>

https://github.com/navabi/JustifiedTextView

https://github.com/ufo22940268/android-justifiedtextview

https://github.com/PareshMayani/Android-JustifyText

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!