23

テキストビュー内のテキストを自動調整する方法を探していました。検索を通じて、次のような多くのソリューションを見つけました。

しかし、他の多くの人と同様に、これらは私の問題を解決しません。複数行で TextView を使用すると、期待どおりに機能しません。

基本的に私の目標はこれです:

フェーズ 1 フェーズ2 フェーズ 3 フェーズ 4

ご覧のとおり、テキストは幅と高さに基づいてサイズ変更され、改行にも注意を払い、複数行のテキストビューを作成します。書体の変更も可能。

これを解決するための私のアイデアの1つは、次のようなものでした。

int size = CONSTANT_MAX_SIZE;
TextView tv = (TextView) findViewById(R.id.textview1)
while(Math.abs(tv.getMeasuredHeight()) >= TEXTVIEW_MAX_HEIGHT) {
    size--;
    tv.setTextSize(size);
    tv.measure(MeasureSpec.UNSPECIFIED,MeasureSpec.UNSPECIFIED);
    i++;
}

CONSTANT_MAX_SIZE は、フォントの最大サイズを定義する定数です (TextView のテキストサイズの妥当性)。

TEXTVIEW_MAX_HEIGHT は、textview の最大サイズを定義する定数です。

これは、テキストビュー内のテキストが変更されるたびに呼び出されました。

textview xml は次のようなものでした。

<TextView
     android:id="@+id/textview1"
     android:layout_width="200dp"
     android:layout_height="wrap_content"
     android:singleLine="false"
     android:inputType="textMultiLine"
     android:text=""
     android:textSize="150sp" />

XML では幅が制限されるため、ビューの高さだけを考慮する必要があります。それを調整すると、必要に応じて Android が自動的に複数行を作成するからです。

これは潜在的な解決策ですが、完全には機能しておらず (それとはほど遠い)、リサイズ ダウン (テキストを削除するとき) をサポートしていません。

提案やアイデアはありますか?

4

6 に答える 6

1

nunofmendes のアイデアを使用して、テキストのサイズを自動変更し、複数行をサポートする TextView の派生クラスを作成しました。

import android.content.Context;
import android.os.Handler;
import android.text.Layout;
import android.text.TextPaint;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.TypedValue;

public class AutoResizeTextView extends TextView {

    private Handler measureHandler = new Handler();
    private Runnable requestLayout = new Runnable() {
        @Override
        public void run() {
            requestLayout();
        }
    };

    public AutoResizeTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

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

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

    @Override
    protected void onMeasure(final int widthMeasureSpec,
                             final int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final float maxWidth = getWidth();
        final float maxHeight = getHeight();
        if (maxWidth < 1.0f || maxHeight < 1.0f) {
            return;
        }

        int index = 0;
        int lineCount = 0;
        CharSequence text = getText();
        final TextPaint paint = getPaint();
        while (index < text.length()) {
            index += paint.breakText(text, index, text.length(), true, maxWidth, null);
            lineCount++;
        }
        final float height = lineCount * getLineHeight() + (lineCount > 0 ?
                (lineCount - 1) * paint.getFontSpacing() : 0);
        if (height > maxHeight) {
            final float textSize = getTextSize();
            setTextSize(TypedValue.COMPLEX_UNIT_PX, (textSize - 1));
            measureHandler.post(requestLayout);
        }
    }
}
于 2014-07-08T18:29:29.037 に答える
1

あなたの解決策をありがとう、あなたはスーパーマンです! あなたのコードを TextView の派生クラスに実装しました。コードは、Xamarin android 用の C# コードに変換されます。必要に応じて Java に簡単に変換できます (Java の最初のコンストラクターを削除します)。

public class AutoFitTextView : TextView
{
    public AutoFitTextView(System.IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer)
        : base(javaReference, transfer)
    {
    }

    public AutoFitTextView(Context context)
        : base(context)
    {

    }

    public AutoFitTextView(Context context, IAttributeSet attrs)
        : base(context, attrs)
    {

    }


    public void ResizeFontSize()
    {
        int textSize = 50;
        int maxHeight = this.Height;
        while (GetHeightOfMultiLineText(this.Text, textSize, this.Width) > maxHeight)
        {
            textSize--;
        }
        float scaleFactor = Context.Resources.DisplayMetrics.ScaledDensity;
        float additionalFactor = 1.2f;

        TextSize = ((float)(textSize / (additionalFactor * scaleFactor)));
    }


    private int GetHeightOfMultiLineText(string text, int textSize, int maxWidth)
    {
        TextPaint paint = new TextPaint();
        paint.TextSize = textSize;
        int index = 0;
        int lineCount = 0;
        while (index < text.Length)
        {
            index += paint.BreakText(text, index, text.Length, true, maxWidth, null);
            lineCount++;
        }

        Rect bounds = new Rect();
        paint.GetTextBounds("Yy", 0, 2, bounds);
        // obtain space between lines
        double lineSpacing = Math.Max(0, ((lineCount - 1) * bounds.Height() * 0.25));

        return (int)Math.Floor(lineSpacing + lineCount * bounds.Height());
    }

}

ここにAXMLコードがあります

        <touchtest.AutoFitTextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/tvLabel2"
        android:singleLine="false"
        android:inputType="textMultiLine"
        android:text="I am here To test this text" />
于 2013-11-21T04:06:14.257 に答える
-2

コンパイル可能で修正されたコード: 修正する必要があるため、受け入れられたものではなく、これをコピーして貼り付けます:)

public static int getHeightOfMultiLineText(String text, int textSize, int maxWidth) {
    TextPaint paint = new TextPaint();
    paint.setTextSize(textSize);
    int index = 0;
    int lineCount = 0;
    while (index < text.length()) {
        index += paint.breakText(text, index, text.length(), true, maxWidth, null);
        lineCount++;
    }

    Rect bounds = new Rect();
    paint.getTextBounds("Yy", 0, 2, bounds);
    // obtain space between lines
    double lineSpacing = Math.max(0, ((lineCount - 1) * bounds.height() * 0.25));

    return (int) Math.floor(lineSpacing + lineCount * bounds.height());
}

使う必要があります、ありがとう。

重要: 倍率を考慮する必要があります

    int textSize = 50;
    int maxHeight = boundsTv.height();
    while (getHeightOfMultiLineText(text, textSize, params.width) > maxHeight) {
        textSize--;
    }
    float scaleFactor =  mainActivity.getResources().getDisplayMetrics().scaledDensity;     
    float temp = 1.2f;

    tvText.setTextSize((float) (textSize / (temp*scaleFactor)));
于 2013-11-02T14:22:28.100 に答える