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获取单词的长度,并在自定义视图的画布上手动布局
- 我认为有两种选择:
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" />