Fügen Sie Android-Ressourcen / -Werten Gleitkommawerte hinzu


243

Ich versuche, meinen TextViews mithilfe android:lineSpacingMultiplier der Dokumentation einen kleinen Abstand zwischen den Zeilen hinzuzufügen :

Zusätzlicher Abstand zwischen Textzeilen als Multiplikator.

Muss ein Gleitkommawert sein, z. B. "1.2".

Da ich dies in einigen verschiedenen TextViews verwende, möchte ich meinen Ressourcen eine globale Dimension / einen globalen Wert hinzufügen, weiß aber nicht, welches Tag ich verwenden soll, falls es überhaupt vorhanden ist. Ich habe alle Ressourcentypen ausprobiert , die für mich sinnvoll sind, aber keiner von ihnen funktioniert.

Was ich gerne hätte, wäre ungefähr so:

<resources>
    <dimen name="text_line_spacing">1.4</dimen>
</resources>

Bearbeiten: Mir ist bekannt android:lineSpacingExtra(was eine Dimension mit einer angehängten Einheit benötigt), aber ich würde sie gerne verwenden, android:lineSpacingMultiplierwenn dies möglich ist.

Antworten:


517

Es gibt eine Lösung:

<resources>
    <item name="text_line_spacing" format="float" type="dimen">1.0</item>
</resources>

Auf diese Weise befindet sich Ihre Float-Nummer unter @dimen. Beachten Sie, dass Sie andere Modifikatoren "Format" und / oder "Typ" verwenden können, wobei Format für Folgendes steht:

Format = umschließender Datentyp:

  • schweben
  • Boolescher Wert
  • Fraktion
  • ganze Zahl
  • ...

und Typ steht für:

Typ = Ressourcentyp (referenziert mit R.XXXXX.name):

  • Farbe
  • dimen
  • Zeichenfolge
  • Stil
  • etc...

Um Ressourcen aus Code abzurufen, sollten Sie dieses Snippet verwenden:

TypedValue outValue = new TypedValue();
getResources().getValue(R.dimen.text_line_spacing, outValue, true);
float value = outValue.getFloat();  

Ich weiß, dass dies verwirrend ist (man würde einen Anruf erwarten getResources().getDimension(R.dimen.text_line_spacing)), aber Android dimensionshat eine Sonderbehandlung und die reine "Float" -Nummer ist keine gültige Dimension.


Zusätzlich gibt es einen kleinen "Hack", um die Float-Nummer in die Dimension zu bringen. Seien Sie jedoch gewarnt, dass dies wirklich ein Hack ist und Sie das Risiko eingehen , die Float-Reichweite und -Präzision zu verlieren.

<resources>
    <dimen name="text_line_spacing">2.025px</dimen>
</resources>

und aus Code können Sie diesen Float vorbei bekommen

float lineSpacing = getResources().getDimension(R.dimen.text_line_spacing);

in diesem Fall Wert lineSpacingheißt 2.024993896484375, und nicht , 2.025wie man es erwartet.


2
Ich habe versucht, dies zu verwenden, erhalte jedoch die NotFoundException "Typ # 0x04 ist ungültig", wenn der Wert aus dem Code abgerufen wird.
Moises Jimenez

Können Sie das Problem genauer beschreiben? Sie haben wahrscheinlich einen falschen Datentyp für das Format verwendet ...
Tomo

19
@rodkarom, um Floats aus XML abzurufen, verwenden Sie dieses XML: <item type="string" format="float" name="my_float">0.5</item>und diesen Code, um es abzurufen:float my_float = Float.parseFloat (getResources ().getString (R.string.my_float));
Gregn3

1
@ gregn3 Könnte das nicht einfach mit dem <string>Tag gemacht werden?
Pablisco

4
Ich denke, Sie sollten den hackischen Teil entfernen, die Lösung ist einfach perfekt wie sie ist.
Mathijs Segers


43

Alle Lösungen empfehlen, den vordefinierten Gleitkommawert durch Code zu verwenden.

Wenn Sie sich jedoch fragen, wie Sie auf den vordefinierten Gleitkommawert in XML verweisen sollen (z. B. Layouts), finden Sie im Folgenden ein Beispiel dafür, was ich getan habe und es funktioniert einwandfrei:

Definieren Sie Ressourcenwerte wie type="integer"aber format="float", zum Beispiel:

<item name="windowWeightSum" type="integer" format="float">6.0</item>
<item name="windowNavPaneSum" type="integer" format="float">1.5</item>
<item name="windowContentPaneSum" type="integer" format="float">4.5</item>

Und verwenden Sie sie später in Ihrem Layout, indem Sie @integer/name_of_resourcebeispielsweise Folgendes verwenden :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="@integer/windowWeightSum"                 // float 6.0
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="@integer/windowNavPaneSum"        // float 1.5
        android:orientation="vertical">
        <!-- other views -->
    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="@integer/windowContentPaneSum"    // float 4.5
        android:orientation="vertical">
        <!-- other views -->
    </LinearLayout>

</LinearLayout>

1
Dies ist die beste Antwort, da ich damit die Bemaßungswerte bei Bildschirmdrehung dynamisch ändern kann, ohne Code schreiben zu müssen.
Phileo99

@Vyacheslav für Drawables, sollten Sie Standard verwenden Dimensionen
waqaslam

es funktioniert überhaupt nicht. AndroidStudio scheitert sogar mit Dimensionen
Vyacheslav

Ich meinte mit<dimen>
waqaslam

19

Ich habe auch eine Problemumgehung gefunden, die ohne Warnungen gut zu funktionieren scheint:

