Explicar el significado de banderas Span como SPAN_EXCLUSIVE_EXCLUSIVE

¿Alguien puede explicar claramente con ejemplos qué significan cada uno de los indicadores de span como SPAN_EXCLUSIVE_EXCLUSIVE y SPAN_MARK_MARK y cuándo usar qué flags?

No entiendo la documentación oficial cuando dice:

Los espacios del tipo SPAN_EXCLUSIVE_EXCLUSIVE no se expanden para incluir texto insertado en su punto inicial o final.

¿”Expandir para incluir” se refiere a las ediciones realizadas después de insertar los tramos?

¿Significa que estas banderas NO afectan a Spannables con texto inmutable?

¿”Expandir para incluir” se refiere a las ediciones realizadas después de insertar los tramos?

Sí. Por ejemplo, supongamos que tenemos lo siguiente:

El zorro rápido saltó.

Si usamos SPAN_EXCLUSIVE_EXCLUSIVE en el espacio en negrita, e insertamos el texto en el medio del tramo, todavía está en negrita:

El rápido zorro marrón saltó.

Sin embargo, si insertamos texto al principio o al final del tramo en negrita, el texto insertado no está en negrita:

El zorro realmente rápido saltó.

Sin embargo, si hubiéramos usado SPAN_INCLUSIVE_EXCLUSIVE , la inserción de texto al principio se incluiría como parte del intervalo, y tendríamos que:

El zorro realmente rápido saltó.

¿Significa que estas banderas NO afectan a Spannables con texto inmutable?

Diría que tienen un uso limitado para el texto inmutable. En su mayoría, estos se usarán con SpannableStringBuilder o cosas que usen uno debajo de las cubiertas (por ejemplo, EditText ).

Lo que las banderas no significan

Cuando vi por primera vez las partes INCLUSIVE y EXCLUSIVE de las banderas de Spannable , pensé que simplemente me dijeron si el lapso incluía las posiciones de inicio y final del tramo. Esto no es verdad. Permítanme ilustrarlo con el siguiente ejemplo.

 String myString = "01234"; int start = 1; int end = 3; int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing SpannableString spannableString = new SpannableString(myString); ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED); spannableString.setSpan(foregroundSpan, start, end, spanFlag); textView.setText(spannableString); 

Aquí están los resultados:

SPAN_INCLUSIVE_INCLUSIVE

enter image description here

SPAN_INCLUSIVE_EXCLUSIVE

enter image description here

SPAN_EXCLUSIVE_INCLUSIVE

enter image description here

SPAN_EXCLUSIVE_EXCLUSIVE

enter image description here

¡Son todos iguales! Las banderas no afectan el lapso. Un lapso siempre incluye el carácter en su índice de inicio y excluye el carácter en el índice final.

Qué significan las banderas

Las partes INCLUSIVE y EXCLUSIVE de las banderas de Spannable indican si el span debe incluir o no texto insertado en las posiciones inicial o final .

Aquí hay un ejemplo modificado para ilustrar eso.

 String myString = "01234"; int start = 1; int end = 3; int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; // this is what is changing // set the span SpannableStringBuilder spannableString = new SpannableStringBuilder(myString); ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED); spannableString.setSpan(foregroundSpan, start, end, spanFlag); // insert the text after the span has already been set // (inserting at start index second so that end index doesn't get messed up) spannableString.insert(end, "x"); spannableString.insert(start, "x"); textView.setText(spannableString); 

Estos son los resultados después de insertar una x al final e iniciar índices:

SPAN_INCLUSIVE_INCLUSIVE

enter image description here

SPAN_INCLUSIVE_EXCLUSIVE

enter image description here

SPAN_EXCLUSIVE_INCLUSIVE

enter image description here

SPAN_EXCLUSIVE_EXCLUSIVE

enter image description here

