Italian Righello e centimetri

Kapelis

Member
Licensed User
Longtime User
Salve amici, chiedo cortesemente il vostro aiuto per risolvere un problema. Vorrei costruire un semplice righello sullo schermo (orientato in landscape), con dieci semplici barrette che rappresenterebbero i centimetri. Ovviamente le distanze sullo schermo dovrebbero corrispondere alla realtà, sul mio schermo (galaxy S3) cosi come su tutti gli schermi. Vi posto il codice che ho usato. Le barrette dei centimetri sullo schermo del mio cel non corrispondono al vero, fra 0 e 1 cm sono quasi giusti, ma al decimo cm la differenza e tanta, circa 3-4 mm. Dove sbaglio? Grazie di cuore per il vostro aiuto.
B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
Dim Cel As Phone
    Private imgRosso As ImageView
    Private imgBlu As ImageView
Dim dpi As Float
    Dim dpi2 As Float
Dim S As Float
Private img1 As ImageView
    Private img2 As ImageView
    Private img3 As ImageView
    Private img4 As ImageView
    Private img5 As ImageView
    Private img6 As ImageView
    Private img7 As ImageView
    Private img8 As ImageView
    Private img9 As ImageView
Private img10 As ImageView
Private img11 As ImageView
    Private Panel1 As Panel
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Cel.SetScreenOrientation(0)

    S=GetDeviceLayoutValues.Scale ' trova i dpi dello schermo
    If S= 0.75 Then
        dpi=120
    Else If  S= 1 Then
        dpi=160
    Else If  S= 1.5 Then
        dpi=240
    Else If S=2 Then
        dpi=320
    End If
   
    Dim Cm As Int
' dpi in 1 Cm. Se in un pollice (25,4 mm) ho 320 dpi, in 1 cm (10 mm) avrò i dpi
‘ ricavati con la seguente formula:
    Cm = dpi*10/25.4

    ' centimetri
    img1.Left=0dip
    img2.Left= Cm*1
    img3.Left= Cm*2
    img4.Left= Cm*3
    img5.Left= Cm*4
    img6.Left=Cm*5
    img7.Left=Cm*6
    img8.Left=Cm*7
    img9.Left=Cm*8
    img10.Left=Cm*9
img11.Left=Cm*10

End Sub
 
Last edited:

IlCasti

Active Member
Licensed User
Longtime User
Così ad occhio mi sembrano uguali
Non ho preso il cm
L'ultimo se lo schermo non è esattamente x cm non sarà mai pieno
Tipo il mio è 9.x cm e l'ultimo rimane tronco

B4X:
Dim Cm As Float 'NON PERDI DECIMALI CON Dim Cm As Int
Cm = dpi*1/2.54
For i = 0 To Activity.NumberOfViews - 1
  Dim v As View
  v = Activity.GetView(i)
  If v Is ImageView Then
    v.Color=Colors.ARGB(255,Rnd(1,255),Rnd(1,255),Rnd(1,255))
    v.Width = Cm
    v.Left = i*Cm
  End If
Next
 

Kapelis

Member
Licensed User
Longtime User
Così ad occhio mi sembrano uguali
Non ho preso il cm
L'ultimo se lo schermo non è esattamente x cm non sarà mai pieno
Tipo il mio è 9.x cm e l'ultimo rimane tronco

B4X:
Dim Cm As Float 'NON PERDI DECIMALI CON Dim Cm As Int
Cm = dpi*1/2.54
For i = 0 To Activity.NumberOfViews - 1
  Dim v As View
  v = Activity.GetView(i)
  If v Is ImageView Then
    v.Color=Colors.ARGB(255,Rnd(1,255),Rnd(1,255),Rnd(1,255))
    v.Width = Cm
    v.Left = i*Cm
  End If
Next
Grazie mille, ho risolto il problema con il consiglio anche di Erel che mi ha postato il codice (per chi fosse interessato):
B4X:
DimXdpi,Ydpi As Float
Dimr As Reflector
r.Target = r.GetContext
r.Target = r.RunMethod("getResources")
r.Target = r.RunMethod("getDisplayMetrics")
Xdpi = r.GetField("xdpi")
Ydpi = r.GetField("ydpi")
 

