次の文字列RM123.456があります。私はしたいと思います
私はほぼ使用してそれを達成することができます
spannableString.setSpan(new RelativeSizeSpan(0.50f), 0, index, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableString, TextView.BufferType.SPANNABLE);
結果は次のようになります
ただし、下揃えになります。上に配置されません。
SuperscriptSpan
を使用しようとしています。のように見えます
それは私が望んでいることをしません
SuperscriptSpan
はテキストを小さくしません。サイズを制御できません。SuperscriptSpan
は、テキストを「上揃え」にしますRelativeSizeSpanを上に揃えるにはどうすればよいですか正確に?
これは私が達成したいことです。
2つのTextViewソリューションを使用することは望まないことに注意してください。
しかし、私はこのようにしました:
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 );
}
}
これがお役に立てば幸いです。
私はRelativeSizeSpan
を見て、かなり単純な実装を見つけました。そのため、目的に合わせて独自のRelativeSizeSpan
を実装できます。ここでの唯一の違いは、これがParcelableSpan
を実装しないことです。これは、フレームワークコードのみを対象としているためです。 AntiRelativeSizeSpan
は、もちろん多くのテストを行わない高速ハックですが、問題なく動作するようです。 baselineShift
に最適な値を見つけるには、完全にPaint.getTextBounds()
に依存しますが、もっと良い方法があるかもしれません。
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;
}
}
カスタムの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ロジックの参照元: 1つのテキストビューに2つの異なるスタイルがあり、重力と高さが異なる
これを私のアプリケーションの1つに実装しました。
<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のテキストスタイルや色を個別に変更するなど、より多くのサーカスを行うことができます。また、右側と左側の両方に上付き文字を追加できます(必要に応じて、ここですべてのコードにコメントを付けてみてください...)
最適なソリューションはhtmlです。
このソリューションを優先します。すべてのAndroidバージョンとデバイスでサポートされています。
ここにあなたが望むテキストと同じように取る例があります
_<p><sup>TM</sup> 123.456.</p>
_
私はAndroidで結果を得ています
TM 123.456。
AndroidでTextviewにテキストを簡単に表示できます
Html.fromText("YOUR_STRING_INHTML");
それが役に立てば幸い。
下付き文字と上付き文字には以下のようなhtmlタグを使用する必要があります。
((TextView) findViewById(R.id.text)).setText(Html.fromHtml("<sup><small>2</small></sup>X"));
または
以下のコードを使用することもできます:
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);
ここで提供される回答の多くは、テキストサイズスケールのパーセンテージを設定し、正しいオフセットを計算する際の間違いを考慮してオフセットを推測するか、複数のスパンを設定する必要があります。
したがって、この質問を更新するために、上付き文字の正しいベースラインを設定し、必要な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」は「123.456」のテキストサイズの60%になり、上端は「123.456」の上端に正確に揃えられます
[〜#〜] update [〜#〜]:これは、他のすべての回答と同様に、不正確であるため使用しないでください。代わりに、このライブラリのように、テキストビューの各セクションの高さを計算し、各セクションのy値を手動で設定することをお勧めします: https://github.com/fabiomsr/MoneyTextView/tree/master/ moneytextview/src/main/res/values
これは古いスレッドであることは知っていますが、今日これに遭遇したばかりです。誰もこれで答えていないことに驚いています... 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)
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);