Notas

  • La mayoría de esta respuesta describe cosas que el OP ya sabía. Solo lo estoy agregando para futuros visitantes como yo que no sabían estas cosas.
  • En el segundo ejemplo, tuve que usar un SpannableStringBuilder porque el texto en un SpannableString es inmutable por lo que no puede insertar texto en él. Por lo tanto, los indicadores generalmente no tienen sentido para SpannableString . Sin embargo, uno podría imaginar una situación en la que los tramos de SpannableString se copien a SpannableStringBuilder o Editable , y desde allí las banderas tendrían significado.
  • Consulte esta respuesta para conocer la diferencia entre SpannableString , SpannableStringBuilder , Editable y más.

Los valores String que mantenemos como recurso dentro de un archivo xml en el directorio res / values ​​se pueden diseñar con los métodos definidos en la interfaz android.text.Spannable, los campos definidos en la interfaz android.text.Spanned (Spannable es una subinterfaz de Spanned), con la clase android.text.SpannableStringBuilder (SpannableStringBuilder es una subclase de Spannable) y con las clases definidas en el paquete android.text.style especialmente android.text.style.ForegroundColorSpan y android.text.style.StyleSpan clases Como SpannableStringBuilder es una subclase de Spannable y Spannable es una subinterfaz de Spanned. Todos los campos de la interfaz Spanned y una implementación completa de los métodos de la interfaz Spannable existen en la clase SpannableStringBuilder.

1. Ahora, para darle un estilo a un recurso de texto, debemos obtenerlo primero con su id de recurso con el método getString (int resource_id) de un objeto Resources, para obtener un objeto Resources asociado con una subclase de contexto que llamamos método getResources (). ejemplo-

String title = getResources (). GetString (R.string.string_title);

2. Ahora tenemos que crear un objeto SpannableStringBuilder con su public no parameter constructor o cualquier otro constructor público.

3.SpannableStringBuilder funciona de una manera un poco compleja. Podemos agregar texto a SpannableStringBuilder con uno de los métodos de agregar. Algunas partes del texto que SpannableStringBuilder contiene se pueden marcar como distribuidas y solo esa parte se personaliza (con color, fuente, etc.) ), cuando se agrega un nuevo texto dentro de un objeto SpannableStringBuilder en cualquier índice, si el nuevo texto también se marcará como espaciado o no, eso se define por los campos de la interfaz extendida. Llamamos al método setSpan (Object what, int start, int end, int flags) declarado por la interfaz Spannable e implementado por la clase SpannableStringBuilder. Aquí lo que es un objeto de una clase del paquete android.text.style.StyleSpan, este objeto define el tipo de estilo que queremos aplicar, flags es uno de los campos definidos en la interfaz Spanned, este parámetro flags especifica cuándo un el nuevo texto se agrega dentro de este objeto SpannableStringBuilder en cualquier índice, si el nuevo texto también se marcará como extendido o no.

4. Las diferentes clases del paquete android.text.style.StyleSpan definen estilos diferentes, pero a partir de ahora solo conozco un uso de la clase android.text.style.StyleSpan y un uso de android.text.style.ForegroundColorSpan clase. Un constructor público de la clase StyleSpan toma un valor int que puede ser el valor de uno de los campos definidos en la clase android.graphics.Typeface (BOLD, BOLD_ITALIC, ITALIC, NORMAL). Como estos nombres de campo sugieren, van a dar estilo al texto como negrita o bold_italic o cursiva o normal. Por ejemplo-

StyleSpan style_span = new StyleSpan (Typeface.ITALIC);

Un constructor público de la clase ForegroundColorSpan toma un valor int que puede ser cualquier valor de color argb hexadecimal o puede ser el valor de uno de los campos definidos en la clase android.graphics.Color (BLACK, BLUE, CYAN, DKGRAY, GREY, GREEN , LTGRAY, MAGENTA, ROJO, TRANSPARENTE, BLANCO, AMARILLO). Como los nombres de estos campos sugieren que coloreen un texto. Para dar un valor de color hexadecimal argb como int al constructor comenzamos el valor hexadecimal con un 0X o 0x, java luego convierte automáticamente el valor hexadecimal en su equivalente int. Por ejemplo-

ForegroundColorSpan fore_ground_color_Span = new ForegroundColorSpan (Color.RED);

5. En el método setSpan (Object what, int start, int end, int flags), el inicio y el final definen el rango inicial del texto a marcar como spanned, start especifica el índice de los caracteres iniciales y el final especifica el índice del personaje, uno pasó el carácter final, por ejemplo, para una cadena “01234”

