Hi All,
After reading the manual I thought I had my head around the whole resizing thing, but clearly I was mistaken.
After a day of exploration, I'm still not completely clear on how things are supposed to work, though I do have something working (the code shown at the bottom of this post).
I started at Erel's post here:
http://www.b4x.com/forum/designer-layouts/17460-useful-tempate-1-a.html
But that presumes the same layout for all screens, horizontal or vertical.
I wanted one layout for width>height, and another for height >= width. So, I tried having two variants (320x480 and 480x320, both scale 1), and putting variant-specific code in each.
I tried putting an if in the all-variant's section of the designer script:
if height>width then
portrait code
else
landscape code
end if
But that fails because "100>100" isn't a number. The 'if' for designer scripts seems limited/nonexistent.
I have several Android devices:
Nexus One phone, Android 2.3.7 (480x800, scale 1.5)
Sumvision Cyclone Astro, 7" tab, Android 2.3.4 (480x800, scale 1.0)
Ainol Novo7 Basic, 7" tab, Android 4.0.1 (480x800, scale 1.0)
Google Nexus 7, 7" tab, Android 4.1.1 (800x1280, scale 1.33125)
Samsung Galaxy tab, 10" tab, Android 4.0.4 (800x1280, scale 1.0)
Of course, the sizes shown are raw pixels. The size given to the activity depends on many things: the scale, chrome the vendor installed, whether the title bar is shown, whether I've asked to go full screen, etc.
Because of the wide range of devices (I have 5, but there's over 1500 these days), I figured that instead of trying to have a variant for every single device (and OS version), I'd have two generic layouts (portrait and landscape, designed in Abstract Designer), and scale the items upon Activity.create preserving their spatial relationships with something like this:
The variables scr.scalex and scr.scaley depend on my knowing the intended width/height of the layout, and the number of pixels I have to play with on the current device.
The code for portrait (listed first in the designer) was always run on all my devices no matter the orientation. I'm guessing that this is because the DeviceLayout did not precisely match a variant, so it defaulted to the first one, which couldn't be customized due to the 'if' issue above.
So, that was a pretty much pointless exercise.
What I ended up doing was setting a single variant (320x480, scale 1.0) in the designer, and then modifying everything else in code.
In the end, it seems *much* simpler than trying various schemes in the designer.
This seems to be working for me on all my devices:
I'd love to hear where I went wrong, or if my approach has pitfalls I haven't thought about yet.
-Ken
After reading the manual I thought I had my head around the whole resizing thing, but clearly I was mistaken.
After a day of exploration, I'm still not completely clear on how things are supposed to work, though I do have something working (the code shown at the bottom of this post).
I started at Erel's post here:
http://www.b4x.com/forum/designer-layouts/17460-useful-tempate-1-a.html
But that presumes the same layout for all screens, horizontal or vertical.
I wanted one layout for width>height, and another for height >= width. So, I tried having two variants (320x480 and 480x320, both scale 1), and putting variant-specific code in each.
I tried putting an if in the all-variant's section of the designer script:
if height>width then
portrait code
else
landscape code
end if
But that fails because "100>100" isn't a number. The 'if' for designer scripts seems limited/nonexistent.
I have several Android devices:
Nexus One phone, Android 2.3.7 (480x800, scale 1.5)
Sumvision Cyclone Astro, 7" tab, Android 2.3.4 (480x800, scale 1.0)
Ainol Novo7 Basic, 7" tab, Android 4.0.1 (480x800, scale 1.0)
Google Nexus 7, 7" tab, Android 4.1.1 (800x1280, scale 1.33125)
Samsung Galaxy tab, 10" tab, Android 4.0.4 (800x1280, scale 1.0)
Of course, the sizes shown are raw pixels. The size given to the activity depends on many things: the scale, chrome the vendor installed, whether the title bar is shown, whether I've asked to go full screen, etc.
Because of the wide range of devices (I have 5, but there's over 1500 these days), I figured that instead of trying to have a variant for every single device (and OS version), I'd have two generic layouts (portrait and landscape, designed in Abstract Designer), and scale the items upon Activity.create preserving their spatial relationships with something like this:
B4X:
Dim v As View
For i =0 To Activity.NumberOfViews-1
v = Activity.GetView(i)
v.Left = v.Left*scr.scalex
v.Width = v.Width*scr.scalex
v.Top = v.Top*scr.scaley
v.Height = v.Height*scr.scaley
Next
The variables scr.scalex and scr.scaley depend on my knowing the intended width/height of the layout, and the number of pixels I have to play with on the current device.
The code for portrait (listed first in the designer) was always run on all my devices no matter the orientation. I'm guessing that this is because the DeviceLayout did not precisely match a variant, so it defaulted to the first one, which couldn't be customized due to the 'if' issue above.
So, that was a pretty much pointless exercise.
What I ended up doing was setting a single variant (320x480, scale 1.0) in the designer, and then modifying everything else in code.
In the end, it seems *much* simpler than trying various schemes in the designer.
This seems to be working for me on all my devices:
B4X:
Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("homescreen")
resizeIface
' Then I do the rest of the setup for my Activity...
End Sub
Sub resizeIface
Dim cardsize As Int
' scr is a process global defined like this:
' Type scrMeasurements(portrait As Boolean,aspect As Double, cardw _
' As Int, cardh As Int, scalex As Double, scaley As Double, _
' delta As Double, rate As Double)
' Dim scr As scrMeasurements
scr.Initialize
lv = GetDeviceLayoutValues
If lv.Height > lv.Width Then
scr.portrait = True
Else
scr.portrait = False
End If
scr.aspect = lv.Width / lv.Height
If scr.portrait Then
scr.scalex = 100%x / 320dip
scr.scaley = 100%y / 480dip
cardsize = lv.Width/lv.Scale
Else
scr.scalex = 100%x / 480dip
scr.scaley = 100%y / 320dip
cardsize = lv.Height/lv.Scale
End If
If cardsize >= 750 Then
scr.cardw = 87dip
scr.cardh = 120dip
Else
If cardsize >= 480 Then
scr.cardw = 72dip
scr.cardh = 100dip
Else
If cardsize > 320 Then
scr.cardw = 55dip
scr.cardh = 70dip
Else
scr.cardw = 41dip
scr.cardh = 52dip
End If
End If
End If
' could this be a formula? It's not quite linear...this is
' too small on a phone.
' scr.cardw = cardsize/7.52
' scr.cardh = cardsize/5.45
Log("scr is "&scr)
panel2.SetLayout(0,0,100%x,100%y)
Dim v As View
Dim l,t,w,h As Int
For i =0 To Activity.NumberOfViews-1
v = Activity.GetView(i)
l = v.left * scr.scalex
t = v.Top * scr.scaley
w = v.Width * scr.scalex
h = v.Height * scr.scaley
v.SetLayout(l,t,w,h)
Next
' Want these to stay at a constant width.
playertrack.Width=10
playertrackprogress.Width=10
computertrack.Width=10
computertrackprogress.Width=10
' Now that we've diddled all the sizes, redraw.
Activity.Invalidate
End Sub
I'd love to hear where I went wrong, or if my approach has pitfalls I haven't thought about yet.
-Ken