Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/190.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android文本视图调整文本_Android_Text_Format_Textview_Justify - Fatal编程技术网

Android文本视图调整文本

Android文本视图调整文本,android,text,format,textview,justify,Android,Text,Format,Textview,Justify,如何使TextView的文本对齐(文本在左侧和右侧齐平) 我找到了一个可能的解决方案,但它不起作用(即使您将垂直中心更改为垂直中心,等等)。我认为Android不支持完全对齐 更新2018-01-01:Android 8.0+支持。我不相信Android支持完全正当性 更新2018-01-01:Android 8.0+支持。您必须设置 android:layout_height="wrap_content" 及 你必须把它设置好 android:layout_height="wrap_cont

如何使
TextView
的文本对齐(文本在左侧和右侧齐平)


我找到了一个可能的解决方案,但它不起作用(即使您将垂直中心更改为垂直中心,等等)。

我认为Android不支持完全对齐


更新2018-01-01:Android 8.0+支持。

我不相信Android支持完全正当性

更新2018-01-01:Android 8.0+支持。

您必须设置

android:layout_height="wrap_content"

你必须把它设置好

android:layout_height="wrap_content"


@commonware的答案是正确的。安卓8.0+确实支持“完全正当化”(或者简单地说是“正当化”,因为它有时被含糊不清地提到)

Android还支持“刷新左/右文本对齐”。有关区别,请参见维基百科上的文章。许多人认为“正当化”的概念包括完全的正当性和左/右文本对齐,这是他们在想要做左/右文本对齐时最终搜索的。这个答案解释了如何实现左/右文本对齐

可以实现齐平的左/右文本对齐(与问题所涉及的完全对齐相反)。为了演示,我将使用基本的2列表单(标签在左列,文本字段在右列)作为示例。在本例中,左列标签中的文本将右对齐,以便它们与右列中的文本字段对齐

在XML布局中,通过在所有TextView中添加以下属性,可以使TextView元素自身(左列)向右对齐:

<TextView
   ...
   android:layout_gravity="center_vertical|end">
   ...
</TextView>

...
但是,如果文本换行到多行,文本仍将在TextView中左对齐。添加以下属性将使实际文本在TextView中向右对齐(向左参差不齐):

<TextView
   ...
   android:gravity="end">
   ...
</TextView>

...

因此gravity属性指定如何对齐TextView中的文本布局\u gravity指定如何对齐/布局TextView元素本身。

Commonware的答案是正确的。安卓8.0+确实支持“完全正当化”(或者简单地说是“正当化”,因为它有时被含糊不清地提到)

Android还支持“刷新左/右文本对齐”。有关区别,请参见维基百科上的文章。许多人认为“正当化”的概念包括完全的正当性和左/右文本对齐,这是他们在想要做左/右文本对齐时最终搜索的。这个答案解释了如何实现左/右文本对齐

可以实现齐平的左/右文本对齐(与问题所涉及的完全对齐相反)。为了演示,我将使用基本的2列表单(标签在左列,文本字段在右列)作为示例。在本例中,左列标签中的文本将右对齐,以便它们与右列中的文本字段对齐

在XML布局中,通过在所有TextView中添加以下属性,可以使TextView元素自身(左列)向右对齐:

<TextView
   ...
   android:layout_gravity="center_vertical|end">
   ...
</TextView>

...
但是,如果文本换行到多行,文本仍将在TextView中左对齐。添加以下属性将使实际文本在TextView中向右对齐(向左参差不齐):

<TextView
   ...
   android:gravity="end">
   ...
</TextView>

...

因此,gravity属性指定如何对齐TextView中的文本layout\u gravity指定如何对齐/布局TextView元素本身。

为了在android中对齐文本,我使用了WebView

    setContentView(R.layout.main);

    WebView view = new WebView(this);
    view.setVerticalScrollBarEnabled(false);

    ((LinearLayout)findViewById(R.id.inset_web_view)).addView(view);

    view.loadData(getString(R.string.hello), "text/html; charset=utf-8", "utf-8");
和html

