Layout Variants Question

PharCyDeD

Active Member
Licensed User
Longtime User
I am using this code:

B4X:
Sub Globals
   Dim DeviceType As Int
   Dim Dim480x320x160 As Int: Dim480x320x160 = 1 ' 4" phones lo-res
   Dim Dim800x480x240 As Int: Dim800x480x240 = 2 ' 4" phones
   Dim Dim800x480x160 As Int: Dim800x480x160 = 3 ' 7" tablets
   Dim Dim1280x800x160 As Int: Dim1280x800x160 = 4 ' 10" tablets
   Dim LayoutVal As LayoutValues
End Sub

Sub Activity_Create(FirstTime As Boolean)
   '''''''''''''''''
   'Set Device Type'
   '''''''''''''''''
   LayoutVal = GetDeviceLayoutValues   
      Dim Dens As Float
     Dens = Density
      
      If LayoutVal.Width >= 1280 AND Dens = 1 Then
      
         DeviceType = Dim1280x800x160
        
      Else If LayoutVal.Width > 599 Then
      
         If Dens = 1.5 Then
        
            DeviceType = Dim800x480x240
          
         Else
        
            DeviceType = Dim800x480x160
          
         End If
        
      Else
      
         DeviceType = Dim480x320x160
        
      End If

End Sub

from Designer - Basic4android Wiki ...though it is modified.

I want to make my app compatible with as many devices as possible and I see in the abstract designer there are the following other landscape layouts (my project is landscape) available:

Nexus One: 800x480x240 1.5 dens
HTC Wildfire: 320x240x120 .75 dens
HTC Sensation / Evo 3D: 960x540x240 1.5 dens
Galaxy Note: 1280x800x320 2 dens
Galaxy Nexus: 1196x720x320 2 dens

Do I need to add those all to my layout variants in order for my app to work on those devices? If so, how would I fit them into the above code?
 
Last edited:

nfordbscndrd

Well-Known Member
Licensed User
Longtime User
As noted on the Wiki page where you got the code:

"While a layout can be designed with relative size specifications which will allow Android to automatically adjust the layout for devices of different sizes and resolutions, many applications require more specific placement of components of the layout for best results, resulting in anywhere from 3 to 8 variants of the original layout."

The Nexus One (800x480x240) is already covered by the code under "If LayoutVal.Width > 599", but the rest of the devices you listed may (or may not) require individual layout variants, depending on the complexity of your app's layout(s).
 
Upvote 0

PharCyDeD

Active Member
Licensed User
Longtime User
Yeah, I figured as much. I am making a game so placement is extremely important so it looks like I am going to have to do some extra layout coding. Would this code work to assign things properly?

B4X:
If LayoutVal.Width >= 1280 Then
       
      If Dens = 1 Then
      
         DeviceType = Dim1280x800x160 '10inchtab
          
      Else
         
         DeviceType = Dim1280x800x320 'Galaxy Note
        
      End if
            
       Else If LayoutVal.Width = 1196 Then
      
         DeviceType = Dim1196x720x320 'Galaxy Nexus
         
      Else If LayoutVal.Width = 960 Then
      
         DeviceType = 960x540x240 'HTC Sensation / Evo
      
      Else If LayoutVal.Width > 599 Then
       
          If Dens = 1.5 Then
          
             DeviceType = Dim800x480x240 'Nexus One
             
          Else
          
             DeviceType = Dim800x480x160 '7" tablets
             
          End If
          
       Else If LayoutVal.Width = 480 Then
       
         DeviceType = Dim480x320x160 '4" low res phones
        
      Else
         
         DeviceType Dim320x240x120 'HTC WildFire
      
          
       End If
 
Upvote 0

nfordbscndrd

Well-Known Member
Licensed User
Longtime User
...Would this code work to assign things properly?
...

No. First of all, the code will not execute at all because you have an End If line directly ahead of an Else If line.

But more to the point -- from the code you have quoted from the Wiki, you left out the most important part, which is loading the layouts. The variable names you are setting up are ones that I use in various parts of the program when I need to know the device size.

Just to give you a general idea of how I adjust code for various device sizes and resolutions, below is small portion of the code in the Activity_Create sub of my CardShark Spades app in which the placement and size of views are adjusted. I'm not expecting this code to be directly usable in your app -- just giving you an idea of the complexity involved.

