Подтвердить что ты не робот

Как сделать RelativeSizeSpan выровненным вверх

У меня есть следующая строка RM123.456. Я хотел бы

  • Сделать RM относительно небольшим
  • Сделайте RM выровненным вверх точно

Я почти достигал этого, используя

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

Результат выглядит как

введите описание изображения здесь

Однако он выровнен по отношению к нижней части. Он не соответствует вершине.

Я пытаюсь использовать SuperscriptSpan. Он выглядит как

введите описание изображения здесь

Он не делает то, что я хочу, как

  • SuperscriptSpan не уменьшает текст. Я не могу контролировать его размер.
  • SuperscriptSpan сделает текст "над верхним выравниванием"

Могу ли я узнать, как я могу установить RelativeSizeSpan в начало точно?

Это то, чего я хочу достичь.

введите описание изображения здесь

Обратите внимание: мы не хотим идти на 2 решения TextViews.

4b9b3361

Ответ 1

Однако я сделал так:

введите описание изображения здесь

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

Надеюсь, это поможет вам.

Ответ 2

Я посмотрел на RelativeSizeSpan и нашел довольно простую реализацию. Поэтому вы можете просто реализовать свой собственный RelativeSizeSpan для своей цели. Единственное отличие здесь в том, что он не реализует ParcelableSpan, так как это предназначено только для кода рамки. AntiRelativeSizeSpan - это просто быстрый взлом без особого тестирования, но, похоже, он работает нормально. Он полностью полагается на Paint.getTextBounds(), чтобы найти наилучшее значение для baselineShift, но, возможно, был бы лучший подход.

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

Ответ 3

Вы можете достичь максимальной гравитации, создав собственный класс MetricAffectingSpan

вот код пользовательского класса:

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

Применение диапазона:

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

Вывод:

введите описание изображения здесь

Подробнее о MetricAffectingSpan: http://developer.android.com/reference/android/text/style/MetricAffectingSpan.html

Пользовательская логика MetricAffectingSpan ссылается на: Два разных стиля в одном текстовом режиме с разной степенью тяжести и hieght

Ответ 4

Я реализовал это в одном из своих приложений.

 <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" />

В Activity/Frgament.class

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

Жесткий код для целей тестирования,

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

Добавьте этот класс в свой пакет,

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

}

Создан метод формата в 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;
}

Используя этот метод, вы можете сделать больше цирка, как изменение стиля текста, отдельно для SuperScript. Также вы можете добавить верхний индекс справа и слева. (Здесь я прокомментировал весь код, если вы хотите, можете попробовать...)

введите описание изображения здесь введите описание изображения здесь введите описание изображения здесь

Ответ 5

наилучшим подходящим решением является html.

Я предпочту для этих решений, он поддерживает и все версии Android, а также устройства.

вот пример, возьмите его так же, как текст

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

Я получаю результат в android

TM 123.456.

вы можете легко отображать текст в Textview в Android с помощью

Html.fromText("YOUR_STRING_INHTML");

Надеюсь, что это поможет.

Ответ 6

вам нужно использовать тег html, как показано ниже для индекса и надстрочного индекса. Он работает как шарм.

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

введите описание изображения здесь

или

Вы также можете использовать код ниже:

String titleFirst = "Insert GoTechTM device into the vehicle\ 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);

Ответ 7

Класс для верхнего выравнивания, который следует использовать вместо RelativeSizeSpan (не в дополнение к):

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

И использование:

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

Ответ 8

Многие из приведенных здесь ответов требуют, чтобы вы установили процентную шкалу размера текста и угадали смещение, чтобы учесть их ошибку при вычислении правильного смещения, или они требуют, чтобы вы установили несколько интервалов.

Итак, чтобы обновить этот вопрос, вот решение, которое устанавливает правильную базовую линию верхнего индекса и только запрашивает, чтобы вы предоставили процентное значение масштаба текста только для 1 требуемого диапазона:

class TopAlignSuperscriptSpan(private val textSizeScalePercentage: Float = 0.5f) : MetricAffectingSpan() {

    override fun updateDrawState(tp: TextPaint) {
        tp.baselineShift += (tp.ascent() * textSizeScalePercentage).toInt()
        tp.textSize = tp.textSize * textSizeScalePercentage
    }

    override fun updateMeasureState(tp: TextPaint) {
        updateDrawState(tp)
    }
}

Вы можете использовать это, не устанавливая другие промежутки, например так:

val spannableString = SpannableString("RM123.456")
spannableString.setSpan(TopAlignSuperscriptSpan(0.6f), 0, 2, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE)
myTextView.text = spannableString

"RM" будет составлять 60% от размера текста "123,456", а его верх будет точно выровнен с верхом "123,456"

ОБНОВЛЕНИЕ: Вы не должны использовать это, потому что это неточно, как любой другой ответ здесь. Вместо этого я бы предложил рассчитать высоту каждого раздела текстового представления и вручную установить значение y для каждого раздела, как это делает эта библиотека: https://github.com/fabiomsr/MoneyTextView/tree/master/moneytextview/src/Основные /RES/значения

Ответ 9

Я знаю, что это старая ветка, но я только что столкнулся с этим сегодня, и я удивлен, что никто не ответил с этим... Я бы порекомендовал не жестко кодировать 2, 4 но вы можете выяснить, как

val span = SpannableStringBuilder.valueOf("$temp")
span.append("°F", SuperscriptSpan(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
span.setSpan(RelativeSizeSpan(0.5f), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
tempTextView.setText(span, TextView.BufferType.SPANNABLE)