nuevo SpannableStringBuilder (“01234”). setSpan (foreground_color_span, 1, 3, span_flag);

causará que solo el 12 se marque como abarcado inicialmente, por lo que el carácter inicial es el ‘1’ según lo especificado por el índice inicial y el carácter final es el 2 especificado por el índice (end-1). Entonces, si damos el mismo valor para inicio y fin, entonces no habrá texto cubierto inicialmente y el rango será cero, para el ejemplo anterior si inicio y fin ambos son 1, entonces el carácter inicial es 1 pero el carácter final es 0. Esto no tiene sentido en este caso, no habrá texto marcado como abarcado inicialmente.

6. Ahora algunos campos de la interfaz extendida funcionan como se describe a continuación. Cuando se anexa un nuevo texto ………. el SPAN_EXCLUSIVE_EXCLUSIVE no marca ningún texto agregado antes del carácter inicial y después del carácter final tal como se extendió, sino que marca cualquier texto agregado después del carácter inicial o antes del carácter final como se distribuye, SPAN_EXCLUSIVE_EXCLUSIVE es el sinónimo de SPAN_POINT_MARK, si el rango es cero, significa que ningún texto está marcado como abarcado inicialmente, entonces cualquier texto agregado a cualquier índice no está marcado como abarcado con este indicador,

el SPAN_EXCLUSIVE_INCLUSIVE no marca ningún texto agregado antes del carácter inicial como extendido, sino que marca cualquier texto agregado después del carácter inicial o cualquier texto agregado antes o después del carácter final tal como se extendió, de acuerdo con mis pruebas SPAN_EXCLUSIVE_INCLUSIVE es el sinónimo de SPAN_POINT_POINT, si el el rango es cero, lo que significa que ningún texto se marca como abarcado inicialmente, luego cualquier texto agregado a cualquier índice no se marca como abarcado con esta bandera,

el SPAN_INCLUSIVE_EXCLUSIVE no marca ningún texto agregado antes del carácter final como extendido, sino que marca cualquier texto agregado después o antes del carácter inicial o cualquier texto astackdo después del carácter final como se extendió, de acuerdo con mis pruebas SPAN_INCLUSIVE_EXCLUSIVE es el sinónimo de SPAN_MARK_MARK, si el rango es cero, lo que significa que ningún texto se marca como abarcado inicialmente, luego cualquier texto agregado a cualquier índice no se marca como abarcado con esta bandera,

el SPAN_INCLUSIVE_INCLUSIVE marca cualquier texto agregado después o antes del carácter inicial y final, SPAN_INCLUSIVE_INCLUSIVE es el sinónimo de SPAN_MARK_POINT; si el rango es cero, significa que ningún texto está marcado como abarcado inicialmente, luego cualquier texto agregado a cualquier índice después o antes el carácter inicial o final siempre se marca como cruzado con esta bandera,

No he podido comprender las otras constantes de bandera definidas correctamente en la interfaz extendida.

7. Ahora podemos agregar cualquier texto dentro de nuestro objeto SpannableStringBuilder con uno de los métodos de agregar o uno de los métodos de inserción, por ejemplo-

SpannableStringBuilder text = new SpannableStringBuilder (); …… text.append (string_value); // append (texto de CharSequence) anexa una cadena dada al final // insert (int donde, CharSequence tb) inserta la cadena dada después del carácter cuyo índice es (where-1)

El nuevo texto insertado en este SpannableStringBuilder se marcará como “extendido y con estilo” o no, dependerá del indicador que hemos especificado para la llamada anterior al método setSpan (Object what, int start, int end, int flags).

