My use case was converting a TextView's contents, including color and style, to/from a hex string. Building off Dan's answer, I came up with the following code. Hopefully if someone has a similar use case, it'll save you some headache.
Store textBox's contents to string:
String actualText = textBox.getText().toString();
SpannableString spanStr = new SpannableString(textBox.getText());
ForegroundColorSpan[] fSpans = spanStr.getSpans(0,spanStr.length(),ForegroundColorSpan.class);
StyleSpan[] sSpans = spanStr.getSpans(0,spanStr.length(),StyleSpan.class);
int nSpans = fSpans.length;
String spanInfo = "";
String headerInfo = String.format("%08X",nSpans);
for (int i = 0; i < nSpans; i++) {
spanInfo += String.format("%08X",fSpans[i].getForegroundColor());
spanInfo += String.format("%08X",spanStr.getSpanStart(fSpans[i]));
spanInfo += String.format("%08X",spanStr.getSpanEnd(fSpans[i]));
}
nSpans = sSpans.length;
headerInfo += String.format("%08X",nSpans);
for (int i = 0; i < nSpans; i++) {
spanInfo += String.format("%08X",sSpans[i].getStyle());
spanInfo += String.format("%08X",spanStr.getSpanStart(sSpans[i]));
spanInfo += String.format("%08X",spanStr.getSpanEnd(sSpans[i]));
}
headerInfo += spanInfo;
headerInfo += actualText;
return headerInfo;
Retrieve textBox's contents from string:
String header = tvString.substring(0,8);
int fSpans = Integer.parseInt(header,16);
header = tvString.substring(8,16);
int sSpans = Integer.parseInt(header,16);
int nSpans = fSpans + sSpans;
SpannableString tvText = new SpannableString(tvString.substring(nSpans*24+16));
tvString = tvString.substring(16,nSpans*24+16);
int cc, ss, ee;
int begin;
for (int i = 0; i < fSpans; i++) {
begin = i*24;
cc = (int) Long.parseLong(tvString.substring(begin,begin+8),16);
ss = (int) Long.parseLong(tvString.substring(begin+8,begin+16),16);
ee = (int) Long.parseLong(tvString.substring(begin+16,begin+24),16);
tvText.setSpan(new ForegroundColorSpan(cc), ss, ee, 0);
}
for (int i = 0; i < sSpans; i++) {
begin = i*24+fSpans*24;
cc = (int) Long.parseLong(tvString.substring(begin,begin+8),16);
ss = (int) Long.parseLong(tvString.substring(begin+8,begin+16),16);
ee = (int) Long.parseLong(tvString.substring(begin+16,begin+24),16);
tvText.setSpan(new StyleSpan(cc), ss, ee, 0);
}
textBox.setText(tvText);
The reason for the (int) Long.parseLong in the retrieval code is because the style/color can be negative numbers. This trips up parseInt and results in an overflow error. But, doing parseLong and then casting to int gives the correct (positive or negative) integer.
` element which when restored adds two `\n` at the end. Trimming the result isn't simple because its a SpannableString.
– Iftah Oct 28 '14 at 08:37