LucaMs

Expert
Licensed User
Longtime User
Più che interessato, sono curioso: una volta che hai ottenuto il numero di pixel per pollice?

A me risultano 240, quindi nessuna differenza con:
B4X:
    S=GetDeviceLayoutValues.Scale ' trova i dpi dello schermo
    If S= 0.75 Then
        dpi=120
    Else If  S= 1 Then
        dpi=160
    Else If  S= 1.5 Then
        dpi=240
    Else If S=2 Then
        dpi=320
    End If

E se ho 240dpi, avrò 240/2.54 dpc (dot per cm :))

Se però utilizzo quel risultato, i cm mi vengono più "corti".

[P.S. Io ho utilizzato un panel sul quale disegno le righe, invece di tante immagini.]
 
Last edited:

Kapelis

Member
Licensed User
Longtime User
Più che interessato, sono curioso: una volta che hai ottenuto il numero di pixel per pollice?

A me risultano 240, quindi nessuna differenza con:
B4X:
    S=GetDeviceLayoutValues.Scale ' trova i dpi dello schermo
    If S= 0.75 Then
        dpi=120
    Else If  S= 1 Then
        dpi=160
    Else If  S= 1.5 Then
        dpi=240
    Else If S=2 Then
        dpi=320
    End If

E se ho 240dpi, avrò 240/2.54 dpc (dot per cm :))

Se però utilizzo quel risultato, i cm mi vengono più "corti".

[P.S. Io ho utilizzato un panel sul quale disegno le righe, invece di tante immagini.]
I pixel per pollice mi servono per posizionare le barrette dei centimetri sullo schermo con il comando img.left ma non so perchè non mi venivano giusti i centimetri, erano sempre più distanziati tanto che al decimo centimetro c'erano 4 mm di differenza, mentre con il codice di Erel mi vengono perfetti.
 

LucaMs

Expert
Licensed User
Longtime User
Il codice di Erel non fa altro che riportare quello che tu avevi già scritto in quella sorta di Select (hai usato gli IF ma a quelli mi riferisco).
Cioè, il mio smartphone che ha scale 1.5, nella tua IF porta a 240dpi, esattamente come il codice di Erel. Stessa cosa per un emulatore con scale 1 che riporta 160dpi sia con gli IF che con il codice di Erel.

Come hai applicato i risultati Xdpi e Ydpi?

In teoria, avresti dovuto soltanto modificare la formula che avevi usato:
Cm = dpi*1/2.54
con
Cm = Xdpi*1/2.54

ma otterresti lo stesso risultato. A meno che tu non abbia utilizzato un dispositivo con scale "anomalo" che non era previsto dalle tue IF.

B4X:
Sub Disegna
    Private Dens As Double
    Private DevLayVal As Float
    DevLayVal = GetDeviceLayoutValues.Scale
    If DevLayVal = 0.75 Then
        Dens=120
    Else If  DevLayVal= 1 Then
        Dens=160
    Else If  DevLayVal= 1.5 Then
        Dens=240
    Else If DevLayVal=2 Then
        Dens=320
    End If
   

Dim Xdpi,Ydpi As Float
Dim r As Reflector
r.Target = r.GetContext
r.Target = r.RunMethod("getResources")
r.Target = r.RunMethod("getDisplayMetrics")
Xdpi = r.GetField("xdpi")
Ydpi = r.GetField("ydpi")
Log("Xdpi = " & Xdpi)
Log("Ydpi = " & Ydpi)

    Private DipXCm As Double
    ' che io usi questo:
    DipXCm = Xdpi / 2.54
    ' oppure questo:
'    DipXCm = Dens / 2.54
    ' non cambia e non può cambiare assolutamente niente.

    Private cnv As Canvas
    cnv.Initialize(pnlCentimetro)
   
    Private x1,y1,x2,y2 As Float
    y1 = 0
    y2 = pnlCentimetro.Height
    For c = 0 To 10
        x1 = c * DipXCm
        x2 = x1
        cnv.DrawLine(x1, y1, x2, y2, Colors.Black, 1dip)
    Next
   
End Sub
 

Kapelis

