30

TextViewの境界(X次元とY次元の両方)に収まるように、複数行のテキストのサイズを変更するメソッドを作成しようとしていTextViewます。

現在、私は何かを持っていますが、テキストの最初の文字/文字だけがの寸法を満たすようにテキストのサイズを変更するだけですTextView(つまり、最初の文字だけが表示され、巨大です)。TextViewの境界内にテキストのすべての行を収めるために必要です。

これが私がこれまでに持っているものです:

public static void autoScaleTextViewTextToHeight(TextView tv)
{
    final float initSize = tv.getTextSize();
    //get the width of the view's back image (unscaled).... 
    float minViewHeight;
    if(tv.getBackground()!=null)
    {
      minViewHeight = tv.getBackground().getIntrinsicHeight();
    }
    else
    {
      minViewHeight = 10f;//some min.
    }
    final float maxViewHeight = tv.getHeight() - (tv.getPaddingBottom()+tv.getPaddingTop())-12;// -12 just to be sure
    final String s = tv.getText().toString();

    //System.out.println(""+tv.getPaddingTop()+"/"+tv.getPaddingBottom());

    if(minViewHeight >0 && maxViewHeight >2)
    {
      Rect currentBounds = new Rect();
      tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
      //System.out.println(""+initSize);
      //System.out.println(""+maxViewHeight);
      //System.out.println(""+(currentBounds.height()));

      float resultingSize = 1;
      while(currentBounds.height() < maxViewHeight)
      {
        resultingSize ++;
        tv.setTextSize(resultingSize);

        tv.getPaint().getTextBounds(s, 0, s.length(), currentBounds);
        //System.out.println(""+(currentBounds.height()+tv.getPaddingBottom()+tv.getPaddingTop()));
        //System.out.println("Resulting: "+resultingSize);
      }
      if(currentBounds.height()>=maxViewHeight)
      {
        //just to be sure, reduce the value
        tv.setTextSize(resultingSize-1);
      }
    }
}

問題はの使用にあると思いますtv.getPaint().getTextBounds(...)。テキストのサイズがの幅または高さよりもはるかに大きい場合でも、テキストの境界には常に小さい数値が返されます...および値に比べて小さいtv.getWidth()...。tv.getHeight()TextView

4

14 に答える 14

4

さまざまな 7 インチ タブレット (Kindle fire、Nexus7、および低解像度の画面を備えた中国の安価なタブレット) とデバイスでフォント サイズを正しくしようと、かなり長い間これを試してきました。

最終的に私のために働いたアプローチは次のとおりです。「32」は、私が探していたフォント サイズである 7 インチ タブレットの水平線に基本的に約 70 文字以上を与える任意の要素です。それに応じて調整します。

textView.setTextSize(getFontSize(activity));


public static int getFontSize (Activity activity) { 

    DisplayMetrics dMetrics = new DisplayMetrics();
    activity.getWindowManager().getDefaultDisplay().getMetrics(dMetrics);

    // lets try to get them back a font size realtive to the pixel width of the screen
    final float WIDE = activity.getResources().getDisplayMetrics().widthPixels;
    int valueWide = (int)(WIDE / 32.0f / (dMetrics.scaledDensity));
    return valueWide;
}
于 2013-01-09T17:20:18.390 に答える
3

自分で解決策を探しているときにこれに遭遇しました...スタックオーバーフローなどで確認できる他のすべての解決策を試しましたが、実際には機能しなかったので、自分で作成しました。

基本的に、テキストビューをカスタムの線形レイアウトでラップすることにより、テキストが固定幅で測定されるようにすることで、テキストを適切に測定することができました。

<!-- TextView wrapped in the custom LinearLayout that expects one child TextView -->
<!-- This view should specify the size you would want the text view to be displayed at -->
<com.custom.ResizeView
    android:layout_width="fill_parent"
    android:layout_height="0dp"
    android:layout_margin="10dp"
    android:layout_weight="1"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/CustomTextView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
