android android-studio spannablestring

android - Cómo hacer que RelativeSizeSpan se alinee hacia arriba



android-studio spannablestring (7)

Tengo la siguiente cadena RM123.456 . me gustaría

  • Hacer RM relativamente más pequeño
  • Hacer RM alineado al top exactamente

Casi puedo lograrlo usando

spannableString.setSpan(new RelativeSizeSpan(0.50f), 0, index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(spannableString, TextView.BufferType.SPANNABLE);

El resultado parece

Sin embargo, está alineado al fondo. No se alinea con la parte superior.

Intento usar SuperscriptSpan . Parece que

No hace lo que quiero como

  • SuperscriptSpan no hace el texto más pequeño. No soy capaz de controlar su tamaño.
  • SuperscriptSpan hará que el texto "sobre la parte superior se alinee"

¿Puedo saber cómo puedo hacer que RelativeSizeSpan se alinee exactamente arriba?

Esto es lo que deseo lograr.

Tenga en cuenta que no deseamos ir a la solución 2 TextViews.


Clase de alineación superior que se debe usar en lugar de RelativeSizeSpan (no en adicional a):

import android.text.TextPaint; import android.text.style.MetricAffectingSpan; public class TopRelativeSizeSpan extends MetricAffectingSpan { private final float mProportion; public TopRelativeSizeSpan(float proportion) { mProportion = proportion; } @Override public void updateDrawState(TextPaint ds) { ds.baselineShift += (mProportion - 1) * (ds.getTextSize() - ds.descent()); ds.setTextSize(ds.getTextSize() * mProportion); } @Override public void updateMeasureState(TextPaint ds) { updateDrawState(ds); } }

Y uso:

spannableString.setSpan(new TopRelativeSizeSpan(0.50f), 0, index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(spannableString, TextView.BufferType.SPANNABLE);


Eché un vistazo a RelativeSizeSpan y encontré una implementación bastante simple. Así que solo podría implementar su propio RelativeSizeSpan para su propósito. La única diferencia aquí es que no implementa ParcelableSpan , ya que esto solo es para el código de marco. AntiRelativeSizeSpan es solo un hack rápido sin muchas pruebas, por supuesto, pero parece funcionar bien. Se basa completamente en Paint.getTextBounds() para encontrar el mejor valor para la baselineShift Paint.getTextBounds() , pero quizás haya un mejor enfoque.

public class AntiRelativeSizeSpan extends MetricAffectingSpan { private final float mProportion; public AntiRelativeSizeSpan(float proportion) { mProportion = proportion; } public float getSizeChange() { return mProportion; } @Override public void updateDrawState(TextPaint ds) { updateAnyState(ds); } @Override public void updateMeasureState(TextPaint ds) { updateAnyState(ds); } private void updateAnyState(TextPaint ds) { Rect bounds = new Rect(); ds.getTextBounds("1A", 0, 2, bounds); int shift = bounds.top - bounds.bottom; ds.setTextSize(ds.getTextSize() * mProportion); ds.getTextBounds("1A", 0, 2, bounds); shift += bounds.bottom - bounds.top; ds.baselineShift += shift; } }


He implementado esto en una de mis aplicaciones.

<TextView android:id="@+id/txt_formatted_value" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:textColor="#000000" android:textSize="28dp" />

En Actividad / Frgament.class

myTextView = (TextView) view.findViewById(R.id.txt_formatted_value);

Codificado para fines de prueba,

String numberValue = "123.456"; myTextView.setText(UtilityClass.getFormattedSpannedString("RM"+numberValue, numberValue.length(),0));

Agrega esta clase en tu paquete,

public class SuperscriptSpanAdjuster extends MetricAffectingSpan { double ratio = 0.5; public SuperscriptSpanAdjuster() { } public SuperscriptSpanAdjuster(double ratio) { this.ratio = ratio; } @Override public void updateDrawState(TextPaint paint) { paint.baselineShift += (int) (paint.ascent() * ratio); } @Override public void updateMeasureState(TextPaint paint) { paint.baselineShift += (int) (paint.ascent() * ratio); }

}

Creado el método de formato en UntilityClass.class

public static SpannableString getFormattedSpannedString(String value, int mostSignificantLength, int leastSignificantLength){ SpannableString spanString = new SpannableString(value); /* To show the text in top aligned(Normal)*/ spanString.setSpan(new SuperscriptSpanAdjuster(0.7), 0,spanString.length()-mostSignificantLength-leastSignificantLength, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); /* Show the number of characters is normal size (Normal)*/ spanString.setSpan(new RelativeSizeSpan(1.3f), 0,spanString.length()-mostSignificantLength-leastSignificantLength, 0); /*To set the text style as bold(MostSignificant)*/ //spanString.setSpan(new StyleSpan(Typeface.BOLD), spanString.length()-mostSignificantLength-leastSignificantLength, spanString.length()-leastSignificantLength, 0); /*To set the text color as WHITE(MostSignificant)*/ //spanString.setSpan(new ForegroundColorSpan(Color.WHITE), spanString.length()-mostSignificantLength-leastSignificantLength, spanString.length()-leastSignificantLength, 0); /*Show the number of characters as most significant value(MostSignificant)*/ spanString.setSpan(new RelativeSizeSpan(2.3f), spanString.length()-mostSignificantLength-leastSignificantLength, spanString.length()-leastSignificantLength, 0); /* To show the text in top aligned(LestSignificant)*/ spanString.setSpan(new SuperscriptSpanAdjuster(1.2), spanString.length()-leastSignificantLength, spanString.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); /*To set the text style as bold(LestSignificant)*/ //spanString.setSpan(new StyleSpan(Typeface.BOLD), spanString.length()-leastSignificantLength, spanString.length(), 0); /*Show the number of characters as most significant value(LestSignificant)*/ spanString.setSpan(new RelativeSizeSpan(0.8f), spanString.length()-leastSignificantLength, spanString.length(), 0); return spanString; }

Usando este método, puedes hacer más circo como cambiar el estilo de texto, colorea por separado para SuperScript. También puede agregar superíndice en el lado derecho e izquierdo. (Aquí comenté todo el código, si lo desea, puede intentarlo ...)


La mejor solución adecuada es ir con html.

Prefiero para estas soluciones, es compatible con todas las versiones de Android, así como dispositivos.

Aquí hay un ejemplo, tómalo como quieras texto.

<p><sup>TM</sup> 123.456.</p>

Estoy obteniendo resultados en Android

TM 123.456.

puede visualizar fácilmente el texto en Textview en Android con

Html.fromText("YOUR_STRING_INHTML");

Espero eso ayude.


Podría alcanzar la mayor gravedad creando una clase personalizada MetricAffectingSpan

Aquí está el código de la clase personalizada:

public class CustomCharacterSpan extends MetricAffectingSpan { double ratio = 0.5; public CustomCharacterSpan() { } public CustomCharacterSpan(double ratio) { this.ratio = ratio; } @Override public void updateDrawState(TextPaint paint) { paint.baselineShift += (int) (paint.ascent() * ratio); } @Override public void updateMeasureState(TextPaint paint) { paint.baselineShift += (int) (paint.ascent() * ratio); } }

Aplicando el lapso:

spannableString.setSpan(new RelativeSizeSpan(0.50f), 0, index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); spannableString.setSpan(new CustomCharacterSpan(), 0, index, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(spannableString, TextView.BufferType.SPANNABLE);

Salida:

Para obtener más información sobre MetricAffectingSpan: http://developer.android.com/reference/android/text/style/MetricAffectingSpan.html

Lógica personalizada de MetricAffectingSpan referida desde: Dos estilos diferentes en una sola vista de texto con diferente gravedad y altura


Sin embargo lo hice de esta manera:

activity_main.xml :

<TextView android:id="@+id/txtView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="50dp" android:textSize="26sp" />

MainActivity.java :

TextView txtView = (TextView) findViewById(R.id.txtView); SpannableString spannableString = new SpannableString("RM123.456"); spannableString.setSpan( new TopAlignSuperscriptSpan( (float)0.35 ), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE ); txtView.setText(spannableString);

TopAlignSuperscriptSpan.java :

private class TopAlignSuperscriptSpan extends SuperscriptSpan { //divide superscript by this number protected int fontScale = 2; //shift value, 0 to 1.0 protected float shiftPercentage = 0; //doesn''t shift TopAlignSuperscriptSpan() {} //sets the shift percentage TopAlignSuperscriptSpan( float shiftPercentage ) { if( shiftPercentage > 0.0 && shiftPercentage < 1.0 ) this.shiftPercentage = shiftPercentage; } @Override public void updateDrawState( TextPaint tp ) { //original ascent float ascent = tp.ascent(); //scale down the font tp.setTextSize( tp.getTextSize() / fontScale ); //get the new font ascent float newAscent = tp.getFontMetrics().ascent; //move baseline to top of old font, then move down size of new font //adjust for errors with shift percentage tp.baselineShift += ( ascent - ascent * shiftPercentage ) - (newAscent - newAscent * shiftPercentage ); } @Override public void updateMeasureState( TextPaint tp ) { updateDrawState( tp ); } }

Espero que esto te ayudará.


tienes que usar una etiqueta html como la de abajo para subíndice y superíndice. Funciona como encanto.

((TextView) findViewById(R.id.text)).setText(Html.fromHtml("<sup><small>2</small></sup>X"));

o

También puede utilizar el siguiente código:

String titleFirst = "Insert GoTechTM device into the vehicle/'s OBDII port."; SpannableStringBuilder cs = new SpannableStringBuilder(titleFirst); cs.setSpan(new SuperscriptSpan(), titleFirst.indexOf("TM"), titleFirst.indexOf("TM")+2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); cs.setSpan(new RelativeSizeSpan((float)0.50), titleFirst.indexOf("TM"), titleFirst.indexOf("TM")+2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); txtPairInstructionFirst.setText(cs);