Member
Licensed User
Longtime User
Il codice di Erel non fa altro che riportare quello che tu avevi già scritto in quella sorta di Select (hai usato gli IF ma a quelli mi riferisco).
Cioè, il mio smartphone che ha scale 1.5, nella tua IF porta a 240dpi, esattamente come il codice di Erel. Stessa cosa per un emulatore con scale 1 che riporta 160dpi sia con gli IF che con il codice di Erel.

Come hai applicato i risultati Xdpi e Ydpi?

In teoria, avresti dovuto soltanto modificare la formula che avevi usato:
Cm = dpi*1/2.54
con
Cm = Xdpi*1/2.54

ma otterresti lo stesso risultato. A meno che tu non abbia utilizzato un dispositivo con scale "anomalo" che non era previsto dalle tue IF.

B4X:
Sub Disegna
    Private Dens As Double
    Private DevLayVal As Float
    DevLayVal = GetDeviceLayoutValues.Scale
    If DevLayVal = 0.75 Then
        Dens=120
    Else If  DevLayVal= 1 Then
        Dens=160
    Else If  DevLayVal= 1.5 Then
        Dens=240
    Else If DevLayVal=2 Then
        Dens=320
    End If
  

Dim Xdpi,Ydpi As Float
Dim r As Reflector
r.Target = r.GetContext
r.Target = r.RunMethod("getResources")
r.Target = r.RunMethod("getDisplayMetrics")
Xdpi = r.GetField("xdpi")
Ydpi = r.GetField("ydpi")
Log("Xdpi = " & Xdpi)
Log("Ydpi = " & Ydpi)

    Private DipXCm As Double
    ' che io usi questo:
    DipXCm = Xdpi / 2.54
    ' oppure questo:
'    DipXCm = Dens / 2.54
    ' non cambia e non può cambiare assolutamente niente.

    Private cnv As Canvas
    cnv.Initialize(pnlCentimetro)
  
    Private x1,y1,x2,y2 As Float
    y1 = 0
    y2 = pnlCentimetro.Height
    For c = 0 To 10
        x1 = c * DipXCm
        x2 = x1
        cnv.DrawLine(x1, y1, x2, y2, Colors.Black, 1dip)
    Next
  
End Sub

Guarda il codice che ho postato io, che più o meno è lo stesso con il tuo, non funzionava bene anche se sembra giusto. Seguendo il consiglio di Erel che fra l'altro il codice che mi ha inviato è presente nel "beginners guide", tutto fila liscio. Ho usato il codice cosi:
B4X:
Dim r As Reflector
      r.Target = r.GetContext
      r.Target = r.RunMethod("getResources")
      r.Target = r.RunMethod("getDisplayMetrics")
      Xdpi = r.GetField("xdpi")
 
    Cm = Xdpi*10/25.4 ' Cm in dpi
    ' centimetri
    img1.Left = Cm*1
    img2.Left = Cm*2
' ecc
 

LucaMs

Expert
Licensed User
Longtime User
Quindi, Xdpi per te non corrisponde a 75, né a 160, né a 240...

Che valore hai per:
S=GetDeviceLayoutValues.Scale

e che valore per Xdpi?

Grazie, scusa se rompo, ma io ho entrambi a 240 e la risposta che mi ha dato Erel è che evidentemente il produttore del mio smartphone ha sbagliato qualcosa nell'implementazione del sistema operativo.

Tra l'altro, per verificare che il codice funzioni, è difficile farlo con gli emulatori (misurare i cm veri sullo schermo è un'impresa :))
 

Kapelis

Member
Licensed User
Longtime User
Quindi, Xdpi per te non corrisponde a 75, né a 160, né a 240...

Che valore hai per:
S=GetDeviceLayoutValues.Scale

e che valore per Xdpi?

Grazie, scusa se rompo, ma io ho entrambi a 240 e la risposta che mi ha dato Erel è che evidentemente il produttore del mio smartphone ha sbagliato qualcosa nell'implementazione del sistema operativo.

Tra l'altro, per verificare che il codice funzioni, è difficile farlo con gli emulatori (misurare i cm veri sullo schermo è un'impresa :))

Intanto io ho un Galaxy S3, per S (scala) ho 2 e come Xdpi mi dà 304,799...
 
Top