Hintergrund
Oft müssen wir die Schriftart der Textansicht automatisch an die ihr zugewiesenen Grenzen anpassen.
Das Problem
Obwohl es viele Threads und Beiträge (und Lösungsvorschläge) gibt, die über dieses Problem sprechen (Beispiel hier , hier und hier ), funktioniert leider keiner von ihnen wirklich gut.
Deshalb habe ich beschlossen, jeden von ihnen zu testen, bis ich das richtige Angebot gefunden habe.
Ich denke, dass die Anforderungen an eine solche Textansicht sein sollten:
Sollte die Verwendung von Schriftarten, Schriftarten, Stilen und Zeichensätzen ermöglichen.
Sollte sowohl Breite als auch Höhe handhaben
Keine Kürzung, es sei denn, Text kann aufgrund der von uns angegebenen Einschränkung nicht passen (Beispiel: zu langer Text, zu kleine verfügbare Größe). Wir können jedoch eine horizontale / vertikale Bildlaufleiste anfordern, wenn wir dies wünschen, nur für diese Fälle.
Sollte mehrzeilig oder einzeilig sein. Lassen Sie bei Mehrzeiligkeit die Zeilen max und min zu.
Sollte nicht langsam in der Berechnung sein. Verwenden Sie eine Schleife, um die beste Größe zu finden? Optimieren Sie es zumindest und erhöhen Sie Ihre Stichprobe nicht jedes Mal um 1.
Bei mehrzeiligen Zeilen sollten Sie die Größe ändern oder mehr Zeilen verwenden und / oder die Zeilen selbst auswählen können, indem Sie das Zeichen "\ n" verwenden.
Was ich versucht habe
Ich habe so viele Beispiele ausprobiert (einschließlich der Links, über die ich geschrieben habe), und ich habe auch versucht, sie zu ändern, um die Fälle zu behandeln, über die ich gesprochen habe, aber keines funktioniert wirklich.
Ich habe ein Beispielprojekt erstellt, mit dem ich visuell sehen kann, ob die TextView automatisch richtig passt.
Derzeit randomisiert mein Beispielprojekt nur den Text (das englische Alphabet plus Ziffern) und die Größe der Textansicht nach dem Zufallsprinzip und lässt sie in einer Zeile bleiben, aber selbst dies funktioniert bei keinem der Beispiele, die ich ausprobiert habe, gut.
Hier ist der Code (auch hier verfügbar ):
Datei res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity">
<Button android:id="@+id/button1" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" android:text="Button" />
<FrameLayout android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_above="@+id/button1"
android:layout_alignParentLeft="true" android:background="#ffff0000"
android:layout_alignParentRight="true" android:id="@+id/container"
android:layout_alignParentTop="true" />
</RelativeLayout>
Datei src/.../MainActivity.java
public class MainActivity extends Activity
{
private final Random _random =new Random();
private static final String ALLOWED_CHARACTERS ="qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
@Override
protected void onCreate(final Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup container=(ViewGroup)findViewById(R.id.container);
findViewById(R.id.button1).setOnClickListener(new OnClickListener()
{
@Override
public void onClick(final View v)
{
container.removeAllViews();
final int maxWidth=container.getWidth();
final int maxHeight=container.getHeight();
final FontFitTextView fontFitTextView=new FontFitTextView(MainActivity.this);
final int width=_random.nextInt(maxWidth)+1;
final int height=_random.nextInt(maxHeight)+1;
fontFitTextView.setLayoutParams(new LayoutParams(width,height));
fontFitTextView.setSingleLine();
fontFitTextView.setBackgroundColor(0xff00ff00);
final String text=getRandomText();
fontFitTextView.setText(text);
container.addView(fontFitTextView);
Log.d("DEBUG","width:"+width+" height:"+height+" text:"+text);
}
});
}
private String getRandomText()
{
final int textLength=_random.nextInt(20)+1;
final StringBuilder builder=new StringBuilder();
for(int i=0;i<textLength;++i)
builder.append(ALLOWED_CHARACTERS.charAt(_random.nextInt(ALLOWED_CHARACTERS.length())));
return builder.toString();
}
}
Die Frage
Kennt jemand eine Lösung für dieses häufig auftretende Problem, die tatsächlich funktioniert?
Sogar eine Lösung, die viel weniger Funktionen hat als das, worüber ich geschrieben habe, zum Beispiel eine, die nur eine konstante Anzahl von Textzeilen hat und ihre Schriftart entsprechend ihrer Größe anpasst, aber niemals seltsame Störungen aufweist und den Text auch bekommt groß / klein im Vergleich zu seinem verfügbaren Platz.
GitHub-Projekt
Da dies ein so wichtiger ist Textview, habe ich beschlossen , eine Bibliothek zu veröffentlichen, so dass jeder sie leicht nutzen könnten, und dazu beitragen, hier .
quelle
Antworten:
Dank martinh die einfache Lösung hier , dieser Code kümmert sich auch um
android:drawableLeft
,android:drawableRight
,android:drawableTop
undandroid:drawableBottom
Tags.Meine Antwort hier sollte Sie glücklich machen. TextView-Text automatisch skalieren, damit er in Grenzen passt
Ich habe Ihren Testfall geändert:
Ich poste den Code hier auf Anfrage eines Android-Entwicklers :
Endeffekt:
Beispiellayoutdatei:
Und der Java-Code:
Warnung:
Beachten Sie jedoch diesen behobenen Fehler in Android 3.1 (Honeycomb).
quelle
Ich habe die Antwort von M-WaJeEh ein wenig geändert, um zusammengesetzte Zeichnungen an den Seiten zu berücksichtigen.
Die
getCompoundPaddingXXXX()
Methoden kehren zurückpadding of the view + drawable space
. Siehe zum Beispiel: TextView.getCompoundPaddingLeft ()Problem : Dadurch wird die Messung der Breite und Höhe des für den Text verfügbaren TextView-Bereichs behoben. Wenn wir die Zeichengröße nicht berücksichtigen, wird sie ignoriert und der Text überlappt die Zeichengröße.
Aktualisiertes Segment
adjustTextSize(String)
:quelle
Ok, ich habe die letzte Woche genutzt, um meinen Code massiv umzuschreiben, damit er genau zu Ihrem Test passt. Sie können dieses jetzt 1: 1 kopieren und es wird sofort funktionieren - auch
setSingleLine()
. Bitte denken Sie daran, sich anzupassenMIN_TEXT_SIZE
undMAX_TEXT_SIZE
wenn Sie extreme Werte anstreben.Der konvergierende Algorithmus sieht folgendermaßen aus:
Und die ganze Klasse finden Sie hier.
Das Ergebnis ist jetzt sehr flexibel. Dies funktioniert genauso wie in XML deklariert wie folgt:
... sowie programmgesteuert wie in Ihrem Test erstellt.
Ich hoffe wirklich, dass Sie dies jetzt verwenden können. Sie können
setText(CharSequence text)
jetzt anrufen , um es übrigens zu verwenden. Die Klasse kümmert sich um erstaunlich seltene Ausnahmen und sollte absolut solide sein. Das einzige, was der Algorithmus noch nicht unterstützt, ist:setMaxLines(x)
wohinx >= 2
Aber ich habe umfangreiche Kommentare hinzugefügt, um Ihnen beim Aufbau zu helfen, wenn Sie möchten!
Bitte beachten Sie:
Wenn Sie dies nur normal verwenden, ohne es auf eine einzelne Zeile zu beschränken, kann es zu Wortbrüchen kommen, wie Sie bereits erwähnt haben. Dies ist eine Android-Funktion , nicht die Schuld der
AutoFitText
. Android wird immer Wörter brechen, die für eine Textansicht zu lang sind, und es ist eigentlich eine ziemliche Bequemlichkeit. Wenn Sie hier eingreifen möchten, lesen Sie bitte meine Kommentare und meinen Code ab Zeile 203. Ich habe bereits eine angemessene Aufteilung und die Anerkennung für Sie geschrieben. Alles, was Sie von nun an tun müssen, ist, die Wörter zu teilen und sie dann nach Ihren Wünschen zu ändern .Fazit: Sie sollten unbedingt in Betracht ziehen, Ihren Test neu zu schreiben, um auch Leerzeichen zu unterstützen:
Dies führt zu sehr schönen (und realistischeren) Ergebnissen.
Sie werden auch Kommentare finden, um Ihnen den Einstieg in diese Angelegenheit zu erleichtern.
Viel Glück und viele Grüße
quelle
Meine Anforderung ist zu
Ich habe auf den Link verwiesen: TextView-Text automatisch skalieren, damit er in Grenzen passt (einschließlich Kommentare), sowie auf die Datei DialogTitle.java
Ich fand, dass die bereitgestellte Lösung nett und einfach ist, aber die Größe des Textfelds nicht dynamisch ändert. Es funktioniert hervorragend, wenn die in der Listenansicht ausgewählte Textlänge größer ist als die vorhandene Textlänge in der
ScalableTextView
. Wenn der Text ausgewählt wird, dessen Länge kleiner als der vorhandene Text in istScalableTextView
, wird der Text nicht vergrößert, und der Text wird in der kleineren Größe angezeigt.Ich habe die Datei ScalableTextView.java geändert, um die Textgröße basierend auf der Textlänge anzupassen. Hier ist mein
ScalableTextView.java
Viel Spaß beim Codieren ....
quelle
Ich werde Schritt für Schritt erklären, wie dieses Attribut funktioniert.
1- Importieren Sie die Android-Unterstützungsbibliothek 26.xx in Ihre Projekt-Gradle-Datei. Wenn die IDE keine Support-Bibliothek enthält, werden sie automatisch heruntergeladen.
2- Öffnen Sie Ihre Layout-XML-Datei und gestalten Sie Ihre TextView wie folgt um. Dieses Szenario lautet: Wenn die Schriftgröße im System erhöht wird, passen Sie den Text an die verfügbare Breite an, nicht an den Zeilenumbruch.
quelle
Warnung, Fehler in Android 3 (Honeycomb) und Android 4.0 (Ice Cream Sandwich)
Androids-Versionen: 3.1 - 4.04 haben einen Fehler, dass setTextSize () in TextView nur zum ersten Mal funktioniert (erster Aufruf).
Der Fehler wird in Problem 22493: TextView-Höhenfehler in Android 4.0 und Problem 17343 beschrieben: Die Höhe und der Text der Schaltfläche kehren nach dem Erhöhen und Verringern der Textgröße in HoneyComb nicht in den ursprünglichen Zustand zurück .
Die Problemumgehung besteht darin, dem Text, der TextView zugewiesen ist, ein Zeilenumbruchzeichen hinzuzufügen, bevor Sie die Größe ändern:
Ich benutze es in meinem Code wie folgt:
Ich füge dieses "\ u3000" -Zeichen links und rechts von meinem Text hinzu, um ihn zentriert zu halten. Wenn Sie es nach links ausgerichtet haben, hängen Sie es nur nach rechts an. Natürlich kann es auch in das AutoResizeTextView-Widget eingebettet werden, aber ich wollte den festen Code draußen lassen.
quelle
Es gibt jetzt eine offizielle Lösung für dieses Problem. Mit Android O eingeführte automatische Größenanpassung von TextViews ist in der Support Library 26 verfügbar und bis hin zu Android 4.0 abwärtskompatibel.
https://developer.android.com/preview/features/autosizing-textview.html
Ich bin nicht sicher, warum https://stackoverflow.com/a/42940171/47680, das auch diese Informationen enthielt, von einem Administrator gelöscht wurde.
quelle
Ab Juni 2018 unterstützt Android diese Funktion offiziell für Android 4.0 (API Level 14) und höher.
Mit Android 8.0 (API Level 26) und höher:
Android-Versionen vor Android 8.0 (API-Level 26):
Schauen Sie sich meine detaillierte Antwort an .
quelle
Konvertieren Sie die Textansicht in ein Bild und skalieren Sie das Bild innerhalb der Grenzen.
Hier ist ein Beispiel zum Konvertieren einer Ansicht in ein Bild: Konvertieren einer Ansicht in Bitmap, ohne sie in Android anzuzeigen?
Das Problem ist, dass Ihr Text nicht auswählbar ist, aber es sollte den Trick tun. Ich habe es nicht ausprobiert, daher bin ich mir nicht sicher, wie es aussehen würde (aufgrund der Skalierung).
quelle
Unten finden Sie Avalancha TextView mit zusätzlichen Funktionen für benutzerdefinierte Schriftarten.
Verwendung:
Vergessen Sie nicht hinzuzufügen: xmlns: foo = "http://schemas.android.com/apk/res-auto". Die Schriftart sollte sich im Asset-Firectory befinden
Bekannte Fehler: Funktioniert nicht mit Android 4.03 - Schriftarten sind unsichtbar oder sehr klein (Original-Avalancha funktioniert auch nicht). Die folgende Problemumgehung ist für diesen Fehler: https://stackoverflow.com/a/21851239/2075875
quelle
Versuche dies
quelle
Wenn Sie etwas einfacheres suchen:
quelle
Schnelle Lösung für das von @Malachiasz beschriebene Problem
Ich habe das Problem behoben, indem ich in der Klasse für die automatische Größenänderung benutzerdefinierte Unterstützung hinzugefügt habe:
Rufen Sie einfach an
yourView.setTextCompat(newTextValue)
stattyourView.setText(newTextValue)
quelle
Versuchen Sie,
LayoutParams
undMaxWidth
undMaxHeight
zum hinzuzufügenTextView
. Dadurch wird das Layout gezwungen, den übergeordneten Container zu berücksichtigen und nicht überzulaufen.quelle
Seit Android O ist es möglich, die Größe von Text in XML automatisch zu ändern:
https://developer.android.com/preview/features/autosizing-textview.html
quelle
Nachdem ich Android Official Autosizing TextView ausprobiert hatte , stellte ich fest, dass Sie eine Android-Version vor Android 8.0 (API-Level 26) verwenden
android.support.v7.widget.AppCompatTextView
müssen und sicherstellen müssen , dass Ihre Support-Bibliotheksversion über 26.0.0 liegt. Beispiel:Update :
Laut der Antwort von @ android-developer überprüfe ich den
AppCompatActivity
Quellcode und finde diese beiden Zeilen inonCreate
final AppCompatDelegate delegate = getDelegate(); delegate.installViewFactory();
und in
AppCompatDelegateImpl
'screateView
Es wird die
AppCompatViewInflater
Inflater-Ansicht verwendet. BeiAppCompatViewInflater
createView wird AppCompatTextView für "TextView" verwendet.In meinem Projekt verwende ich nicht
AppCompatActivity
, also muss ich<android.support.v7.widget.AppCompatTextView>
in XML verwenden.quelle
AppCompatActivity
. AppCompatActivity verwendet das AppCompatViewInflater-Inflater-Layout.