<string name="hello">
<![CDATA[
<html>
 <head></head>
 <body style="text-align:justify;color:gray;background-color:black;">
  Lorem ipsum dolor sit amet, consectetur 
  adipiscing elit. Nunc pellentesque, urna
  nec hendrerit pellentesque, risus massa
 </body>
</html>
]]>
</string>

洛雷姆·伊普苏姆·多洛·希特·阿梅特,康塞特图
告别精英。努克佩伦茨克,乌尔纳
nec亨德雷特·佩伦茨克,里索斯·马萨
]]>

我还不能上传图片来证明这一点,但“它对我有用”。

为了证明android中的文本是正确的,我使用了WebView

    setContentView(R.layout.main);

    WebView view = new WebView(this);
    view.setVerticalScrollBarEnabled(false);

    ((LinearLayout)findViewById(R.id.inset_web_view)).addView(view);

    view.loadData(getString(R.string.hello), "text/html; charset=utf-8", "utf-8");
和html

<string name="hello">
<![CDATA[
<html>
 <head></head>
 <body style="text-align:justify;color:gray;background-color:black;">
  Lorem ipsum dolor sit amet, consectetur 
  adipiscing elit. Nunc pellentesque, urna
  nec hendrerit pellentesque, risus massa
 </body>
</html>
]]>
</string>

洛雷姆·伊普苏姆·多洛·希特·阿梅特,康塞特图
告别精英。努克佩伦茨克,乌尔纳
nec亨德雷特·佩伦茨克,里索斯·马萨
]]>

我还不能上传图片来证明这一点,但“它对我有用”。

