Ajouter une valeur en virgule flottante aux ressources / valeurs Android


243

J'essaie d'ajouter un peu d'espace entre les lignes à mes TextViews en utilisant android:lineSpacingMultiplier la documentation :

Espacement supplémentaire entre les lignes de texte, comme multiplicateur.

Doit être une valeur à virgule flottante, telle que "1,2".

Comme j'utilise cela dans plusieurs TextViews différentes, je voudrais ajouter une dimension / valeur globale à mes ressources, mais je ne sais pas quelle balise utiliser, si elle existe. J'ai essayé tous les types de ressources qui me conviennent, mais aucun ne fonctionne.

Ce que j'aimerais avoir serait quelque chose comme ceci:

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

Edit: je suis au courant android:lineSpacingExtra(qui a besoin d'une dimension avec une unité ajoutée), mais je voudrais utiliser android:lineSpacingMultipliersi possible.

Réponses:


517

Il existe une solution:

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

De cette façon, votre numéro flottant sera sous @dimen. Notez que vous pouvez utiliser d'autres modificateurs "format" et / ou "type", où format signifie:

Format = type de données englobant:

  • flotte
  • booléen
  • fraction
  • entier
  • ...

et type signifie:

Type = type de ressource (référencé avec R.XXXXX.name):

  • Couleur
  • dimen
  • chaîne
  • style
  • etc...

Pour récupérer des ressources à partir du code, vous devez utiliser cet extrait:

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

Je sais que cela prête à confusion (vous vous attendez à un appel comme getResources().getDimension(R.dimen.text_line_spacing)), mais Android dimensionsa un traitement spécial et le nombre "flottant" pur n'est pas une dimension valide.


De plus, il y a un petit "hack" pour mettre le nombre de flotteurs en dimension, mais soyez averti que c'est vraiment un hack , et vous risquez de perdre la plage et la précision du flotteur.

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

et à partir du code, vous pouvez obtenir ce flotteur en

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

dans ce cas, la valeur de lineSpacingest 2.024993896484375et non pas 2.025comme prévu.


2
J'ai essayé d'utiliser ceci mais j'obtiens NotFoundException, "type # 0x04 n'est pas valide", lors de la récupération de la valeur du code.
Moises Jimenez

pouvez-vous être plus précis sur le problème? vous avez probablement utilisé un mauvais type de données pour le format ...
Tomo

19
@rodkarom pour récupérer des flottants à partir de xml, utilisez ce XML: <item type="string" format="float" name="my_float">0.5</item>et ce code pour le récupérer:float my_float = Float.parseFloat (getResources ().getString (R.string.my_float));
gregn3

1
@ gregn3 Cela ne pourrait-il pas être fait simplement avec la <string>balise?
pablisco

4
Je pense que vous devriez supprimer la partie hackish, la sollution est tout simplement parfaite.
Mathijs Segers


43

Toutes les solutions vous suggèrent d'utiliser la valeur flottante prédéfinie via le code.

Mais au cas où vous vous demandez comment référencer la valeur flottante prédéfinie en XML (par exemple, les mises en page), voici un exemple de ce que j'ai fait et cela fonctionne parfaitement:

Définissez les valeurs de ressource comme type="integer"mais format="float", par exemple:

<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>

Et utilisez-les plus tard dans votre mise en page en utilisant @integer/name_of_resource, par exemple:

<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
C'est la meilleure réponse car elle me permet de modifier dynamiquement les valeurs de dimension lors de la rotation de l'écran sans avoir à écrire de code.
Phileo99

@Vyacheslav for drawables, you should use standard dimensions
waqaslam

ça ne marche pas du tout. AndroidStudio échoue même avec des dimensions
Vyacheslav

Je voulais dire<dimen>
waqaslam

19

J'ai également trouvé une solution de contournement qui semble fonctionner correctement sans avertissement:

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

Ensuite:

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

Attention : cela ne fonctionne que lorsque vous utilisez le dimen du code Java et non du xml


Malheureusement, cela ne fonctionne pas si j'utilise une telle valeur dans la définition XML: android: lineSpacingMultiplier = "@ dimen / TEXT_SPACING_MULTIPLIER". Il provoque NumberFormatException lors du gonflement de la disposition.
peter.bartos

4
Exactement. Cela ne fonctionne que lorsque vous utilisez le dimen à partir du code Java.
Cristian

2
C'est le meilleur moyen que j'ai pu trouver pour accéder aux flottants à partir du code.
Alex Lockwood

Dans floats.xml, j'ai ajouté <item name = "shadow_percent" type = "dimen"> 25% </item> puis dans mon dessinable, j'ai utilisé ce pourcentage pour définir le centre du dégradé d'ombre à l'aide d'Android: centerY = "@ dimen / shadow_percent ". Cela a parfaitement fonctionné pour définir l'ombre à 25% de la hauteur totale de la liste des calques. MERCI!
Chris Sprague

juste une note, vous devez utiliser type="fraction"pour éviter les erreurs dans le code Java
adek111

8

Ajoutez un flottant à dimens.xml:

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

Pour référencer à partir de XML:

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

Pour lire cette valeur par programme, vous pouvez utiliser à ResourcesCompat.getFloatpartir de androidx.core

Dépendance Gradle:

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

Usage:

import androidx.core.content.res.ResourcesCompat;

...

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

7

Nous pouvons également l'utiliser pour guider la disposition des contraintes.

Créez un fichier integer.xml et ajoutez-le à

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

Utiliser à partir d'un fichier layout.xml

 app:layout_constraintGuide_percent="@integer/guideline_button_top" 

1
exactement ce dont j'ai besoin, je l'utilise pour différentes valeurs de pourcentage pour les tablettes et différentes pour les mobiles sans créer deux fichiers de mise en page
abdu

5

J'ai utilisé un style pour résoudre ce problème. Le lien officiel est ici .

Des trucs assez utiles. Vous créez un fichier pour contenir vos styles (comme "styles.xml"), et les définissez à l'intérieur. Vous référencez ensuite les styles dans votre mise en page (comme "main.xml").

Voici un exemple de style qui fait ce que vous voulez:

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

Disons que vous souhaitez modifier une simple TextView avec cela. Dans votre fichier de mise en page, vous devez taper:

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

Essayez-le - c'est essentiellement ainsi que se fait toute l'interface utilisateur intégrée sur Android. Et en utilisant des styles, vous avez également la possibilité de modifier toutes sortes d'autres aspects de vos vues.


2

Si vous avez des flottants simples dont vous contrôlez la plage, vous pouvez également avoir un entier dans les ressources et diviser par le nombre de décimales dont vous avez besoin directement dans le code.

Donc quelque chose comme ça

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

est utilisé avec 2 décimales

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

et cela fait 3,56f

Cela ne veut pas dire que c'est la solution la plus élégante mais pour les projets simples, c'est pratique.


0

J'ai trouvé une solution qui fonctionne, mais qui aboutit à un Warning( WARN/Resources(268): Converting to float: TypedValue{t=0x3/d=0x4d "1.2" a=2 r=0x7f06000a}) dans LogCat.

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

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

voir ma réponse ci-dessus. vous pouvez utiliser l'élément de ressource "générique", où vous devez spécifier le format et le type. le format est pour le type java (float, boolean, fraction, integer, etc.), et le type est pour la référence de ressource gen android ("dimen" pour R.dimen, "color" pour R.color, "string" pour R.string , etc.)
Tomo

C'était ma réponse initiale qui est vraiment dépassée maintenant, c'est pourquoi j'ai accepté votre réponse. :)
slup

0

Bien que j'aie utilisé la réponse acceptée dans le passé, il semble qu'avec les outils de construction actuels, il est possible de faire:

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

J'utilise Build Tools version principale 29.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.