2016-05-01 3 views
29

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

  • сделать RM относительно меньше
  • сделать RM выровнен к началу точно

я почти в состоянии достичь его с помощью

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

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

enter image description here

Однако, он выровнен по низу. Он не соответствует вершине.

Я стараюсь использовать SuperscriptSpan. Похоже

enter image description here

Это не то, что я хочу, как

  • SuperscriptSpan не делает текст меньше. Я не могу контролировать его размер.
  • SuperscriptSpan сделает текст «над верхней совместятся»

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

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

enter image description here

Пожалуйста, обратите внимание, что мы не хотим идти на решение 2 TextViews.

+0

Вы можете сделать это легко с помощью два textView. – Masum

+0

http://stackoverflow.com/questions/28830159/multiple-relativesizespan-on-same-line – USKMobility

+0

Не могли бы вы опубликовать снимок экрана, что вы хотите? –

ответ

14

Однако я сделал таким образом:

enter image description here

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

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

+0

Но это еще не выровнено. Вы можете видеть, что «RM» - позиция выше, чем «123.456» –

+0

@CheokYanCheng, можете ли вы отправить снимок экрана, что вы хотите? –

+0

Я обновил скриншот. –

10

Вы можете достичь верхней гравитации путем создания пользовательского 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); 

Выход:

enter image description here

Для получения дополнительной информации о MetricAffectingSpan: http://developer.android.com/reference/android/text/style/MetricAffectingSpan.html

Пользовательские MetricAffectingSpan логики, перешедших из: Two different styles in a single textview with different gravity and hieght

7

вы должны использоваться HTML тег, как показано ниже для подстрочный и superscript.It работает как шарм.

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

enter image description here

или

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

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

наиболее подходящее решение идти с HTML.

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

здесь пример взять его так же, как вы хотите тексту

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

я получаю результат в андроида

ТМ 123.456.

вы можете легко отображать текст в TextView в андроиде с

Html.fromText("YOUR_STRING_INHTML");

Надеется, что это помогает.

11

Я взглянул на 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; 
    } 
} 
7

Я реализовал это в одном из моего приложения.

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

В деятельности/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; 
} 

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

enter image description hereenter image description hereenter image description here

+0

@Srivivasan Я не могу найти последний формат (BLUE one) из getFormattedSpannedString, я пробовал все из них, но ни один из них не дает тот же результат. –

+0

@RonakMehta Я прокомментировал этот код. Вы должны установить значение ForegroundColorSpan (в примере добавлен WHITE). Вы можете изменить его на BLUE. – Srinivasan

0

класс для верхнего выравнивания, которая должна использоваться вместо 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);