我认为有两种选择:

  • 使用类似Pango的工具,通过NDK专门处理这个问题,并将文本渲染到OpenGL或其他曲面

  • 使用和friends获取单词的长度,并在自定义视图的画布上手动布局


    • 我认为有两种选择:

      • 使用类似Pango的工具,通过NDK专门处理这个问题,并将文本渲染到OpenGL或其他曲面

      • 使用和friends获取单词的长度,并在自定义视图的画布上手动布局


      尝试使用RelativeLayout>(确保填写父项),然后只需添加
      android:layout\u alignParentLeft=“true”

      android:layout\u alignParentRight=“true”
      到您想要的左、右外侧元素


      罪有应得

      尝试使用<
      RelativeLayout>
      (确保填写父项),然后只需添加
      android:layout\u alignParentLeft=“true”

      android:layout\u alignParentRight=“true”
      到您想要的左、右外侧元素


      罪有应得

      对于html格式化,您不需要调用Webkit,您可以使用
      html.fromHtml(text)
      来完成这项工作


      来源:

      对于html格式化,您不需要调用Webkit,您可以使用
      html.fromHtml(text)
      来完成这项工作


      资料来源:

      我是这样做的,我认为这是我能做到的最优雅的方式。使用此解决方案,您只需在布局中执行以下操作:

      • 添加一个额外的
        x
        
        <td style="font-family:Calibri,Arial;
            font-size:15px;
            font-weight:800;
            background-color:#f5d5fd;
            color:black;
            border-style:solid;
            border-width:1px;
            border-color:#bd07eb;
            padding-left:10px;
            padding-right:1000px;
            padding-top:3px;
            padding-bottom:3px;
        >
        
        android:gravity="center_horizontal"
        
        case Gravity.CENTER_HORIZONTAL:
        case Gravity.FILL_HORIZONTAL:
            return (mLayout.getLineWidth(0) - ((mRight - mLeft) -
                    getCompoundPaddingLeft() - getCompoundPaddingRight())) /
                    getHorizontalFadingEdgeLength();
        
        package com.fawad.textjustification;
        import android.app.Activity;
        import android.database.Cursor;
        import android.graphics.Point;
        import android.graphics.Typeface;
        import android.os.Bundle;
        import android.util.DisplayMetrics;
        import android.view.Display;
        import android.view.Gravity;
        import android.view.Menu;
        import android.widget.TextView;
        
        public class MainActivity extends Activity {
            static Point size;
            static float density;
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
        
                Display display = getWindowManager().getDefaultDisplay();
                size=new Point();
                DisplayMetrics dm=new DisplayMetrics();
                display.getMetrics(dm);
                density=dm.density;
                display.getSize(size);
        
        
                TextView tv=(TextView)findViewById(R.id.textView1);
                Typeface typeface=Typeface.createFromAsset(this.getAssets(), "Roboto-Medium.ttf");
                tv.setTypeface(typeface);
                tv.setLineSpacing(0f, 1.2f);
                tv.setTextSize(10*MainActivity.density);
        
                //some random long text
                 String myText=getResources().getString(R.string.my_text);
        
                 tv.setText(myText);
                TextJustification.justify(tv,size.x);
        
        
            }
        
            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
            }
        
        }
        
        package com.fawad.textjustification;
        
        import java.util.ArrayList;
        
        import android.graphics.Paint;
        import android.text.TextUtils;
        import android.widget.TextView;
        
        public class TextJustification {
        
            public static void justify(TextView textView,float contentWidth) {
                String text=textView.getText().toString();
                Paint paint=textView.getPaint();
        
                ArrayList<String> lineList=lineBreak(text,paint,contentWidth);
        
                textView.setText(TextUtils.join(" ", lineList).replaceFirst("\\s", ""));
            }
        
        
            private static ArrayList<String> lineBreak(String text,Paint paint,float contentWidth){
                String [] wordArray=text.split("\\s"); 
                ArrayList<String> lineList = new ArrayList<String>();
                String myText="";
        
                for(String word:wordArray){
                    if(paint.measureText(myText+" "+word)<=contentWidth)
                        myText=myText+" "+word;
                    else{
                        int totalSpacesToInsert=(int)((contentWidth-paint.measureText(myText))/paint.measureText(" "));
                        lineList.add(justifyLine(myText,totalSpacesToInsert));
                        myText=word;
                    }
                }
                lineList.add(myText);
                return lineList;
            }
        
            private static String justifyLine(String text,int totalSpacesToInsert){
                String[] wordArray=text.split("\\s");
                String toAppend=" ";
        
                while((totalSpacesToInsert)>=(wordArray.length-1)){
                    toAppend=toAppend+" ";
                    totalSpacesToInsert=totalSpacesToInsert-(wordArray.length-1);
                }
                int i=0;
                String justifiedText="";
                for(String word:wordArray){
                    if(i<totalSpacesToInsert)
                        justifiedText=justifiedText+word+" "+toAppend;
        
                    else                
                        justifiedText=justifiedText+word+toAppend;
        
                    i++;
                }
        
                return justifiedText;
            }
        
        }
        
         <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
        
            tools:context=".MainActivity" 
            >
        
        
        
            <ScrollView
                android:id="@+id/scrollView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                 >
        
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:orientation="vertical"
        
                     >
                    <TextView
                android:id="@+id/textView1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/hello_world" />
                </LinearLayout>
            </ScrollView>
        
        </RelativeLayout>
        
        import java.util.ArrayList;
        import android.content.Context;
        import android.graphics.Canvas;
        import android.graphics.Color;
        import android.graphics.Paint;
        import android.graphics.Typeface;
        import android.text.TextPaint;
        import android.view.View;
        
        public class JustifiedTextView extends View {
                String text;
                ArrayList<Line> linesCollection = new ArrayList<Line>();
                TextPaint textPaint;
                Typeface font;
                int textColor;
                float textSize = 42f, lineHeight = 57f, wordSpacing = 15f, lineSpacing = 15f;
                float onBirim, w, h;
                float leftPadding, rightPadding;
        
                public JustifiedTextView(Context context, String text) {
                        super(context);
                        this.text = text;
                        init();
                }
        
                private void init() {
                        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
                        textColor = Color.BLACK;
                }
        
                @Override
                protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
                        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
                        if (font != null) {
                                font = Typeface.createFromAsset(getContext().getAssets(), "font/Trykker-Regular.ttf");
                                textPaint.setTypeface(font);
                        }
                        textPaint.setColor(textColor);
        
                        int minw = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth();
                        w = resolveSizeAndState(minw, widthMeasureSpec, 1);
                        h = MeasureSpec.getSize(widthMeasureSpec);
        
                        onBirim = 0.009259259f * w;
                        lineHeight = textSize + lineSpacing;
                        leftPadding = 3 * onBirim + getPaddingLeft();
                        rightPadding = 3 * onBirim + getPaddingRight();
        
                        textPaint.setTextSize(textSize);
        
                        wordSpacing = 15f;
                        Line lineBuffer = new Line();
                        this.linesCollection.clear();
                        String[] lines = text.split("\n");
                        for (String line : lines) {
                                String[] words = line.split(" ");
                                lineBuffer = new Line();
                                float lineWidth = leftPadding + rightPadding;
                                float totalWordWidth = 0;
                                for (String word : words) {
                                        float ww = textPaint.measureText(word) + wordSpacing;
                                        if (lineWidth + ww + (lineBuffer.getWords().size() * wordSpacing) > w) {// is
                                                lineBuffer.addWord(word);
                                                totalWordWidth += textPaint.measureText(word);
                                                lineBuffer.setSpacing((w - totalWordWidth - leftPadding - rightPadding) / (lineBuffer.getWords().size() - 1));
                                                this.linesCollection.add(lineBuffer);
                                                lineBuffer = new Line();
                                                totalWordWidth = 0;
                                                lineWidth = leftPadding + rightPadding;
                                        } else {
                                                lineBuffer.setSpacing(wordSpacing);
                                                lineBuffer.addWord(word);
                                                totalWordWidth += textPaint.measureText(word);
                                                lineWidth += ww;
                                        }
                                }
                                this.linesCollection.add(lineBuffer);
                        }
                        setMeasuredDimension((int) w, (int) ((this.linesCollection.size() + 1) * lineHeight + (10 * onBirim)));
                }
        
                @Override
                protected void onDraw(Canvas canvas) {
                        super.onDraw(canvas);
                        canvas.drawLine(0f, 10f, getMeasuredWidth(), 10f, textPaint);
                        float x, y = lineHeight + onBirim;
                        for (Line line : linesCollection) {
                                x = leftPadding;
                                for (String s : line.getWords()) {
                                        canvas.drawText(s, x, y, textPaint);
                                        x += textPaint.measureText(s) + line.spacing;
                                }
                                y += lineHeight;
                        }
                }
        
                public String getText() {
                        return text;
                }
        
                public void setText(String text) {
                        this.text = text;
                }
        
                public Typeface getFont() {
                        return font;
                }
        
                public void setFont(Typeface font) {
                        this.font = font;
                }
        
                public float getLineHeight() {
                        return lineHeight;
                }
        
                public void setLineHeight(float lineHeight) {
                        this.lineHeight = lineHeight;
                }
        
                public float getLeftPadding() {
                        return leftPadding;
                }
        
                public void setLeftPadding(float leftPadding) {
                        this.leftPadding = leftPadding;
                }
        
                public float getRightPadding() {
                        return rightPadding;
                }
        
                public void setRightPadding(float rightPadding) {
                        this.rightPadding = rightPadding;
                }
        
                public void setWordSpacing(float wordSpacing) {
                        this.wordSpacing = wordSpacing;
                }
        
                public float getWordSpacing() {
                        return wordSpacing;
                }
        
                public float getLineSpacing() {
                        return lineSpacing;
                }
        
                public void setLineSpacing(float lineSpacing) {
                        this.lineSpacing = lineSpacing;
                }
        
                class Line {
                        ArrayList<String> words = new ArrayList<String>();
                        float spacing = 15f;
        
                        public Line() {
                        }
        
                        public Line(ArrayList<String> words, float spacing) {
                                this.words = words;
                                this.spacing = spacing;
                        }
        
                        public void setSpacing(float spacing) {
                                this.spacing = spacing;
                        }
        
                        public float getSpacing() {
                                return spacing;
                        }
        
                        public void addWord(String s) {
                                words.add(s);
                        }
        
                        public ArrayList<String> getWords() {
                                return words;
                        }
                }
        }
        
        JustifiedTextView jtv= new JustifiedTextView(getApplicationContext(), "Lorem ipsum dolor sit amet... ");
        LinearLayout place = (LinearLayout) findViewById(R.id.book_profile_content);
        place.addView(jtv);
        
        // Please visit Github for latest setup instructions.
        
        <WebView
         android:id="@+id/textContent"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content" />
        
        WebView view = (WebView) findViewById(R.id.textContent);
        String text;
        text = "<html><body><p align=\"justify\">";
        text+= "This is the text will be justified when displayed!!!";
        text+= "</p></body></html>";
        view.loadData(text, "text/html", "utf-8");
        
        public static void justify(final TextView textView) {
        
            final AtomicBoolean isJustify = new AtomicBoolean(false);
        
            final String textString = textView.getText().toString();
        
            final TextPaint textPaint = textView.getPaint();
        
            final SpannableStringBuilder builder = new SpannableStringBuilder();
        
            textView.post(new Runnable() {
                @Override
                public void run() {
        
                    if (!isJustify.get()) {
        
                        final int lineCount = textView.getLineCount();
                        final int textViewWidth = textView.getWidth();
        
                        for (int i = 0; i < lineCount; i++) {
        
                            int lineStart = textView.getLayout().getLineStart(i);
                            int lineEnd = textView.getLayout().getLineEnd(i);
        
                            String lineString = textString.substring(lineStart, lineEnd);
        
                            if (i == lineCount - 1) {
                                builder.append(new SpannableString(lineString));
                                break;
                            }
        
                            String trimSpaceText = lineString.trim();
                            String removeSpaceText = lineString.replaceAll(" ", "");
        
                            float removeSpaceWidth = textPaint.measureText(removeSpaceText);
                            float spaceCount = trimSpaceText.length() - removeSpaceText.length();
        
                            float eachSpaceWidth = (textViewWidth - removeSpaceWidth) / spaceCount;
        
                            SpannableString spannableString = new SpannableString(lineString);
                            for (int j = 0; j < trimSpaceText.length(); j++) {
                                char c = trimSpaceText.charAt(j);
                                if (c == ' ') {
                                    Drawable drawable = new ColorDrawable(0x00ffffff);
                                    drawable.setBounds(0, 0, (int) eachSpaceWidth, 0);
                                    ImageSpan span = new ImageSpan(drawable);
                                    spannableString.setSpan(span, j, j + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                                }
                            }
        
                            builder.append(spannableString);
                        }
        
                        textView.setText(builder);
                        isJustify.set(true);
                    }
                }
            });
        }
        
        public class TextJustifyUtils {
            // Please use run(...) instead
            public static void justify(TextView textView) {
                Paint paint = new Paint();
        
                String[] blocks;
                float spaceOffset = 0;
                float textWrapWidth = 0;
        
                int spacesToSpread;
                float wrappedEdgeSpace;
                String block;
                String[] lineAsWords;
                String wrappedLine;
                String smb = "";
                Object[] wrappedObj;
        
                // Pull widget properties
                paint.setColor(textView.getCurrentTextColor());
                paint.setTypeface(textView.getTypeface());
                paint.setTextSize(textView.getTextSize());
        
                textWrapWidth = textView.getWidth();
                spaceOffset = paint.measureText(" ");
                blocks = textView.getText().toString().split("((?<=\n)|(?=\n))");
        
                if (textWrapWidth < 20) {
                    return;
                }
        
                for (int i = 0; i < blocks.length; i++) {
                    block = blocks[i];
        
                    if (block.length() == 0) {
                        continue;
                    } else if (block.equals("\n")) {
                        smb += block;
                        continue;
                    }
        
                    block = block.trim();
        
                    if (block.length() == 0)
                        continue;
        
                    wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
                            spaceOffset, textWrapWidth);
                    wrappedLine = ((String) wrappedObj[0]);
                    wrappedEdgeSpace = (Float) wrappedObj[1];
                    lineAsWords = wrappedLine.split(" ");
                    spacesToSpread = (int) (wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
                            / spaceOffset
                            : 0);
        
                    for (String word : lineAsWords) {
                        smb += word + " ";
        
                        if (--spacesToSpread > 0) {
                            smb += " ";
                        }
                    }
        
                    smb = smb.trim();
        
                    if (blocks[i].length() > 0) {
                        blocks[i] = blocks[i].substring(wrappedLine.length());
        
                        if (blocks[i].length() > 0) {
                            smb += "\n";
                        }
        
                        i--;
                    }
                }
        
                textView.setGravity(Gravity.LEFT);
                textView.setText(smb);
            }
        
            protected static Object[] createWrappedLine(String block, Paint paint,
                    float spaceOffset, float maxWidth) {
                float cacheWidth = maxWidth;
                float origMaxWidth = maxWidth;
        
                String line = "";
        
                for (String word : block.split("\\s")) {
                    cacheWidth = paint.measureText(word);
                    maxWidth -= cacheWidth;
        
                    if (maxWidth <= 0) {
                        return new Object[] { line, maxWidth + cacheWidth + spaceOffset };
                    }
        
                    line += word + " ";
                    maxWidth -= spaceOffset;
        
                }
        
                if (paint.measureText(block) <= origMaxWidth) {
                    return new Object[] { block, Float.MIN_VALUE };
                }
        
                return new Object[] { line, maxWidth };
            }
        
            final static String SYSTEM_NEWLINE = "\n";
            final static float COMPLEXITY = 5.12f; // Reducing this will increase
                                                    // efficiency but will decrease
                                                    // effectiveness
            final static Paint p = new Paint();
        
            public static void run(final TextView tv, float origWidth) {
                String s = tv.getText().toString();
                p.setTypeface(tv.getTypeface());
                String[] splits = s.split(SYSTEM_NEWLINE);
                float width = origWidth - 5;
                for (int x = 0; x < splits.length; x++)
                    if (p.measureText(splits[x]) > width) {
                        splits[x] = wrap(splits[x], width, p);
                        String[] microSplits = splits[x].split(SYSTEM_NEWLINE);
                        for (int y = 0; y < microSplits.length - 1; y++)
                            microSplits[y] = justify(removeLast(microSplits[y], " "),
                                    width, p);
                        StringBuilder smb_internal = new StringBuilder();
                        for (int z = 0; z < microSplits.length; z++)
                            smb_internal.append(microSplits[z]
                                    + ((z + 1 < microSplits.length) ? SYSTEM_NEWLINE
                                            : ""));
                        splits[x] = smb_internal.toString();
                    }
                final StringBuilder smb = new StringBuilder();
                for (String cleaned : splits)
                    smb.append(cleaned + SYSTEM_NEWLINE);
                tv.setGravity(Gravity.LEFT);
                tv.setText(smb);
            }
        
            private static String wrap(String s, float width, Paint p) {
                String[] str = s.split("\\s"); // regex
                StringBuilder smb = new StringBuilder(); // save memory
                smb.append(SYSTEM_NEWLINE);
                for (int x = 0; x < str.length; x++) {
                    float length = p.measureText(str[x]);
                    String[] pieces = smb.toString().split(SYSTEM_NEWLINE);
                    try {
                        if (p.measureText(pieces[pieces.length - 1]) + length > width)
                            smb.append(SYSTEM_NEWLINE);
                    } catch (Exception e) {
                    }
                    smb.append(str[x] + " ");
                }
                return smb.toString().replaceFirst(SYSTEM_NEWLINE, "");
            }
        
            private static String removeLast(String s, String g) {
                if (s.contains(g)) {
                    int index = s.lastIndexOf(g);
                    int indexEnd = index + g.length();
                    if (index == 0)
                        return s.substring(1);
                    else if (index == s.length() - 1)
                        return s.substring(0, index);
                    else
                        return s.substring(0, index) + s.substring(indexEnd);
                }
                return s;
            }
        
            private static String justifyOperation(String s, float width, Paint p) {
                float holder = (float) (COMPLEXITY * Math.random());
                while (s.contains(Float.toString(holder)))
                    holder = (float) (COMPLEXITY * Math.random());
                String holder_string = Float.toString(holder);
                float lessThan = width;
                int timeOut = 100;
                int current = 0;
                while (p.measureText(s) < lessThan && current < timeOut) {
                    s = s.replaceFirst(" ([^" + holder_string + "])", " "
                            + holder_string + "$1");
                    lessThan = p.measureText(holder_string) + lessThan
                            - p.measureText(" ");
                    current++;
                }
                String cleaned = s.replaceAll(holder_string, " ");
                return cleaned;
            }
        
            private static String justify(String s, float width, Paint p) {
                while (p.measureText(s) < width) {
                    s = justifyOperation(s, width, p);
                }
                return s;
            }
        }
        
        public class TextViewEx extends TextView {
            private Paint paint = new Paint();
        
            private String[] blocks;
            private float spaceOffset = 0;
            private float horizontalOffset = 0;
            private float verticalOffset = 0;
            private float horizontalFontOffset = 0;
            private float dirtyRegionWidth = 0;
            private boolean wrapEnabled = false;
            int left, top, right, bottom = 0;
            private Align _align = Align.LEFT;
            private float strecthOffset;
            private float wrappedEdgeSpace;
            private String block;
            private String wrappedLine;
            private String[] lineAsWords;
            private Object[] wrappedObj;
        
            private Bitmap cache = null;
            private boolean cacheEnabled = false;
        
            public TextViewEx(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);
                // set a minimum of left and right padding so that the texts are not too
                // close to the side screen
                // this.setPadding(10, 0, 10, 0);
            }
        
            public TextViewEx(Context context, AttributeSet attrs) {
                super(context, attrs);
                // this.setPadding(10, 0, 10, 0);
            }
        
            public TextViewEx(Context context) {
                super(context);
                // this.setPadding(10, 0, 10, 0);
            }
        
            @Override
            public void setPadding(int left, int top, int right, int bottom) {
                // TODO Auto-generated method stub
                super.setPadding(left + 10, top, right + 10, bottom);
            }
        
            @Override
            public void setDrawingCacheEnabled(boolean cacheEnabled) {
                this.cacheEnabled = cacheEnabled;
            }
        
            public void setText(String st, boolean wrap) {
                wrapEnabled = wrap;
                super.setText(st);
            }
        
            public void setTextAlign(Align align) {
                _align = align;
            }
        
            @SuppressLint("NewApi")
            @Override
            protected void onDraw(Canvas canvas) {
                // If wrap is disabled then,
                // request original onDraw
                if (!wrapEnabled) {
                    super.onDraw(canvas);
                    return;
                }
        
                // Active canas needs to be set
                // based on cacheEnabled
                Canvas activeCanvas = null;
        
                // Set the active canvas based on
                // whether cache is enabled
                if (cacheEnabled) {
        
                    if (cache != null) {
                        // Draw to the OS provided canvas
                        // if the cache is not empty
                        canvas.drawBitmap(cache, 0, 0, paint);
                        return;
                    } else {
                        // Create a bitmap and set the activeCanvas
                        // to the one derived from the bitmap
                        cache = Bitmap.createBitmap(getWidth(), getHeight(),
                                Config.ARGB_4444);
                        activeCanvas = new Canvas(cache);
                    }
                } else {
                    // Active canvas is the OS
                    // provided canvas
                    activeCanvas = canvas;
                }
        
                // Pull widget properties
                paint.setColor(getCurrentTextColor());
                paint.setTypeface(getTypeface());
                paint.setTextSize(getTextSize());
                paint.setTextAlign(_align);
                paint.setFlags(Paint.ANTI_ALIAS_FLAG);
        
                // minus out the paddings pixel
                dirtyRegionWidth = getWidth() - getPaddingLeft() - getPaddingRight();
                int maxLines = Integer.MAX_VALUE;
                int currentapiVersion = android.os.Build.VERSION.SDK_INT;
                if (currentapiVersion >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                    maxLines = getMaxLines();
                }
                int lines = 1;
                blocks = getText().toString().split("((?<=\n)|(?=\n))");
                verticalOffset = horizontalFontOffset = getLineHeight() - 0.5f; // Temp
                                                                                // fix
                spaceOffset = paint.measureText(" ");
        
                for (int i = 0; i < blocks.length && lines <= maxLines; i++) {
                    block = blocks[i];
                    horizontalOffset = 0;
        
                    if (block.length() == 0) {
                        continue;
                    } else if (block.equals("\n")) {
                        verticalOffset += horizontalFontOffset;
                        continue;
                    }
        
                    block = block.trim();
        
                    if (block.length() == 0) {
                        continue;
                    }
        
                    wrappedObj = TextJustifyUtils.createWrappedLine(block, paint,
                            spaceOffset, dirtyRegionWidth);
        
                    wrappedLine = ((String) wrappedObj[0]);
                    wrappedEdgeSpace = (Float) wrappedObj[1];
                    lineAsWords = wrappedLine.split(" ");
                    strecthOffset = wrappedEdgeSpace != Float.MIN_VALUE ? wrappedEdgeSpace
                            / (lineAsWords.length - 1)
                            : 0;
        
                    for (int j = 0; j < lineAsWords.length; j++) {
                        String word = lineAsWords[j];
                        if (lines == maxLines && j == lineAsWords.length - 1) {
                            activeCanvas.drawText("...", horizontalOffset,
                                    verticalOffset, paint);
        
                        } else if (j == 0) {
                            // if it is the first word of the line, text will be drawn
                            // starting from right edge of textview
                            if (_align == Align.RIGHT) {
                                activeCanvas.drawText(word, getWidth()
                                        - (getPaddingRight()), verticalOffset, paint);
                                // add in the paddings to the horizontalOffset
                                horizontalOffset += getWidth() - (getPaddingRight());
                            } else {
                                activeCanvas.drawText(word, getPaddingLeft(),
                                        verticalOffset, paint);
                                horizontalOffset += getPaddingLeft();
                            }
        
                        } else {
                            activeCanvas.drawText(word, horizontalOffset,
                                    verticalOffset, paint);
                        }
                        if (_align == Align.RIGHT)
                            horizontalOffset -= paint.measureText(word) + spaceOffset
                                    + strecthOffset;
                        else
                            horizontalOffset += paint.measureText(word) + spaceOffset
                                    + strecthOffset;
                    }
        
                    lines++;
        
                    if (blocks[i].length() > 0) {
                        blocks[i] = blocks[i].substring(wrappedLine.length());
                        verticalOffset += blocks[i].length() > 0 ? horizontalFontOffset
                                : 0;
                        i--;
                    }
                }
        
                if (cacheEnabled) {
                    // Draw the cache onto the OS provided
                    // canvas.
                    canvas.drawBitmap(cache, 0, 0, paint);
                }
            }
        }
        
        <TextView
                        android:id="@+id/original"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/lorum_ipsum" />
        
        <yourpackagename.TextViewEx
                        android:id="@+id/changed"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/lorum_ipsum" />
        
        TextViewEx changed = (TextViewEx) findViewById(R.id.changed);
        changed.setText(getResources().getString(R.string.lorum_ipsum),true);
        
        <TextView 
        android:justificationMode="inter_word"
        />
        
         <TextView
            android:justificationMode="inter_word"
        />
        
         <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="92dp"
            android:text="@string/contents"
            android:layout_margin="20dp"
            android:justificationMode="inter_word"
             />
        
                <TextView
                .......................................
                .......................................
                .......................................
                android:layout_gravity="center_vertical|end"
                android:justificationMode="inter_word"
                .......................................
                .......................................
                />
        
           android:justificationMode="inter_word"
        
        <com.google.android.material.textview.MaterialTextView
                    ...
                    android:justificationMode="inter_word"
                    tools:targetApi="o" />