Comment faire RelativeSizeSpan aligner en haut

J'ai la chaîne suivante RM123. 456 . Je voudrais

  • Faire RM relativement plus petit
  • Faire RM aligné exactement au sommet

J'ai presque réussi à y parvenir en utilisant

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

, Le résultat ressemble à

entrez la description de l'image ici

Cependant, il est aligné sur le fond. Il n'a pas d'aligner vers le haut.

J'essaie d'utiliser SuperscriptSpan. Il ressemble à

entrez la description de l'image ici

Il ne fait pas ce que je veux comme

  • SuperscriptSpan ne réduit pas le texte. Je ne suis pas capable de contrôler son dimensionnement.
  • {[1] } fera en sorte que le texte "sur le dessus s'alignera"

Puis-je savoir, comment puis-je aligner RelativeSizeSpan sur top exactement?

C'est ce que je souhaite réaliser.

entrez la description de l'image ici

Veuillez noter que nous ne souhaitons pas opter pour la solution 2 TextViews.

30
demandé sur pRaNaY 2016-05-01 10:06:23

7 réponses

Cependant je l'ai fait de cette façon:

entrez la description de l'image ici

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 );
        }
    }

J'espère que cela vous aidera.

15
répondu Hiren Patel 2016-05-08 21:22:35

J'ai regardé le RelativeSizeSpan et j'ai trouvé une implémentation plutôt simple. Donc, vous pouvez simplement implémenter votre propre RelativeSizeSpan pour votre but. La seule différence ici est qu'il n'implémente pas ParcelableSpan, car il est uniquement destiné au Code framework. AntiRelativeSizeSpan est juste un hack rapide sans beaucoup de tests bien sûr, mais il semble fonctionner correctement. Il repose complètement sur Paint.getTextBounds() pour trouver la meilleure valeur pour le baselineShift, mais peut-être y aurait-il un meilleur approche.

Original RelativeSizeSpan AntiRelativeSizeSpan

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;
    }
}
12
répondu tynn 2016-05-07 12:39:38

Vous pouvez atteindre la gravité supérieure en créant une classe metricaffectingspan personnalisée

Voici le code de la classe personnalisée:

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);
    }
}

L'Application de la durée:

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);

Sortie:

entrez la description de l'image ici

Pour plus d'informations sur MetricAffectingSpan: http://developer.android.com/reference/android/text/style/MetricAffectingSpan.html

Logique Metricaffectingspan personnalisée référencée à partir de: deux styles différents dans un seul textview avec gravité différente et hieght

10
répondu Abhishek V 2017-05-23 12:25:47

La meilleure solution appropriée est go avec html.

Je préférerai pour cette solution, il prend en charge dans toutes les versions android ainsi que les appareils.

Voici un exemple, prenez-le comme vous voulez du texte

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

Je reçois des résultats dans android

TM 123.456.

Vous pouvez facilement afficher du texte dans Textview android avec

Html.fromText("YOUR_STRING_INHTML");

J'espère que ça aide.

7
répondu Imtiyaz Khalani 2016-05-06 07:59:08

J'ai implémenté ceci dans une de mes applications.

 <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 Activité / Frgament.Classe

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

Codé en dur à des fins de test,

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

Ajoutez cette classe dans votre paquet,

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);
}

}

A créé la méthode de format dans UntilityClass.Classe

 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;
}

En utilisant cette méthode, vous pouvez faire plus de cirque comme changer le style de texte, la couleur séparément pour L'exposant. Vous pouvez également ajouter un exposant à droite et à gauche.(Ici, j'ai commenté tout le code, si vous voulez pouvez donner un essai...)

entrez la description de l'image icientrez la description de l'image icientrez la description de l'image ici

7
répondu Srinivasan 2016-05-10 12:38:45

Vous devez utiliser la balise html comme ci-dessous pour l'indice et superscript.It fonctionne comme un charme.

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

entrez la description de l'image ici

Ou

Vous pouvez également utiliser le code ci-dessous:

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);
6
répondu Darshan Mistry 2016-05-08 21:23:09

Classe pour top align qui devrait être utilisé à la place de RelativeSizeSpan (pas en plus de):

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);
    }
}

Et utilisation:

spannableString.setSpan(new TopRelativeSizeSpan(0.50f), 0, index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString, TextView.BufferType.SPANNABLE);
0
répondu Oleksandr 2017-02-13 16:16:05