B4X:
If LayoutWidth = 1280 Then
      LeftMargin = C1.Left
   Else
      LeftMargin = CardWidth
   End If
   
   OffsetVertical = (Activity.Height - 20 - CardHeight) / 12
   CardTop = Activity.Height - CardHeight
   ' Calculate how much of each of the player's 13 cards will fit onscreen: 
   i = Activity.Width - LeftMargin * 2 - CardWidth ' last card is shown full
   Offset = i / 12  
   ' If offset is not an even number, a gap will be left on the right
   ' end of the cards, so divide that gap between the left and right:
   j = 12 * Offset + LeftMargin * 2 + CardWidth
   LeftMargin = LeftMargin + (Activity.Width - j) / 2
   
   scrnCenter = Activity.Width / 2
   labelCardsOut.Left = scrnCenter - labelCardsOut.Width/2
   ExplainPanel.Left = scrnCenter - ExplainPanel.Width/2
   explainRight = ExplainPanel.Left + ExplainPanel.Width
   i = labelWinner2.Left - labelWinner1.Left 
   labelWinner1.Left = scrnCenter - labelWinner1.Width/2
   labelWinner2.Left = scrnCenter - labelWinner2.Width/2 + i
   labelHiGameScore.Left = scrnCenter - labelHiGameScore.Width/2 
   labelHiGameScore.Top = Activity.Height - labelHiGameScore.Height * 2
   labelHiGameScore.Visible = False
   
   If LayoutWidth <> Activity.Width Then
      AdjustLeft = (LayoutWidth - Activity.Width) / 2
      btnOptions.Left = btnOptions.Left - AdjustLeft * 2 ' Get out of the way of East's cards
      btnHelp.Left = btnHelp.Left - AdjustLeft * 2
      btnHint.Left = btnHint.Left - AdjustLeft ' re-center from here down
      btnOkay.Left = btnOkay.Left - AdjustLeft 
      OptionsPanel.Left = OptionsPanel.Left - AdjustLeft
      If OptionsPanel.Left < 0 Then OptionsPanel.Left = 0
      PlayerNums.Left = PlayerNums.Left - AdjustLeft   
      ScorePanel.Left = ScorePanel.Left - AdjustLeft
      panelCards.Left = panelCards.Left - AdjustLeft
      panelKeyboard.Left = panelKeyboard.Left - AdjustLeft
      
      labelDetail0.Left = labelDetail0.Left - AdjustLeft ' These are the score detail labels
      labelDetail2.Left = labelDetail2.Left - AdjustLeft
      ' LabelDetail1: center between CardWidth and explainPanel.Left
      labelDetail1.Left = CardWidth + (ExplainPanel.Left - CardWidth)/2 - labelDetail1.Width/2
      ' LabelDetail3: center between ExplainPanel and cards
      cardsLeft = Activity.Width - CardWidth 'This line and the one above must come before the next 2.
      labelDetail3.Left = ExplainRight + (cardsLeft - ExplainRight)/2 - labelDetail3.Width/2
      If labelDetail3.Left > explainRight Then labelDetail3.Left = explainRight
   End If
   
   If panelCards.Left + panelCards.Width > Activity.Width - CardWidth Then
      panelCards.Left = Activity.Width - CardWidth - panelCards.Width
   End If
   
   ' WebView Help file viewer:
   If DeviceType = Dim800x480x240 Then
      HelpFile = "spades_help_small.htm"
   Else   
      HelpFile = "spades_help.htm"
   End If
   panelWebView.SetLayout(0, 0, Activity.Width, Activity.Height)
   ViewHelp.SetLayout(0, btnSearchAgain.Height + 2, Activity.Width, Activity.Height - btnSearchAgain.Height - 2)
   ViewHelp.LoadURL("file:///android_asset/" & HelpFile)
   btnWebViewExit.Left = Activity.Width - btnWebViewExit.Width - 1
   btnWebViewBack.Left = btnWebViewExit.Left - btnWebViewBack.Width - 5
   panelWebView.Visible = False
   
   ' Score panel:
   labelNameS.Left = scrnCenter - labelNameS.Width/2
   labelNameN.Left = scrnCenter - labelNameN.Width/2
   labelNameW.Left = CardWidth
   labelNameE.Left = Activity.Width - CardWidth - labelNameE.Width
   
   labelNameS.Top = Activity.Height - CardHeight - labelNameS.Height
   labelNameN.Top = CardHeight
   labelNameW.Top = (Activity.Height - labelNameW.Height)/2
   labelNameE.Top = (Activity.Height - labelNameE.Height)/2
      
   If DeviceType = Dim800x480x240 Then labelNameS.Visible = False ' no room
      
   labelTrickNum.Left = btnOptions.left + 5
   labelTime.Left = labelTrickNum.Left
   labelBattery.Left = labelTrickNum.Left
   
   ' Adjustment for tablets whose menu bar is at the bottom of the screen in landscape mode:
   If LayoutHeight <> Activity.Height Then
      AdjustUp = (LayoutHeight - Activity.Height) / 2 ' This could be negative for a taller screen, like a 4:3 aspect ratio
      ExplainPanel.Top = ExplainPanel.Top - AdjustUp
      ScorePanel.Top = ScorePanel.Top - AdjustUp
      PlayerNums.Top = PlayerNums.Top - AdjustUp
      labelDetail1.Top = labelDetail1.Top - AdjustUp
      labelDetail3.Top = labelDetail3.Top - AdjustUp
      panelCards.Top = panelCards.Top - AdjustUp
   End If
   
   labelDetail0.Top = Activity.Height - CardHeight - labelDetail0.Height
   panelKeyboard.Top = Activity.Height - panelKeyboard.Height - 1

   i = labelWinner2.Top - labelWinner1.Top
   labelWinner1.Top = CardHeight + (ScorePanel.Top - CardHeight - labelWinner1.Height) /2
   labelWinner2.Top = labelWinner1.Top + i

   DoEvents
   labelReplayFile.Left = scrnCenter - labelReplayFile.Width/2
   labelReplayFile.Top = ExplainPanel.Top + ExplainPanel.Height
   btnHint.Top = labelReplayFile.Top + labelReplayFile.Height 
   btnOkay.Top = btnHint.Top
   btnGeneral.Top = btnHint.Top
   btnGeneral.left = (Activity.Width - btnGeneral.Width) / 2
   labelCardsOut.Top = ExplainPanel.Top - labelCardsOut.Height
   If labelCardsOut.Top < labelNameN.Top + labelNameN.Height Then
      labelCardsOut.Top = labelNameN.Top + labelNameN.Height + 5
   End If

   btnOkayTop = btnOkay.Top
   btnOkayLeft = btnOkay.Left
   btnHelpTop = btnHelp.Top
   btnHelpLeft = btnHelp.Left
   
   If panelCards.Top + panelCards.Height > btnOkay.Top Then
      panelCards.Top = btnOkay.Top - panelCards.Height - 5
   End If
 