</com.custom.ResizeView>

次に、線形レイアウトコード

public class ResizeView extends LinearLayout {

    public ResizeView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ResizeView(Context context) {
        super(context);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        // oldWidth used as a fixed width when measuring the size of the text
        // view at different font sizes
        final int oldWidth = getMeasuredWidth() - getPaddingBottom() - getPaddingTop();
        final int oldHeight = getMeasuredHeight() - getPaddingLeft() - getPaddingRight();

        // Assume we only have one child and it is the text view to scale
        TextView textView = (TextView) getChildAt(0);

        // This is the maximum font size... we iterate down from this
        // I've specified the sizes in pixels, but sp can be used, just modify
        // the call to setTextSize

        float size = getResources().getDimensionPixelSize(R.dimen.solutions_view_max_font_size);

        for (int textViewHeight = Integer.MAX_VALUE; textViewHeight > oldHeight; size -= 0.1f) {
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

            // measure the text views size using a fixed width and an
            // unspecified height - the unspecified height means measure
            // returns the textviews ideal height
            textView.measure(MeasureSpec.makeMeasureSpec(oldWidth, MeasureSpec.EXACTLY), MeasureSpec.UNSPECIFIED);

            textViewHeight = textView.getMeasuredHeight();
        }
    }
}

これが誰かを助けることを願っています。

于 2012-04-13T23:52:19.467 に答える
3

私は同じ問題を抱えていて、私にとってはうまくいくと思われるクラスを書きました。基本的に、静的レイアウトを使用して別のキャンバスにテキストを描画し、収まるフォント サイズが見つかるまで再測定しました。以下のトピックに投稿されたクラスを確認できます。お役に立てば幸いです。

境界内に収まるようにTextViewテキストを自動スケーリング

于 2011-04-04T07:32:14.820 に答える
3

次のコード (以下を参照) を使用して自分の質問に答えることができましたが、私の解決策はアプリケーションに非常に固有のものでした。たとえば、これはおそらく、サイズが約 1 の TextView に対してのみ適切に表示および/または機能します。画面の 1/2 (上余白 40 ピクセル、横余白 20 ピクセル... 下余白なし)。

ただし、このアプローチを使用すると、独自の同様の実装を作成できます。静的メソッドは、基本的に文字数を調べて、TextView のテキスト サイズに適用する倍率を決定し、全体の高さ (推定高さ - テキストの幅、テキストを使用して高さ、および TextView の幅) は、TextView の幅のすぐ下にあります。倍率を決定するために必要なパラメーター (つまり、if/else if ステートメント) は、推測とチェックによって設定されました。特定のアプリケーションで機能させるには、数字をいじる必要があるでしょう。

これは最も洗練されたソリューションではありませんが、コーディングは簡単で、私にとってはうまくいきます。誰もがより良いアプローチを持っていますか?

public static void autoScaleTextViewTextToHeight(final TextView tv, String s)
    {       
        float currentWidth=tv.getPaint().measureText(s);
        int scalingFactor = 0;
        final int characters = s.length();
        //scale based on # of characters in the string
        if(characters<5)
        {
            scalingFactor = 1;
        }
        else if(characters>=5 && characters<10)
        {
            scalingFactor = 2;
        }
        else if(characters>=10 && characters<15)
        {
            scalingFactor = 3;
        }
        else if(characters>=15 && characters<20)
        {
            scalingFactor = 3;
        }
        else if(characters>=20 && characters<25)
        {
            scalingFactor = 3;
        }
        else if(characters>=25 && characters<30)
        {
            scalingFactor = 3;
        }
        else if(characters>=30 && characters<35)
        {
            scalingFactor = 3;
        }
        else if(characters>=35 && characters<40)
        {
            scalingFactor = 3;
        }
        else if(characters>=40 && characters<45)
        {
            scalingFactor = 3;
        }
        else if(characters>=45 && characters<50)
        {
            scalingFactor = 3;
        }
        else if(characters>=50 && characters<55)
        {
            scalingFactor = 3;
        }
        else if(characters>=55 && characters<60)
        {
            scalingFactor = 3;
        }
        else if(characters>=60 && characters<65)
        {
            scalingFactor = 3;
        }
        else if(characters>=65 && characters<70)
        {
            scalingFactor = 3;
        }
        else if(characters>=70 && characters<75)
        {
            scalingFactor = 3;
        }
        else if(characters>=75)
        {
            scalingFactor = 5;
        }

        //System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
        //the +scalingFactor is important... increase this if nec. later
        while((((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor)*tv.getTextSize())<tv.getHeight())
        {
            tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, tv.getTextSize()+0.25f);
            currentWidth=tv.getPaint().measureText(s);
            //System.out.println(((int)Math.ceil(currentWidth)/tv.getWidth()+scalingFactor));
        }

        tv.setText(s);
    }