8.Si queremos aplicar más de un estilo al texto en un objeto SpannableStringBuilder, podemos llamar al método setSpan (Object what, int start, int end, int flags) de nuevo y especificar el estilo al parámetro what, y el principio y el final que se van a diseñar inicialmente, luego el parámetro de indicador para especificar cómo se comportará el estilo cuando se inserte un texto nuevo. Aquí, una cosa importante es que cuando llamamos al método de tramo, el estilo que especificamos se empareja con el inicio, el final y el indicador que es independiente de cualquier llamada anterior al método de tramo, lo que significa que cada llamada al método tramo aplica un estilo que funciona independientemente de cualquier otro estilo que también se aplique al mismo texto. Aunque apliquemos el mismo estilo otra vez pero con un nuevo objeto para el parámetro “qué”, este estilo también funciona independientemente del mismo estilo aplicado anteriormente, solo forma de modificar un estilo ya aplicado es especificar el mismo objeto para el parámetro “qué”. Por ejemplo-

  TextView txv=(TextView)findViewById(R.id.textView9); String myString = "01234"; Object ob; int start = 1; int end = 4; int spanFlag = Spannable.SPAN_INCLUSIVE_INCLUSIVE; SpannableStringBuilder spannableString = new SpannableStringBuilder(myString); ForegroundColorSpan foregroundSpan = new ForegroundColorSpan(Color.RED); ob=foregroundSpan; spannableString.setSpan(foregroundSpan, start, end, spanFlag); txv.setText(spannableString); 

Esto dará como resultado que txv tenga “01234”, donde la parte “123” es roja.

  end=3; spanFlag = Spannable.SPAN_EXCLUSIVE_INCLUSIVE; spannableString.setSpan(new StyleSpan(Typeface.BOLD), start, end, spanFlag); txv.setText(spannableString); 

Esto dará como resultado que txv tenga “01234”, donde la parte “123” sea roja, y la subparte “12” sea negrita (grasosa) y roja, pero “3” solo será roja, no negrita debido al “final” valor.

  spannableString.insert(end, "x"); spannableString.insert(start, "x"); txv.setText(spannableString); 

Esto hará que txv tenga “0x12x34”, donde la parte “x12x3” es roja y solo “12×3” está en negrita, esto sucedió porque el estilo rojo se aplicó inicialmente al texto “123” con la bandera SPAN_INCLUSIVE_INCLUSIVE, lo que significa cualquier texto Anexado antes o antes de 1 y 3 siempre se incluyen en la región de estilo rojo, por lo tanto “x12x3” es rojo, el estilo negrita se aplicó inicialmente al texto “12” con el indicador SPAN_EXCLUSIVE_INCLUSIVE, lo que significa que cualquier texto agregado antes de 1 no está incluido la región de estilo, pero cualquier texto agregado después de 1 y después o antes de 2 siempre se incluye en la regla de estilo negrita, por lo tanto, solo “12×3” está en negrita.

  int end=3; spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; foregroundSpan = new ForegroundColorSpan(Color.RED); spannableString.setSpan(foregroundSpan, start, end, spanFlag); txv.setText(spannableString); 

Esto causará otro estilo rojo independiente en el texto “x1”, pero como ya se aplica otro estilo rojo al texto “x12x3”, no veremos ninguna diferencia en txv. Para cambiar realmente el estilo rojo aplicado anteriormente, necesitamos pasar el mismo objeto ForegroundColorSpan que cuando llamamos al método setSpan en la primera ocasión, debemos usar el siguiente código en lugar del anterior,

  int end=3; spanFlag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE; spannableString.setSpan(ob, start, end, spanFlag); //ob refers to the same the styling object as we specified on the first occasion txv.setText(spannableString); 

Esto causará que solo “x1” sea rojo y también si agregamos cualquier texto después de “1” o antes de “x”, entonces ese texto no se incluirá en la región de estilo roja, pero cualquier texto después de “x” y antes ” 1 “siempre se incluye en la región de estilo rojo, debido a la bandera SPAN_EXCLUSIVE_EXCLUSIVE que especificamos esta vez.

9. Lo último, si queremos eliminar un estilo y sus reglas de indicador de span por completo, entonces podemos llamar al método removeSpan (Object what) definido por la interfaz Spannable implementada por la clase SpannableStringBuilder, necesitamos pasar el mismo objeto de estilo al método removeSpan como le dimos al método setSpan.

Gracias a las respuestas anteriores, especialmente el ejemplo de color me ayudó mucho a entender estas banderas correctamente.