<resources>
    <item name="the_name" type="dimen">255%</item>
    <item name="another_name" type="dimen">15%</item>
</resources>

Dann:

// theName = 2.55f
float theName = getResources().getFraction(R.dimen.the_name, 1, 1);
// anotherName = 0.15f
float anotherName = getResources().getFraction(R.dimen.another_name, 1, 1);

Warnung : Es funktioniert nur, wenn Sie das Dimen aus Java-Code verwenden, nicht aus XML


Dies funktioniert leider nicht, wenn ich einen solchen Wert in der XML-Definition verwende: android: lineSpacingMultiplier = "@ dimen / TEXT_SPACING_MULTIPLIER". Es verursacht NumberFormatException beim Aufblasen des Layouts.
Peter.bartos

4
Genau. Dies funktioniert nur, wenn Sie das Dimen aus Java-Code verwenden.
Cristian

2
Dies ist der beste Weg, um über Code auf Floats zuzugreifen.
Alex Lockwood

In floats.xml habe ich <item name = "shadow_percent" type = "dimen"> 25% </ item> hinzugefügt und dann in meinem Zeichen dieses Prozent verwendet, um die Mitte des Schattengradienten mit android festzulegen: centerY = "@ dimen / shadow_percent ". Dies funktionierte perfekt, um den Schatten auf 25% der Gesamthöhe der Ebenenliste einzustellen. DANKE!
Chris Sprague

Nur eine Anmerkung, die Sie verwenden sollten type="fraction", um Fehler im Java-Code zu vermeiden
adek111

8

Fügen Sie float.xml einen Float hinzu:

<item format="float" name="my_dimen" type="dimen">1.2</item>

So verweisen Sie aus XML:

<EditText 
    android:lineSpacingMultiplier="@dimen/my_dimen"
    ...

Um diesen Wert programmgesteuert zu lesen, können Sie ihn ResourcesCompat.getFloataus androidx.core verwenden

Gradle-Abhängigkeit:

implementation("androidx.core:core:${version}")

Verwendung:

import androidx.core.content.res.ResourcesCompat;

...

float value = ResourcesCompat.getFloat(context.getResources(), R.dimen.my_dimen);

7

Wir können es auch als Richtlinie für das Einschränkungslayout verwenden.

Erstellen Sie die Datei integer.xml und fügen Sie sie hinzu

 <item name="guideline_button_top" type="integer" format="float">0.60</item>

Verwendung aus einer layout.xml-Datei

 app:layout_constraintGuide_percent="@integer/guideline_button_top" 

1
genau das, was ich brauche, ich benutze dies für verschiedene Prozentwerte für Tablets und verschiedene für Handys, ohne zwei Layoutdateien zu erstellen
abdu

5

Ich habe einen Stil verwendet, um dieses Problem zu lösen. Der offizielle Link ist hier .

Ziemlich nützliches Zeug. Sie erstellen eine Datei, in der Ihre Stile gespeichert sind (z. B. "styles.xml"), und definieren sie darin. Sie verweisen dann auf die Stile in Ihrem Layout (wie "main.xml").

Hier ist ein Beispielstil, der macht, was Sie wollen:

<style name="text_line_spacing">
   <item name="android:lineSpacingMultiplier">1.4</item>
</style>

Angenommen, Sie möchten damit eine einfache Textansicht ändern. In Ihre Layoutdatei würden Sie Folgendes eingeben:

<TextView
   style="@style/summary_text"
   ...
   android:text="This sentence has 1.4 times more spacing than normal."
/>

Probieren Sie es aus - so wird im Wesentlichen die gesamte integrierte Benutzeroberfläche auf dem Android ausgeführt. Durch die Verwendung von Stilen haben Sie die Möglichkeit, alle möglichen anderen Aspekte Ihrer Ansichten zu ändern.


2

Wenn Sie einfache Gleitkommazahlen haben, deren Bereich Sie steuern, können Sie auch eine Ganzzahl in den Ressourcen haben und durch die Anzahl der Dezimalstellen dividieren, die Sie direkt im Code benötigen.

Also so etwas

<integer name="strokeWidth">356</integer>

wird mit 2 Dezimalstellen verwendet

this.strokeWidthFromResources = resources_.getInteger(R.integer.strokeWidth);    
circleOptions.strokeWidth((float) strokeWidthFromResources/ 100);

und das macht es 3.56f

Dies ist nicht die eleganteste Lösung, aber für einfache Projekte ist es praktisch.


0

Ich habe eine Lösung gefunden, die funktioniert, aber in LogCat zu einem Warning( WARN/Resources(268): Converting to float: TypedValue{t=0x3/d=0x4d "1.2" a=2 r=0x7f06000a}) führt.

<resources>
    <string name="text_line_spacing">1.2</string>
</resources>

<android:lineSpacingMultiplier="@string/text_line_spacing"/>

siehe meine Antwort oben. Sie können ein "generisches" Ressourcenelement verwenden, in dem Sie Format und Typ angeben sollten. Das Format ist für den Java-Typ (Float, Boolean, Bruch, Ganzzahl usw.) und der Typ für die Ressourcenreferenz für Android ("dimen" für R.dimen, "color" für R.color, "string" für R.string usw.)
Tomo

Dies war meine erste Antwort, die jetzt wirklich veraltet ist. Deshalb habe ich Ihre Antwort akzeptiert. :)
Slup

0

Obwohl ich in der Vergangenheit die akzeptierte Antwort verwendet habe, scheint es mit den aktuellen Build Tools möglich zu sein:

   <dimen name="listAvatarWidthPercent">0.19</dimen>

Ich verwende Build Tools Hauptversion 29.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.