14

I can use Spannable in TextViews to create spans with different looks, underlines, strikethroughs and such. How can I do the same to alter line wrapping behavior? In particular, I don't want an email address to wrap in the middle, I want it to act like one word.

I tried WrapTogetherSpan, but I couldn't get it to work. It looks like it is only used by DynamicLayout, and I could not force the TextView to use DynamicLayout.

<TextView
  android:id="@+id/merchant_email_field"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:textSize="@dimen/account_setting_email"
  android:gravity="center"
  android:bufferType="spannable"
  android:maxLines="2"
  android:ellipsize="end"
  />

How I'm setting the spannable:

WrapTogetherSpan TOGETHER_SPAN = new WrapTogetherSpan() {};
String collectedString = getString(R.string.email_sentence, userEmail);
int emailOffset = collectedString.indexOf(userEmail);
Spannable emailSpannable = Spannable.Factory.getInstance()
    .newSpannable(collectedString);
emailSpannable.setSpan(TOGETHER_SPAN, emailOffset,
    emailOffset + userEmail.length(),
    Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
textView.setText(emailSpannable)
pforhan
  • 807
  • 8
  • 12

3 Answers3

7

Don't know if you have found an answer to it but you can use unicode to help you out.

there is a non-break space character, so you will need to replace all the spaces you want to be unbreakable with this character (\u00A0)

for an example

String text = "Hello World";
text.replace(' ', '\u00A0');
textView.setText(text);

by the way I've looked for a span solution and couldn't find one, WrapTogetherSpan is just an interface so it wouldn't work...

but with this method I'm sure you could make a custom unbreakable span if you want.

ndori
  • 1,934
  • 1
  • 18
  • 23
  • 1
    Well, this works for spaces. But in the case of an email address as mentioned in the question, it doesn't help. I *might* be able to stick invisible characters like U+FEFF or U+2060 in there, but that's just annoying, since it would have to be between every charactetr. – pforhan Aug 22 '14 at 15:14
3

If you are implementing a more low-level solution (ie, drawing your own text and handling line-wrapping yourself), then see BreakIterator. The BreakIterator.getLineInstance() factory method treats email addresses as a single unit.

String text = "My email is me@example.com.";
BreakIterator boundary = BreakIterator.getLineInstance();
boundary.setText(text);
int start = boundary.first();
for (int end = boundary.next(); end != BreakIterator.DONE; end = boundary.next()) {
    System.out.println(start + " " + text.substring(start, end));
    start = end;
}

The output shows the boundary start indexes where line breaks would be acceptable.

0 My 
3 email 
9 is 
12 me@example.com.

See also

Community
  • 1
  • 1
Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
-1

Have you tried adding android:singleLine="true" to your XML?

Barak
  • 16,318
  • 9
  • 52
  • 84
  • 1
    No, because I want up to two lines. I just want the email address to wrap together as one word. – pforhan May 15 '12 at 15:56
  • Apologies, I didn't understand that before. Makes a lot more sense now why you were trying to do it with a spannable. :) – Barak May 15 '12 at 16:15