ありがとう。

于 2010-09-07T20:20:39.227 に答える
2

textViewがテキストを複数行にレイアウトしようとしないように、テキスト測定を行う前にsetHoriztonallyScrolling()をtrueに設定してみてください。

于 2010-04-08T13:25:34.600 に答える
2

1つの方法は、一般化された画面サイズごとに異なるsp次元を指定することです。たとえば、小さい画面には8sp、通常の画面には12sp、大きい画面には16 sp、xlargeには20spを指定します。次に、レイアウトで@dimen text_sizeなどを参照するだけで、密度はspユニットを介して処理されるため、安心できます。このアプローチの詳細については、次のリンクを参照してください。

http://www.developer.android.com/guide/topics/resources/more-resources.html#Dimension

ただし、一部の言語では単語がはるかに長いため、特に1行にテキストを保持することに関心がある場合は、より多くの言語をサポートすることは、テスト段階でより多くの作業を意味することに注意する必要があります。その場合は、たとえば、values-de-largeフォルダーにdimens.xmlファイルを作成し、手動で値を微調整します。お役に立てれば。

于 2012-09-05T22:50:06.930 に答える
1

これは、他のフィードバックに基づいて作成したソリューションです。このソリューションでは、XML でテキストのサイズを設定できます。これが最大サイズになり、ビューの高さに合わせて調整されます。 サイズ調整 TextView

 private float findNewTextSize(int width, int height, CharSequence text) {
            TextPaint textPaint = new TextPaint(getPaint());

            float targetTextSize = textPaint.getTextSize();

            int textHeight = getTextHeight(text, textPaint, width, targetTextSize);
            while(textHeight > height && targetTextSize > mMinTextSize) {
                    targetTextSize = Math.max(targetTextSize - 1, mMinTextSize);
                    textHeight = getTextHeight(text, textPaint, width, targetTextSize);
            }
            return targetTextSize;
    }
private int getTextHeight(CharSequence source, TextPaint paint, int width, float textSize) {
            paint.setTextSize(textSize);
            StaticLayout layout = new StaticLayout(source, paint, width, Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, true);
            return layout.getHeight();
    }
于 2014-01-21T05:10:48.977 に答える
0

テキストを自動的に分割して次の行に継続することが唯一の要件であり、高さが重要でない場合は、このようにしてください。

<TextView
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:maxEms="integer"
    android:width="integer"/>

これにより、maxEms 値に応じて TextView がそのコンテンツに垂直にラップされます。

于 2010-09-07T20:45:44.890 に答える
0

これは私にとってはうまくいくことがわかりました。参照: https://play.google.com/store/apps/details?id=au.id.rupert.chauffeurs_name_board&hl=en

ソース コードはhttp://www.rupert.id.au/chauffeurs_name_board/verson2.phpにあります。

http://catchthecows.com/?p=72 およびhttps://github.com/catchthecows/BigTextButton

于 2012-08-01T07:35:08.507 に答える
0

私の解決策があなたに役立つかどうかを確認してください:

境界内に収まるようにTextViewテキストを自動スケーリング

于 2011-03-12T04:25:01.410 に答える