web-dev-qa-db-ja.com

RelativeSizeSpanを上に揃える方法

次の文字列RM123.456があります。私はしたいと思います

  • [〜#〜] 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つのTextViewソリューションを使用することは望まないことに注意してください。

35
Cheok Yan Cheng

しかし、私はこのようにしました:

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

これがお役に立てば幸いです。

25
Hiren Patel

私はRelativeSizeSpanを見て、かなり単純な実装を見つけました。そのため、目的に合わせて独自のRelativeSizeSpanを実装できます。ここでの唯一の違いは、これがParcelableSpanを実装しないことです。これは、フレームワークコードのみを対象としているためです。 AntiRelativeSizeSpanは、もちろん多くのテストを行わない高速ハックですが、問題なく動作するようです。 baselineShiftに最適な値を見つけるには、完全にPaint.getTextBounds()に依存しますが、もっと良い方法があるかもしれません。

Original RelativeSizeSpanAntiRelativeSizeSpan

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

カスタムの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ロジックの参照元: 1つのテキストビューに2つの異なるスタイルがあり、重力と高さが異なる

11
Abhishek V

これを私のアプリケーションの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のテキストスタイルや色を個別に変更するなど、より多くのサーカスを行うことができます。また、右側と左側の両方に上付き文字を追加できます(必要に応じて、ここですべてのコードにコメントを付けてみてください...)

enter image description hereenter image description hereenter image description here

9
Srinivasan

最適なソリューションはhtmlです。

このソリューションを優先します。すべてのAndroidバージョンとデバイスでサポートされています。

ここにあなたが望むテキストと同じように取る例があります

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

私はAndroidで結果を得ています

TM 123.456。

AndroidでTextviewにテキストを簡単に表示できます

Html.fromText("YOUR_STRING_INHTML");

それが役に立てば幸い。

8
Imtiyaz Khalani

下付き文字と上付き文字には以下のようなhtmlタグを使用する必要があります。

 ((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);
6
Darshan Mistry

ここで提供される回答の多くは、テキストサイズスケールのパーセンテージを設定し、正しいオフセットを計算する際の間違いを考慮してオフセットを推測するか、複数のスパンを設定する必要があります。

したがって、この質問を更新するために、上付き文字の正しいベースラインを設定し、必要な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

1
w3bshark

これは古いスレッドであることは知っていますが、今日これに遭遇したばかりです。誰もこれで答えていないことに驚いています... 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)
0
Joshua King

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