Stop text from multiple lines in periods in web addresses

I have an Android TextView displaying some text and it is multi-line. However, in the text I sometimes have domain names; How can I stop a TextView from dividing lines into periods in them?

Is there a un-break-unicode period, for example?


To see the problem in action when packing an email address, run android create project --target 16 --path demo --package com.example.demo --activity MainActivity
and change the text in res/layout/main.xml to " Hello World, MyActivity filler text + email foo@foo.com ". This produces this output on the Galaxy S3 (API level 16):

Email wrapping

(Correct the text, if necessary, look at the wrapper on devices with different screen sizes. It is noteworthy that the wrapper performs correctly in the preview of the Intellij layout, but only on the device that it is faulty.)

+7
android textview unicode android-textview textwrapping
source share
4 answers

TL; DR;

@Matt McMinn has already demonstrated a solution to this problem here , understand it. I will only repeat this decision here.


Please note that this problem has already been fixed at the platform level in Android 4.2.2. See the screenshots below for a comparison of words for the same code base, but different versions of the platform on the Galaxy Nexus.

Word wrap comparison on Android 4.1.2 vs Android 4.2.2

Therefore, if you are not targeting older versions of Android, you may not use this fix at all.

The code

MainActivity.java

 package com.example.nobr; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.widget.TextView.BufferType; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView helloWorld = (TextView) findViewById(R.id.hello_world); helloWorld.setText(R.string.hello_world, BufferType.EDITABLE); TextView longText = (TextView) findViewById(R.id.long_text); longText.setText(R.string.long_text_with_url, BufferType.EDITABLE); } } 

activity_main.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" > <com.example.nobr.NonBreakingPeriodTextView android:id="@+id/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <com.example.nobr.NonBreakingPeriodTextView android:id="@+id/long_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/hello_world" android:layout_below="@+id/hello_world" android:layout_marginTop="20dp" /> </RelativeLayout> 

NonBreakingPeriodTextView.java

 package com.example.nobr; import android.content.Context; import android.graphics.Paint; import android.text.Editable; import android.util.AttributeSet; import android.util.Log; import android.widget.TextView; public class NonBreakingPeriodTextView extends TextView { private static final String TAG = "NonBreakingPeriodTextView"; public NonBreakingPeriodTextView(Context context) { super(context); } public NonBreakingPeriodTextView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { Editable editable = getEditableText(); if (editable == null) { Log.d(TAG, "non-editable text"); return; } int width = getWidth() - getPaddingLeft() - getPaddingRight(); if (width == 0) { Log.d(TAG, "zero-length text"); return; } Paint p = getPaint(); float[] widths = new float[editable.length()]; p.getTextWidths(editable.toString(), widths); float curWidth = 0.0f; int lastWSPos = -1; int strPos = 0; final char newLine = '\n'; final String newLineStr = "\n"; boolean reset = false; int insertCount = 0; /* * Traverse the string from the start position, adding each character width to the total * until: 1) A whitespace character is found. In this case, mark the whitespace position. If * the width goes over the max, this is where the newline will be inserted. 2) A newline * character is found. This resets the curWidth counter. curWidth > width. Replace the * whitespace with a newline and reset the counter. */ while (strPos < editable.length()) { curWidth += widths[strPos]; char curChar = editable.charAt(strPos); if (curChar == newLine) { reset = true; } else if (Character.isWhitespace(curChar)) { lastWSPos = strPos; } else if (curWidth > width && lastWSPos >= 0) { editable.replace(lastWSPos, lastWSPos + 1, newLineStr); insertCount++; strPos = lastWSPos; lastWSPos = -1; reset = true; } if (reset) { curWidth = 0.0f; reset = false; } strPos++; } if (insertCount != 0) { setText(editable); } } } 

Result

On Android 4.1.2 (Galaxy Nexus)

Word wrap on Android 4.1.2 with the fix

On Android 2.3.3 (AVD, Nexus One clone)

enter image description here

Hope this helps.

+6
source share

To say that android for analyzing domain links in TextView uses this code in the TextView code block:

 android:autoLink="web" 

This will show the domain names as links in the application and will not split the lines.

0
source share

Use this:

android: singleLine = "true" in xml

0
source share

@ozbek's solution didn't work for me, respectively @Matt McMinn, I had to change the line

 else if(Character.isWhitespace(curChar)) 

for

 } else if (curChar == '\u00A0') { 

but otherwise a great solution, thanks

0
source share

All Articles