So skalieren / Größe ändern Text, um eine Textview passt ?

? RyanM @ | Original: StackOverFlow
---

Ich versuche, eine Methode zur Größenänderung mehrzeiligen Text in einem TextView, so dass sie innerhalb der Grenzen ( der X- und Y-Dimensionen ) der TextView passt zu schaffen.

Derzeit habe ich etwas, aber alle es tut, ist die Größe des Textes, so dass nur der erste Buchstabe / Zeichen des Textes erfüllt die Dimensionen der TextView (dh nur der erste Buchstabe ist sichtbar, und es ist sehr groß) . Ich brauche es, um alle Zeilen des Textes innerhalb der Grenzen des Textview passen.

Hier ist, was ich bisher :

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

Ich denke, das Problem ist bei der Verwendung von tv.getPaint().getTextBounds(...) . Es gibt immer eine kleine Anzahl für den Text Grenzen ... klein im Vergleich zu den tv.getWidth() und tv.getHeight() Werte ... auch wenn die Textgröße ist weit größer als die Breite oder Höhe des TextView .

---

Top 5 Antwort

1snctln @

Vielleicht versuchen Sie, http://developer.android.com/reference/android/widget/TextView.html#setHorizontallyScrolling%28boolean%29 auf true, bevor Sie Text Messungen, so dass die Textview versucht nicht, Ihren Text auf mehrere Zeilen -Layout

2RyanM @

Ich konnte meine eigene Frage zu beantworten mit dem folgenden Code (siehe unten), aber meine Lösung war sehr spezifisch für die Anwendung . Beispielsweise wird dies wahrscheinlich nur gut aus und / oder arbeiten für eine Textview so bemessen, dass ca. 1/2 der Bildschirm ( mit ebenfalls einem 40px 20px oberen Rand und Seitenränder ... nein unteren Rand ) .

Die mit diesem Ansatz zwar, können Sie Ihre eigene ähnliche Umsetzung. Die statische Methode im Grunde nur befasst sich mit der Anzahl der Zeichen, und bestimmt einen Skalierungsfaktor, der auf der Textview die Textgröße gelten, und dann schrittweise erhöht die Schriftgröße, bis die Gesamthöhe ( einer geschätzten Höhe - mit Hilfe der Breite des Textes, den Text Höhe und die Breite der Textview ) nur unter der des Textview . Die Parameter, die den Skalierungsfaktor zu bestimmen (dh die if / else if-Anweisungen ) wurden von guess -and- Prüfung eingestellt . Sie werden wahrscheinlich haben zu spielen, um mit den Zahlen, um es für Ihre Anwendung zu arbeiten.

Dies ist nicht die eleganteste Lösung, aber es war einfach zu Code und es funktioniert für mich . Hat jemand eine bessere Lösung haben ?

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

Thanks.

3Octavian Damiean @

Wenn Ihre einzige Voraussetzung ist der Text automatisch Split zu haben und weiter in die nächste Zeile und die Höhe ist nicht wichtig, dann nur noch das so .

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

Dies wird Ihre Textview- Wrap müssen es Inhalte vertikal je nach maxEms Wert .

4vsm @

Überprüfen Sie, ob mein Lösung hilft Ihnen :

http://stackoverflow.com/questions/5033012/auto-scale-textview-text-to-fit-within-bounds/5280436#5280436

5Chase @

Ich hatte das gleiche Problem und schrieb eine Klasse, die für mich arbeiten scheint . Im Grunde habe ich eine statische Layout, um den Text in einem separaten Leinwand ziehen und neu zu bewerten, bis ich eine Schriftgröße, die passt. Sie können die Klasse in der folgenden Thema geschrieben sehen . Ich hoffe es hilft.

http://stackoverflow.com/questions/5033012/auto-scale-textview-text-to-fit-within-bounds/5535672#5535672