2013-05-03 13 views
9

Quindi ho un dispositivo Android 2.3.5 che è NORMAL/HDPI. Ho un dimens.xml nel mio progetto:getDimension()/getDimensionPixelSize() - numero del moltiplicatore

... 
    <dimen name="gameresult_congrats_label_msg_textSize">20sp</dimen> 
... 

questo file è assolutamente identico nei valori-normali/valori-hdpi e così via cartelle. Nella mia prima attività app mi dimostra che valore utilizzando:

Toast.makeText(this, "textSize is "+getResources().getDimensionPixelSize(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show(); 

e vengono visualizzate 30. I Tried anche:

Toast.makeText(this, "textSize is "+getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show(); 

ma risultato è lo stesso. Ma solo quando ho provato questo:

Toast.makeText(this, "textSize is "+getResources().getString(R.dimen.gameresult_congrats_label_msg_textSize), Toast.LENGTH_SHORT).show(); 

Ho finalmente il mio "20sp"! Ma perché è così? Official docs says that those methods restituisce

Valore della dimensione risorsa moltiplicato per la metrica appropriata.

Ho verificato ciò cambiando il mio valore a 25 e ho ottenuto 38 il che significa che aos usa moltiplicatore 1.5. Ma perché? Ottiene già valore dalla cartella appropriata, il che significa che ottiene un valore pronto all'uso! Da dove viene ottenuto quel moltiplicatore 1.5x? So che dipende da DisplayMetrics. Ma come calcola 1.5x?
UPDATE
Capisco del moltiplicatore ma, vedete, il vero problema riguarda il doppio ridimensionamento. E questo è il motivo per cui ho fatto questa domanda.
Quindi, se ho qualche layout.xml (in res \ cartella di layout) con TexView definito come:

<TextView 
    android:id="@+id/congratsLabel" 
    ... 
    android:textSize="@dimen/gameresult_congrats_label_msg_textSize" /> 

Tutto sembra ok. Intendo che la visualizzazione del testo è come mi aspetto.
Ora lascia fare la stessa cosa in codice:

TextView congratsLabel = fineViewById(R.id.congratsLabel); 
textSize = getResources().getDimension(R.dimen.gameresult_congrats_label_msg_textSize) 
congratsLabel.setTextSize(textSize) 

e qui è il problema !!! getResources(). getDimension() restituisce un valore SCALED e questo è ok. Ma la dimensione risultante del mio textView sarà maggiore di 1.5 rispetto a quanto mi aspetto cuec setTextSize funziona con SP e qui arriva la seconda scala! Ed ecco perché AOS rende le dimensioni del testo risultanti ridimensionate a 45 (originariamente definite come 20sp).

+5

'setTextSize()' accetta un parametro 'int' aggiuntivo che specifica il tipo di dimensione' float'. Ad esempio, per il valore di dimensione già ridimensionato, utilizzare 'TypedValue.COMPLEX_UNIT_PX'. – laalto

risposta

12

Per il Supporting Different Screen Densities training, hdpi è 1.5x normali (MDPI) dimensioni. Poiché getDimensionPixelSize tiene conto di questa differenza durante la conversione in pixel, il valore restituito sarà 1.5x il valore in sp.

Si noti che sp dipende anche dalla dimensione del testo preferita dell'utente e può pertanto essere maggiore di 1,5 volte il valore previsto.

+0

Non funziona se si utilizza la cartella dei valori corrispondenti? Come se aos ottenga il valore dai valori-hdpi perché lo moltiplica ancora per 1,5 per ottenere il valore HDPI? O se esiste dimens.xml in valori-hdpi perché non usarlo senza post-conversione? – Stan

+0

@Stan - le dimensioni in dp o sp sono sempre ridimensionate quando si converte in pixel (ecco cosa sono lì per). Ciò garantisce che la dimensione fisica del testo sia esattamente la stessa su ciascun dispositivo, indipendentemente dalla densità dello schermo (20px su mppi in pollici fisici == 30px su hdp in pollici fisici). Puoi, ovviamente, costruire le tue dimensioni in pixel (vale a dire 20px), ma ciò significa che il tuo testo è estremamente piccolo sui dispositivi xhdpi mentre è enorme sui dispositivi LDAP, che non è quasi mai quello che vuoi. – ianhanniballake

+0

Sì, ma perché getDimension() fa questo? Volevo solo una cosa: ottenere il valore della mia dimensione così com'è. Come se il suo 20sp mi aspetto di ottenere 20 anziché 20x1,5 pixel. Perché voglio usarlo in metodo come view.setTextSize() che accetta valori trattati come SP anziché pixel. E questo è il problema. Quindi, se uso 20 in questo metodo, tutto sembra a posto, ma quando sto cercando di ottenere il valore usando getDimension (non getDimensionPixelSize) e AOS restituisce 30 il testo diventa troppo grande. – Stan

10

Il metodo getDimension() converte i valori dp o sp in pixel in base alla densità dello schermo corrente. Ciò è molto utile in quanto non è necessario farlo da soli, quando si desidera impostare in larghezza Java o dimensioni del testo (accettano solo pixel).

Ma se avete bisogno di sp originale o dp potreste fare "reverse engineering".

Fase 1.Controllare rapporto di scala attuale (in base alla densità dello schermo):

float scaleRatio = getResources().getDisplayMetrics().density; 

Fase 2. Ottenere dimensione da dimens.xml

float dimenPix = getResources().getDimension(R.dimen.your_dimen_name); 

Fase 3. Fare qualche matematica

float dimenOrginal = dimenPix/scaleRatio; 

Note:

  • di solito è necessario per i metodi int dimensione (come setWidth()), quindi è necessario convertire risultato float a int per esempio usando Math.round()
  • risultato più preciso quando si aggira per int si potrebbe ottenere utilizzando tale formula (dimenPix-0.5f)/scaleRatio
  • in caso di sp si poteva prendere anche in considerazione le preferenze degli utenti su scala del testo

per saperne di più dimensioni in Android: http://android4beginners.com/2013/07/appendix-c-everything-about-sizes-and-dimensions-in-android/

+0

Vedete, il problema qui riguarda il doppio ridimensionamento. Se creo un'etichetta in codice e desidero utilizzare una dimensione definita per il suo testo, uso qualcosa come 'textSize = getResources(). GetDimension (R.dimen.gameresult_congrats_label_msg_textSize)' e questo restituisce un valore SCALED. Ora se lo si imposta usando 'myLabel.setTextSize (textSize)' la dimensione risultante sarà 1.5 maggiore di quanto mi serve cuz 'setTextSize' funziona con SP e qui arriva la seconda scala! E questo è il motivo per cui ho voluto ottenere la dimensione originale (20) anziché la scala (30) che rende le dimensioni del testo risultanti ridimensionate a (45) – Stan

1

Perché ... NORMALE NON è hdpi ...
Normal è mdpi (160dpi) = 1.0x.
hdpi (240 dpi) è 1.5x.
xhdpi (320 dpi) è 2.0x.
xxdpi (480 dpi) è 3.0x.
xxxhdpi (640 dpi) è 4.0x.
E (ultimo ma non meno importante) ldpi (120 dpi) è 0,75x.

+0

Vedete, il problema qui riguarda il doppio ridimensionamento. Se creo un'etichetta in codice e desidero utilizzare una dimensione definita per il suo testo, uso qualcosa come 'textSize = getResources(). GetDimension (R.dimen.gameresult_congrats_label_msg_textSize)' e questo restituisce un valore SCALED. Ora se lo si imposta usando 'myLabel.setTextSize (textSize)' la dimensione risultante sarà 1.5 maggiore di quanto mi serve cuz 'setTextSize' funziona con SP e qui arriva la seconda scala! – Stan

+0

Quindi ... di solito uso sp e non penso nemmeno di ridimensionare manualmente. –

+0

O si esegue il ridimensionamento (nonostante il ridimensionamento del sistema) e si utilizza semplicemente px anziché sp. Avrai sicuramente degli avvertimenti sui lanci, ma puoi semplicemente ignorarli. –

5

Se qualcun altro ha bisogno di questo:

per affrontare il doppio di scala problema Stan spettacolo quando si utilizza getDimensionPixelSize con TextView.setTextSize:

È possibile utilizzare la versione alternativa di setTextSize in cui è possibile specificare l'unità come questo :

title.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.title)); 
18

Giusto per chiarire (informazioni ottenute esaminando il codice sorgente di Android):

Resources.getDimension() e getDimensionPixelOffset()/getDimensionPixelSize() differiscono solo in quanto il primo restituisce float mentre gli ultimi due restituiscono lo stesso valore arrotondato a int in modo appropriato. Per tutti loro, il valore di ritorno è in pixel non elaborati.

Tutti e tre funzioni sono implementate chiamando Resources.getValue() e convertendo così ottenuto TypedValue chiamando TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset() e TypedValue.complexToDimensionPixelSize(), rispettivamente.

Pertanto, se si desidera ottenere il valore "raw" insieme all'unità specificata nella sorgente XML, chiamare Resources.getValue() e utilizzare i metodi della classe TypedValue.