Screen Resizing/Orientation challenge and a bug?

kcorey

Member
Licensed User
Longtime User
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:

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
 
Top