Dodaj wartość zmiennoprzecinkową do zasobów / wartości Androida

243

Próbuję dodać trochę miejsca między wierszami do moich TextView, używając android:lineSpacingMultiplier z dokumentacji :

Dodatkowe odstępy między wierszami tekstu jako mnożnik.

Musi być wartością zmiennoprzecinkową, na przykład „1.2”.

Ponieważ używam tego w kilku różnych TextViews, chciałbym dodać globalny wymiar / wartość do moich zasobów, ale nie wiem, którego znacznika użyć, jeśli w ogóle istnieje. Próbowałem wszystkich typów zasobów, które mają dla mnie sens, ale żaden z nich nie działa.

Chciałbym mieć coś takiego:

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

Edycja: Jestem świadomy android:lineSpacingExtra(który wymaga wymiaru z dołączoną jednostką), ale chciałbym użyć, android:lineSpacingMultiplierjeśli to możliwe.

slup
źródło

Odpowiedzi:

517

Istnieje rozwiązanie:

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

W ten sposób Twój numer zmiennoprzecinkowy będzie pod @dimen. Zauważ, że możesz użyć innych modyfikatorów „format” i / lub „typ”, gdzie format oznacza:

Format = obejmujący typ danych:

  • pływak
  • boolean
  • frakcja
  • liczba całkowita
  • ...

i typ oznacza:

Type = typ zasobu (w odniesieniu do R.XXXXX.name):

  • kolor
  • dimen
  • strunowy
  • styl
  • itp...

Aby pobrać zasób z kodu, użyj tego fragmentu:

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

Wiem, że jest to mylące (można się spodziewać połączenia podobnego getResources().getDimension(R.dimen.text_line_spacing)), ale Android dimensionsma specjalne traktowanie i czysty numer „float” nie jest prawidłowym wymiarem.


Dodatkowo istnieje mały „hack”, aby umieścić liczbę zmiennoprzecinkową w wymiarze, ale OSTRZEŻENIE, że to naprawdę hack i ryzykujesz utratą zasięgu zmiennoprzecinkowego i precyzji.

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

a z kodu można uzyskać to zmiennoprzecinkowe przez

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

w tym przypadku wartość lineSpacingjest 2.024993896484375, a nie 2.025tak, jak można się spodziewać.

Tomo
źródło
2
Próbowałem tego użyć, ale otrzymałem NotFoundException „typ 0x04 nie jest prawidłowy” podczas pobierania wartości z kodu.
Moises Jimenez
czy możesz dokładniej określić problem? prawdopodobnie użyłeś niewłaściwego typu danych dla formatu ...
Tomo
19
@rodkarom, aby pobrać zmiennoprzecinkowe pliki z XML, użyj tego XML: <item type="string" format="float" name="my_float">0.5</item>i tego kodu, aby go pobrać:float my_float = Float.parseFloat (getResources ().getString (R.string.my_float));
gregn3 29.09.12
1
@ gregn3 Czy nie można tego zrobić po prostu za pomocą <string>tagu?
pablisco
4
Myślę, że powinieneś usunąć część hackish, sollution jest po prostu idealny.
Mathijs Segers,
83

Jak opisano w tym linku http://droidista.blogspot.in/2012/04/adding-float-value-to-your-resources.html

Zadeklaruj w dimen.xml

<item name="my_float_value" type="dimen" format="float">9.52</item>

Odwołanie z xml

@dimen/my_float_value

Odwołanie z Java

TypedValue typedValue = new TypedValue();
getResources().getValue(R.dimen.my_float_value, typedValue, true);
float myFloatValue = typedValue.getFloat();
yajnesh
źródło
43

Wszystkie rozwiązania sugerują użycie predefiniowanej wartości zmiennoprzecinkowej za pomocą kodu.

Ale jeśli zastanawiasz się, jak odwoływać się do predefiniowanej wartości zmiennoprzecinkowej w formacie XML (na przykład układy), poniżej znajduje się przykład tego, co zrobiłem i działa idealnie:

Zdefiniuj wartości zasobów jako, type="integer"ale format="float"na przykład:

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

A później użyj ich w swoim układzie, używając @integer/name_of_resourcena przykład:

<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>
waqaslam
źródło
1
To najlepsza odpowiedź, ponieważ pozwala mi dynamicznie zmieniać wartości wymiarów podczas obracania ekranu bez konieczności pisania kodu.
Phileo99,
@ Vyacheslav dla drawable, powinieneś użyć standardowych wymiarów
waqaslam,
to w ogóle nie działa. AndroidStudio kończy się niepowodzeniem nawet przy wymiarach
Wiaczesław,
Miałem na myśli użycie<dimen>
waqaslam,
19

