mmaitlen
mmaitlen

Reputation: 822

Zero-width line breaking space for Android

Does anyone know if \u200b should be working on Android as a zero width space that functions as a line break if the TextView length is exceeded by the text of the TextView? It appears that only \u0020 is line breaking for me, but I'm not able to figure out how to have a zero width version of it. \u200b is what I expect should work, per the following link, but it only does the zero-width space and doesn't break...and as stated, only \u0020 is line breaking.

http://www.cs.tut.fi/~jkorpela/chars/spaces.html

I've attached the view of an Activity I'm using for testing where U+ is being used in place of \u.

I've also tried using the fromHtml option to see if there is an Html option that works but haven't had any luck with arial.

Here's the test code I'm using

public class TextSpaceActivity extends Activity {

public static void start( Context ctx ) {
    ctx.startActivity(  new Intent( ctx, TextSpaceActivity.class )  );
}

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate( savedInstanceState );
    setContentView( R.layout.text_space_activity );
    setTitle( "TextSpaceActivity" );

    setText( R.id.tsa_txvw_1, "abc\u0020123\u0020xyz\u0020987" );
    setText( R.id.tsa_txvw_2, "abc\u200a123\u200axyz\u200a987" );
    setText( R.id.tsa_txvw_3, "abc\u200b123\u200bxyz\u200b987" );
}

TextView txvw;
private void setText( int txvwResId, String txt ) {
    txvw = (TextView)findViewById( txvwResId );
    txvw.setText( txt );
}
}

enter image description here

Upvotes: 19

Views: 6999

Answers (5)

zerobandwidth
zerobandwidth

Reputation: 1303

Related: I just tested use of the zero-width space character entity ​ as part of an app title, and it is handled as expected when the app's icon is rendered on the desktop by the Android OS.

    <string name="app_name">
        App&#8203;Name&#8203;With&#8203;Many&#8203;Words
    </string>

I tried this on Android 5.0; unknown whether it will work in older versions, however.

Upvotes: 1

rds
rds

Reputation: 27004

Since Lollipop, \u200b is supported.

This is implemented in StaticLayout with a native call on nLineBreakOpportunities.

Upvotes: 6

Terence Bandoian
Terence Bandoian

Reputation: 107

If you only want to control the presentation in a browser, you might try a zero-width inline class in CSS:

.zw { display: inline-block; width: 0; }

Then, in the HTML:

abc<span class="zw"> </span>123

Upvotes: -2

Dan Hulme
Dan Hulme

Reputation: 15290

I don't believe the line-breaking algorithm understands the zero-width line-break, or soft hyphens, or the line- or paragraph-separator characters for that matter. Here's the code from the Android source that decides if there can be a line break here (android.text.StaticLayout, lines 358-366 in the source):

// From the Unicode Line Breaking Algorithm (at least approximately)
boolean isLineBreak = isSpaceOrTab ||
        // / is class SY and - is class HY, except when followed by a digit
        ((c == CHAR_SLASH || c == CHAR_HYPHEN) &&
        (j + 1 >= spanEnd || !Character.isDigit(chs[j + 1 - paraStart]))) ||
        // Ideographs are class ID: breakpoints when adjacent, except for NS
        // (non-starters), which can be broken after but not before
        (c >= CHAR_FIRST_CJK && isIdeographic(c, true) &&
        j + 1 < spanEnd && isIdeographic(chs[j + 1 - paraStart], false));

where isSpaceOrTab is defined just above (line 343) as:

boolean isSpaceOrTab = c == CHAR_SPACE || c == CHAR_TAB;

All the CHAR_ constants are plain character constants, so there's nothing like isspace going on. Lines 952-958 in the same file:

private static final char CHAR_FIRST_CJK = '\u2E80';

private static final char CHAR_NEW_LINE = '\n';
private static final char CHAR_TAB = '\t';
private static final char CHAR_SPACE = ' ';
private static final char CHAR_SLASH = '/';
private static final char CHAR_HYPHEN = '-';

Looking at your other comments, I see you're trying to break Chinese correctly. You might not have to do anything special: as the isIdeographic call above hints, it tries to break between two ideographs without inserting spaces. Only the StaticLayout breaker does this: DynamicLayout only uses newline characters, so it will only break correctly on static text.

I'm afraid from my research it looks like you're screwed. My only suggestion for a work-around would be to use a WebView instead of a TextView, and use the superior line-breaking capabilities of the system's web browser instead of the limited implementation TextView offers.

Upvotes: 14

Tudor Luca
Tudor Luca

Reputation: 6419

In your strings.xml:

<string name="sample_string"><![CDATA[abc123<br />xyz987]]></string>

In your Activity:

TextView textView = (TextView) findViewById(R.id.myText);
textView.setText(Html.fromHtml(getResources().getString(R.string.sample_string)));

Hope it helps!

Upvotes: -2

Related Questions