Code that you have been searching for for a long time on the Internet has been found. After testing, it can be used. Write it down first for later use.Diagram of the effect of the previous experiment

There are two textview s on the diagram. See below for the differences.
The following is the original copy:
1. Where are the problems?
textview will automatically wrap when long text is displayed. In some special cases, the automatic wrap will look like this:
These special cases include:
1) Full-angle/half-angle symbols (typically numbers, letters, Chinese characters)
2) When a full/half punctuation symbol appears at the beginning of a line, it jumps to the next line along with the previous character
3) English words cannot be broken into two lines
4)......
2. What to do?
There are usually two types of solutions:
1) Modify the text content, make all symbols full-angled, add spaces before punctuation symbols, and so on...
2) Keep the contents of the text unchanged and manually divide the text into multiple lines where appropriate
This paper uses the second scheme, which is more general and preserves the original text to the maximum extent.
3. Start working
3.1 "Manually dividing text into multiple lines where appropriate" requires information such as the actual width and font size of the textview, as follows:
-
public class TestCActivity extends Activity {
-
private TextView mText;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
setContentView(R.layout.testc);
-
-
mText = (TextView)findViewById(R.id.txt);
-
mText.setText("This article address http://Www.cnblogs.com/goagent/p/5159125.html This is the address of this article.Address.Ah http://www.cnblogs.com/goagent/p/5159125.html");
-
mText.getViewTreeObserver().addOnGlobalLayoutListener(new OnTvGlobalLayoutListener());
-
}
-
-
private class OnTvGlobalLayoutListener implements OnGlobalLayoutListener {
-
@Override
-
public void onGlobalLayout() {
-
mText.getViewTreeObserver().removeOnGlobalLayoutListener(this);
-
final String newText = autoSplitText(mText);
-
if (!TextUtils.isEmpty(newText)) {
-
mText.setText(newText);
-
}
-
}
-
}
-
-
private String autoSplitText(final TextView tv) {
-
final String rawText = tv.getText().toString();
-
final Paint tvPaint = tv.getPaint();
-
final int tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight();
-
-
-
String newText = rawText;
-
-
-
return newText;
-
}
-
}
3.2 To automatically split text, simply measure it character by character with paint of textview. If you find that the current line cannot be drawn anymore, add a line break manually:
-
private String autoSplitText(final TextView tv) {
-
final String rawText = tv.getText().toString();
-
final Paint tvPaint = tv.getPaint();
-
final float tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight();
-
-
-
String [] rawTextLines = rawText.replaceAll("\r", "").split("\n");
-
StringBuilder sbNewText = new StringBuilder();
-
for (String rawTextLine : rawTextLines) {
-
if (tvPaint.measureText(rawTextLine) <= tvWidth) {
-
-
sbNewText.append(rawTextLine);
-
} else {
-
-
float lineWidth = 0;
-
for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) {
-
char ch = rawTextLine.charAt(cnt);
-
lineWidth += tvPaint.measureText(String.valueOf(ch));
-
if (lineWidth <= tvWidth) {
-
sbNewText.append(ch);
-
} else {
-
sbNewText.append("\n");
-
lineWidth = 0;
-
--cnt;
-
}
-
}
-
}
-
sbNewText.append("\n");
-
}
-
-
-
if (!rawText.endsWith("\n")) {
-
sbNewText.deleteCharAt(sbNewText.length() - 1);
-
}
-
-
return sbNewText.toString();
-
}
3.3. Say nothing but the following:

