studio android spannablestring spannable

android - studio - Combinar Spannable con String.format()



set bold textview android (2)

He creado una versión de String.format que funciona con spannables. Descárgalo y úsalo como la versión normal. En su caso, pondría los espacios alrededor de los especificadores de formato (posiblemente utilizando strings.xml). En la salida, estarían alrededor de lo que fuera reemplazado por esos especificadores.

Supongamos que tiene la siguiente cadena:

String s = "The cold hand reaches for the %1$s %2$s Ellesse''s"; String old = "old"; String tan = "tan"; String formatted = String.format(s,old,tan); //"The cold hand reaches for the old tan Ellesse''s"

Supongamos que desea terminar con esta cadena, pero también debe tener un Span determinado para cualquier palabra reemplazada por String.format .

Por ejemplo, también queremos hacer lo siguiente:

Spannable spannable = new SpannableString(formatted); spannable.setSpan(new StrikethroughSpan(), oldStart, oldStart+old.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); spannable.setSpan(new ForegroundColorSpan(Color.BLUE), tanStart, tanStart+tan.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

¿Existe una forma robusta de conocer los índices de inicio de old y tan ?

Tenga en cuenta que solo buscar ''old'' devuelve ''old'' en ''cold'', así que no funcionará.

Lo que funcionará, supongo, es buscar %[0-9]$s antemano y calcular las compensaciones para tener en cuenta los reemplazos en String.format . Sin embargo, esto parece un dolor de cabeza, sospecho que podría haber un método como String.format que sea más informativo sobre los detalles de su formato. Bueno, ¿hay?


Usar Spannables de esa manera es un dolor de cabeza; esta es probablemente la forma más sencilla de evitarlo:

String s = "The cold hand reaches for the %1$s %2$s Ellesse''s"; String old = "<font color=/"blue/">old</font>"; String tan = "<strike>tan</strike>"; String formatted = String.format(s,old,tan); //The cold hand reaches for the <font color="blue">old</font> <strike>tan</strike> Ellesse''s Spannable spannable = Html.fromHtml(formatted);

Problema: esto no se pone en un StrikethroughSpan . Para hacer el StrikethroughSpan , tomamos prestado un TagHandler personalizado de esta pregunta .

Spannable spannable = Html.fromHtml(text,null,new MyHtmlTagHandler());

MyTagHandler:

public class MyHtmlTagHandler implements Html.TagHandler { public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { if (tag.equalsIgnoreCase("strike") || tag.equals("s")) { processStrike(opening, output); } } private void processStrike(boolean opening, Editable output) { int len = output.length(); if (opening) { output.setSpan(new StrikethroughSpan(), len, len, Spannable.SPAN_MARK_MARK); } else { Object obj = getLast(output, StrikethroughSpan.class); int where = output.getSpanStart(obj); output.removeSpan(obj); if (where != len) { output.setSpan(new StrikethroughSpan(), where, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } } } private Object getLast(Editable text, Class kind) { Object[] objs = text.getSpans(0, text.length(), kind); if (objs.length == 0) { return null; } else { for (int i = objs.length; i > 0; i--) { if (text.getSpanFlags(objs[i - 1]) == Spannable.SPAN_MARK_MARK) { return objs[i - 1]; } } return null; } } }