Znalazłem też obejście, które wydaje się działać dobrze bez ostrzeżeń:

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

Następnie:

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

Ostrzeżenie : działa tylko wtedy, gdy używasz dimen z kodu Java, a nie z xml

Cristian
źródło
To niestety nie działa, jeśli użyję takiej wartości w definicji XML: android: lineSpacingMultiplier = "@ dimen / TEXT_SPACING_MULTIPLIER". Powoduje wyjątek NumberFormatException podczas pompowania układu.
peter.bartos
4
Dokładnie. Działa tylko wtedy, gdy używasz dimen z kodu Java.
Cristian
2
To najlepszy sposób, w jaki mogłem znaleźć dostęp do liczb zmiennoprzecinkowych z kodu.
Alex Lockwood
W floats.xml dodałem <item name = "shadow_percent" type = "dimen"> 25% </item>, a następnie w moim rysunku użyłem tego procentu do ustawienia środka gradientu cienia za pomocą Androida: centerY = "@ dimen / shadow_percent „. Działa to doskonale, ustawiając cień na 25% całkowitej wysokości listy warstw. DZIĘKUJĘ CI!
Chris Sprague,
uwaga, należy użyć, type="fraction"aby uniknąć błędów w kodzie Java
adek111,
8

Dodaj liczbę zmiennoprzecinkową do dimens.xml:

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

Aby odwołać się z XML:

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

Aby odczytać tę wartość programowo, możesz użyć ResourcesCompat.getFloatz androidx.core

Zależność stopniowa:

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

Stosowanie:

import androidx.core.content.res.ResourcesCompat;

...

float value = ResourcesCompat.getFloat(context.getResources(), R.dimen.my_dimen);
Alex Baker
źródło
7

Możemy go również użyć do wytyczenia układu ograniczenia.

Utwórz plik integer.xml i dodaj do

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

Użyj z pliku layout.xml

 app:layout_constraintGuide_percent="@integer/guideline_button_top" 
Photon Point
źródło
1
dokładnie tego, czego potrzebuję, używam tego do różnych wartości procentowych dla tabletów i różnych dla urządzeń mobilnych bez tworzenia dwóch plików układu
abdu
5

Użyłem stylu, aby rozwiązać ten problem. Oficjalny link jest tutaj .

Całkiem przydatne rzeczy. Tworzysz plik do przechowywania swoich stylów (np. „Styles.xml”) i definiujesz je w nim. Następnie odwołujesz się do stylów w swoim układzie (np. „Main.xml”).

Oto przykładowy styl, który robi to, co chcesz:

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

Powiedzmy, że chcesz zmienić prosty TextView za pomocą tego. W pliku układu wpisz:

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

Wypróbuj - jest to zasadniczo sposób, w jaki wszystkie wbudowane interfejsy użytkownika są wykonywane na Androidzie. Używając stylów, możesz zmodyfikować wszystkie inne aspekty swoich widoków.

Scott Biggs
źródło
2

Jeśli masz proste zmiennoprzecinkowe, których kontrolujesz zakres, możesz również mieć liczbę całkowitą w zasobach i podzielić przez liczbę miejsc dziesiętnych, których potrzebujesz prosto w kodzie.

Więc coś takiego

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

jest używany z 2 miejscami po przecinku

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

i to czyni go 3.56f

To nie jest najbardziej eleganckie rozwiązanie, ale dla prostych projektów jest wygodne.

Thanasis Kapelonis
źródło
0

Znalazłem rozwiązanie, które działa, ale powoduje Warning( WARN/Resources(268): Converting to float: TypedValue{t=0x3/d=0x4d "1.2" a=2 r=0x7f06000a}) w LogCat.

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

<android:lineSpacingMultiplier="@string/text_line_spacing"/>
slup
źródło
patrz moja odpowiedź powyżej. możesz użyć „ogólnego” elementu zasobu, w którym powinieneś określić format i typ. Format jest dla typu Java (zmiennoprzecinkowy, logiczny, ułamkowy, liczba całkowita itp.), a typ dla odwołania do zasobów genowych Androida („dimen” dla R.dimen, „color” dla R.color, „string” dla R.string , itp.)
Tomo
To była moja pierwotna odpowiedź, która jest teraz naprawdę nieaktualna, dlatego zaakceptowałem twoją odpowiedź. :)
slup
0

Chociaż w przeszłości korzystałem z akceptowanej odpowiedzi, wydaje się, że przy obecnych Narzędziach do kompilacji można:

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

Korzystam z głównych wersji Build Tools 29.

androidguy
źródło