4. More Plays
4.1. You can encapsulate a custom textview that directly includes the ability to automatically type and wrap lines:
-
package cc.snser.test;
-
-
import android.content.Context;
-
import android.graphics.Paint;
-
import android.text.TextUtils;
-
import android.util.AttributeSet;
-
import android.widget.TextView;
-
-
public class AutoSplitTextView extends TextView {
-
private boolean mEnabled = true;
-
-
public AutoSplitTextView(Context context) {
-
super(context);
-
}
-
-
public AutoSplitTextView(Context context, AttributeSet attrs) {
-
super(context, attrs);
-
}
-
-
public AutoSplitTextView(Context context, AttributeSet attrs, int defStyle) {
-
super(context, attrs, defStyle);
-
}
-
-
public void setAutoSplitEnabled(boolean enabled) {
-
mEnabled = enabled;
-
}
-
-
@Override
-
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-
if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
-
&& MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY
-
&& getWidth() > 0
-
&& getHeight() > 0
-
&& mEnabled) {
-
String newText = autoSplitText(this);
-
if (!TextUtils.isEmpty(newText)) {
-
setText(newText);
-
}
-
}
-
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
}
-
-
private String autoSplitText(final TextView tv) {
-
final String rawText = tv.getText().toString();
-
final Paint tvPaint = tv.getPaint();
-
final float tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight();
-
-
-
String [] rawTextLines = rawText.replaceAll("\r", "").split("\n");
-
StringBuilder sbNewText = new StringBuilder();
-
for (String rawTextLine : rawTextLines) {
-
if (tvPaint.measureText(rawTextLine) <= tvWidth) {
-
-
sbNewText.append(rawTextLine);
-
} else {
-
-
float lineWidth = 0;
-
for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) {
-
char ch = rawTextLine.charAt(cnt);
-
lineWidth += tvPaint.measureText(String.valueOf(ch));
-
if (lineWidth <= tvWidth) {
-
sbNewText.append(ch);
-
} else {
-
sbNewText.append("\n");
-
lineWidth = 0;
-
--cnt;
-
}
-
}
-
}
-
sbNewText.append("\n");
-
}
-
-
-
if (!rawText.endsWith("\n")) {
-
sbNewText.deleteCharAt(sbNewText.length() - 1);
-
}
-
-
return sbNewText.toString();
-
}
-
}
-
-
View AutoSplitTextView.java
TestActivity code:
-
package cc.snser.test;
-
-
import android.app.Activity;
-
import android.os.Bundle;
-
-
public class TestCActivity extends Activity {
-
private AutoSplitTextView mText;
-
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
-
setContentView(R.layout.testc);
-
-
mText = (AutoSplitTextView)findViewById(R.id.txt);
-
mText.setText("This article address http://Www.cnblogs.com/goagent/p/5159125.html This is the address of this article.Address.Ah http://www.cnblogs.com/goagent/p/5159125.html;)
-
}
-
}
xml code:
-
<LinearLayout 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"
-
android:background="@android:color/white"
-
android:orientation="vertical" >
-
-
<cc.snser.test.AutoSplitTextView
-
android:id="@+id/txt"
-
android:layout_width="match_parent"
-
android:layout_height="200dp"
-
android:layout_marginTop="11dp"
-
android:layout_marginLeft="11dp"
-
android:layout_marginRight="11dp"
-
android:background="@android:color/holo_blue_light"
-
android:textSize="20sp"
-
android:textColor="@android:color/black" />
-
-
</LinearLayout>
4.2. Hanging indentation
-
private String autoSplitText(final TextView tv, final String indent) {
-
final String rawText = tv.getText().toString(); //Original Text
-
final Paint tvPaint = tv.getPaint(); //paint, containing information such as fonts
-
final float tvWidth = tv.getWidth() - tv.getPaddingLeft() - tv.getPaddingRight(); //Control Available Width
-
-
//Process indentation into spaces
-
String indentSpace = "";
-
float indentWidth = 0;
-
if (!TextUtils.isEmpty(indent)) {
-
float rawIndentWidth = tvPaint.measureText(indent);
-
if (rawIndentWidth < tvWidth) {
-
while ((indentWidth = tvPaint.measureText(indentSpace)) < rawIndentWidth) {
-
indentSpace += " ";
-
}
-
}
-
}
-
-
//Split the original text by line
-
String [] rawTextLines = rawText.replaceAll("\r", "").split("\n");
-
StringBuilder sbNewText = new StringBuilder();
-
for (String rawTextLine : rawTextLines) {
-
if (tvPaint.measureText(rawTextLine) <= tvWidth) {
-
//If the full line width is within the available width of the control, it is not handled.
-
sbNewText.append(rawTextLine);
-
} else {
-
//If the full line width exceeds the available width of the control, it is measured by character and wrapped manually at the first character that exceeds the available width.
-
float lineWidth = 0;
-
for (int cnt = 0; cnt != rawTextLine.length(); ++cnt) {
-
char ch = rawTextLine.charAt(cnt);
-
//Start with the second line of the manual line break with hanging indentation
-
if (lineWidth < 0.1f && cnt != 0) {
-
sbNewText.append(indentSpace);
-
lineWidth += indentWidth;
-
}
-
lineWidth += tvPaint.measureText(String.valueOf(ch));
-
if (lineWidth <= tvWidth) {
-
sbNewText.append(ch);
-
} else {
-
sbNewText.append("\n");
-
lineWidth = 0;
-
--cnt;
-
}
-
}
-
}
-
sbNewText.append("\n");
-
}
-
-
//Remove \n from the end
-
if (!rawText.endsWith("\n")) {
-
sbNewText.deleteCharAt(sbNewText.length() - 1);
-
}
-
-
return sbNewText.toString();
-
}
Call method:
autoSplitText(tv,
"1,");
Hanging indentation effect:

Note: You need to use AutoSplitTextView in the xml of the layout instead of the native TextView, otherwise it will be the same as the effect image at the beginning of the article.