TextView.setTextSize verhält sich abnormal - So legen Sie die Textgröße der Textansicht dynamisch für verschiedene Bildschirme fest

119

Der Anruf TextView.setTextSize()funktioniert nicht ordnungsgemäß. Gleich nach dem Aufruf von, setTextSizewenn wir eine erhalten getTextSize, wird ein viel höherer Wert zurückgegeben, als wir ihn zuvor festgelegt haben.

Folgendes machen wir:

zoomControl.setOnZoomInClickListener(new OnClickListener() {
    public void onClick(View view) {
        float size = mViewShabad.getTextSize() + 1;
        textView.setTextSize(size);
    }
});

Hat das schon mal jemand gesehen?

singhspk
quelle
2
Sie erhalten und stellen die Textgröße für zwei verschiedene Objekte ein?
Cheryl Simon

Antworten:

359

Der Unterschied besteht darin, dass bei der setTextSize(int size)Methode der Einheitentyp standardmäßig "sp" oder "skalierte Pixel" ist. Dieser Wert ist für jede Bildschirmdichte (ldpi, mdpi, hdpi) eine andere Pixeldimension.

getTextSize()Gibt andererseits die tatsächlichen Pixelabmessungen des Textes zurück.

Sie können mit setTextSize(int unit, float size)einem Gerätetyp angeben. Die konstanten Werte hierfür finden Sie in der TypedValue-Klasse. Einige davon sind jedoch:

TypedValue.COMPLEX_UNIT_PX   //Pixels

TypedValue.COMPLEX_UNIT_SP   //Scaled Pixels

TypedValue.COMPLEX_UNIT_DIP  //Device Independent Pixels
Kevin Coppock
quelle
Ich habe das gerade gefunden und wollte es hier posten. Vielen Dank!
singhspk
1
Ich denke es sollte eigentlich von TypedValue (Singular) sein. Der Import ist android.util.TypedValue;
Hein du Plessis
5
Zu beachten ist auch, dass dies erst auf API-Ebene 7 begonnen wurde. Ein weiteres "Gotcha" in einer lächerlichen API.
mxcl
3
Wichtig, auf die Argumentreihenfolge zu achten - Ich hatte versehentlich setTextSize (Größe, TypedValue.COMPLEX_UNIT_SP), da dies die Reihenfolge war, die ich fälschlicherweise angenommen habe!
Mark
1
Interessanterweise hatte die Verwendung von setTextSize (14, TypedValue.COMPLEX_UNIT_SP) auf ICS auf meinem Galaxy Nexus keine Auswirkung (daher verwendete Standardgröße), aber beim Upgrade auf Jelly Bean wurde kein Text angezeigt (wie 0-Größe). Ich wollte gerade einen Jelly Bean-Fehler melden, als ich meinen Fehler bemerkte!
Mark
20

Dieses Problem trat auf, weil die getTextSize()Methode die Größe in Pixel zurückgibt, die von der Bildschirmdichte abhängt! Verwenden Sie Folgendes, um die tatsächliche Textgröße zu erhalten:

DisplayMetrics metrics;
metrics = getApplicationContext().getResources().getDisplayMetrics();
float Textsize =myTextView.getTextSize()/metrics.density;
myTextView.setTextSize(Textsize+1);

ich hoffe es löst es :)

M_AWADI
quelle
2
Ich löste mein Problem durch die Verwendung von Anzeigemetriken mit setTextSize(int unit, float size)
Edward Chiang
8

Wenn Sie die Schriftgröße ändern (etwas verursacht einen Fehler anzeigen), können Sie Folgendes tun:

setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15.f);
hui 谁 与 争辉
quelle
3
Wer setzt textSize ein DIP?
IgorGanapolsky
4

Wenn wir versuchen, ein textuelles Problem mit getTextSize () zu setzen, wird der Wert in px anstelle von sp / dp / dip zurückgegeben, und wir kennen 1sp / dp = 1,5px (Bildschirmgröße = 240).

 titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*1.5f)); 

funktioniert perfekt für mich oder wir können das Verhältnis von Displaymatrix zu px: sp / dp verwenden und dann diesen Wert durch 1,5f ersetzen

means-> titleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, (getResources().getDimension(R.dimen.text_size)*your_sp_and_px_ratio_in_int f));
Ranjan
quelle
3

Nach langer Zeit schlug dies zu und löste sich schließlich so

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
          getResources().getDimension(R.dimen.textsize));

Erstellen Sie einen Dimen-Ordner wie diesen res / values ​​/ dimensions.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <dimen name="textsize">8sp</dimen>

 </resources>
NagarjunaReddy
quelle
2

Kurz gesagt, wenn Sie Ihre Textgröße verkleinern möchten

float size = mViewShabad.getTextSize()*1.1f;
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);

Da getTextSize () UNIT_PX zurückgibt, sollten wir UNIT_PX verwenden

Frank Nguyen
quelle
1

Kotlin-Lösung

Verwenden Sie zum Festlegen einer Ressource einfach Folgendes:

textView.setTextSize(COMPLEX_UNIT_PX, textView.resources.getDimension(R.dimen.my_text_size))

Um dasselbe mit einem Ressourcenwert zu tun, fügen Sie diese Erweiterungseigenschaft hinzu, um Ihre Textgröße viel einfacher festzulegen

textView.textSizeRes = R.dimen.my_text_size

var TextView.textSizeRes
    get() = textSize.toInt()
    set(@DimenRes textSizeRes) {
        setTextSize(COMPLEX_UNIT_PX, resources.getDimension(textSizeRes))
    }
Gibolt
quelle
0

Das Hinzufügen von etwas mehr Geschmack für diese Antwort, da dies auch zu Verwirrung führte. Sie sollten in der Lage sein, diesen Test in jeden @RunWith(AndroidJUnit4.class)Test Ihres Projekts einzufügen (Sie müssen die Dimensionen auch zu Ihrer dimension.xml hinzufügen).

Hinweis: Alle diese Tests bestehen

@Test public void testScaledFontSizes() {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
    final Context context = InstrumentationRegistry.getTargetContext();

    Configuration configuration = context.getResources().getConfiguration();
    configuration.fontScale = 2.0f;
    configuration.densityDpi = 160; // mdpi, 1:1
    context.getResources().updateConfiguration(configuration, null);

    float scaledTextSize = context.getResources().getDimensionPixelSize(R.dimen.sp_15);
    assertEquals(30.0f, scaledTextSize);

    // Create a new TextView with the explicitly set configuration
    TextView textView = new TextView(context);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, scaledTextSize);

    // 30, because font size is scaled
    assertEquals(30.0f, textView.getTextSize());

    // This is what we *don't* want, it's scaled *twice*!
    textView.setTextSize(scaledTextSize);
    assertEquals(60.0f, textView.getTextSize());

    // DP instead of SP tests
    float fifteenDp = context.getResources().getDimensionPixelSize(R.dimen.dp_15);
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fifteenDp);
    // Still 15, because it's DP, not SP
    assertEquals(15.0f, fifteenDp);

    textView.setTextSize(fifteenDp);
    // 30, because setTextSize DOES font scaling
    assertEquals(30.0f, textView.getTextSize());
  }
}

Der große Vorteil, den ich gefunden habe, ist, dass TextView.setTextSize(float) die Schriftartenskalierung angewendet wird. Wenn Sie also ein Maß übergeben, das bereits als SP anstelle von DP gekennzeichnet ist, erhält es die Schriftartenskalierung zweimal .

Kevin Grant
quelle