Upvote 0

PharCyDeD

Active Member
Licensed User
Longtime User
The 'End If' you are referring too was there in the example code on wiki as well. It just lost its indentation in the pasting process. It should look like this:

B4X:
If LayoutVal.Width >= 1280 Then

   If Dens = 1 Then

   DeviceType = Dim1280x800x160 '10inchtab

   Else

   DeviceType = Dim1280x800x320 'Galaxy Note

   End If
   
Else If LayoutVal.Width = 1196 Then

   DeviceType = Dim1196x720x320 'Galaxy Nexus

Else If LayoutVal.Width = 960 Then

   DeviceType = 960x540x240 'HTC Sensation / Evo

Else If LayoutVal.Width > 599 Then

   If Dens = 1.5 Then

    DeviceType = Dim800x480x240 'Nexus One
    
   Else

    DeviceType = Dim800x480x160
    
   End If

Else If LayoutVal.Width = 480 Then

   DeviceType = Dim480x320x160

Else

   DeviceType Dim320x240x120 'HTC WildFire


End If



With that said, does the code on the wiki not work because of this? I have created layouts with the designer so everything is sized properly for each device (though this was a huge pain to do). All I need is to be able to do things like:

B4X:
If DeviceType = Dim1280x800x160 Then

Do code for this device here

End If

...

etc.

In your code are you just mathematically building layouts on the fly?
 
Upvote 0

nfordbscndrd

Well-Known Member
Licensed User
Longtime User
Here is the code in the Wiki:


B4X:
   If LayoutVal.Width >= 1280 AND Dens = 1 Then
      LayoutWidth = 1280
      Activity.LoadLayout("1280x800x160")
      DeviceType = Dim1280x800x160
   Else If LayoutVal.Width > 599 Then
      LayoutWidth = 800
      If Dens = 1.5 Then
         Activity.LoadLayout("800x480x240")
         DeviceType = Dim800x480x240
      Else
         Activity.LoadLayout("800x480x160")
         DeviceType = Dim800x480x160
      End If
   Else
      LayoutWidth = 480
      Activity.LoadLayout("480x320x160")
      DeviceType = Dim480x320x160
   End If

Compare this to your code -- you have left out all the Activity.LoadLayout(...) lines. The lines that say "DeviceType = ..." are not even necessary unless you want to reference the device type later, but they do little related to setting up the screens.

This answers your question of whether I'm building layouts on the fly, since in the code which you left out, I'm loading the appropriate layout.

What I'm doing with the code in my prior message is fine-tuning the position and sizes of the views in the selected layout.

It is not feasible to have a layout for the Activity.Width and Height of every device (since new devices come out all the time), so what you have to do is create layouts of the primary screen sizes and densities in Designer, then adjust them to the actual device sizes in your code.
 
Upvote 0

PharCyDeD

Active Member
Licensed User
Longtime User
Yeah I am re-adding the loadlayout code, but I do need to reference the size of the device again later. I have objects in my app that move so the .left .top dimensions will change. I need to reference them later for this reason. Once I re-add the LoadLayout("insert layout here") code will my above code correctly assign the layouts?
 
Upvote 0
Top