Android Question My phone's Variants in Visual Designer

johnaaronrose

Active Member
Licensed User
Longtime User
Currently, I'm only interested in developing for Android. I'm converting old apps developed with B4A to B4XPages. I'm developing a new apps with B4XPages. All being done with B4A 11.20.
My phone's specification is 720 pixels wide by 1560 pixels height. It has 320 dpi i.e. scale=2.
I have therefore defined a Portrait Variant in Visual Designer as 720x1560 with Scale=2.0: however, Visual Designer objects to this saying that a scale of greater than 1.0 may lead to errors, also I've seen in the documentation (I forget where) that the recommendation is to have scale=1.0. Does this matter? If so, what should I define the Variant as? I have viewed the Visual Designer tutorial and found it confusing in this matter. Similarly, for the Visual Designer booklet.

In my new app, I have noticed that ToastMessageShow of a GetLayoutValues variable shows it as 0x0,scale=0, dpi=0 after loading the layout and even after waiting 10 seconds! Why is this?
B4X:
Root.LoadLayout("Main")
    Sleep(5000)
    Dim GetLayoutValues As LayoutValues
    ToastMessageShow(GetLayoutValues, True)
    Sleep(5000)
    ToastMessageShow("100%X=" & 100%X & ", 100%Y=" & 100%Y, True) 
    Sleep(5000)
    ToastMessageShow(GetLayoutValues, True)

However, ToastMessageShow of 100%X shows 720 but 100%Y shows 1394. I presume that the difference of 166 pixels in height (versus the 1560 of the phone's specification) is due to the top (title) bar and the bottom (3 Android 'buttons') bar, though I don't know how much vertical space each bar occupies (how do I find that out?). Should I therefore NOT put any Views in the vertical space occupied by these bars?

Looking at the Designer booklet, it recommends having a different Variant for each of Portrait & Landscape. But it doesn't say how to select the appropriate one at runtime. Could this be something like:
B4X:
If 100%X < 100%Y then
    Root.LoadLayout("MainPortrait")
Else
    Root.LoadLayout("MainLandscape")
End If
Years ago, I used to use the SetLayout command (now SeLayoutAnimated with first parameter=0 for a View coded as B4xView), in code after a layout was loaded, to set the position & size of Views by something like:
B4X:
LabelStep1.SetLayout(Round2(0%X, 0), Round2(53.0846%Y, 0), Round2(33.3333%X, 0), Round2(5.7389%Y, 0))
where the numbers before the before %X & %Y were calculated on a spreadsheet as a percentage of the various position & size parameters (i.e. Left, Width, Top, Height) of each View relative to the phone's width & height appropriately: that method was suggested by someone in a post about his ProbCalc B4A project. This is similar to the AutoScale function on page 87 of the Visual Designer booklet with the AutoScaleRate=1.0. The Visual Designer booklet refers to "The AutoScale function is based on the standard variant (320 x 480, scale = 1.0)." which seems like a phone that very few people would have nowadays.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I don't recommend using variants at all. If you do use then use as few as possible.
If you are using B4XPages then the app orientation will be locked anyway.

The designer should normalize the variant parameters for you. It should be: 360x780, scale=1.

Looking at the Designer booklet, it recommends having a different Variant for each of Portrait & Landscape. But it doesn't say how to select the appropriate one at runtime. Could this be something like:
The best matching variant is chosen automatically.
 
Upvote 1

agraham

Expert
Licensed User
Longtime User
Conclusion is that the low side of the bottom most View in a layout should be more than than 100%Y/2. Is that correct?
No. If I understand correctly you are comparing apples to oranges. The Designer normally uses a normalised scale of 1, at runtime it looks like your device scale is about 2 so the layout values will be doubled when the views are drawn. Don't worry about runtime pixels when laying out views. Don't overlook using anchors and scripting to make the layout work on different sizes and pixel density devices.
orientation can be decided when the app initially starts to run. Is that so?
No. Defining the orientation as unspecified will allow Android to rotate your app while it is running which will do bad things to the user experience.
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
having top of 30 for the ImageViews with anchoring upwards, the Button with bottom edge of 0 and anchoring of down
Be aware that the upper three Labels and InmageViews are on a Panel and this Panel is anchored to bottom.
The same for the second set.

Would it be reasonable to have the BBCodeView have a top of 0 with anchoring upwards in order to always have that view just underneath the title bar?
You can set any Top value different from 0 to insert a small gap on top.

I would like to also increase the height of that view (i.e. BBCodeView) as on my phone it has a big gap from the bottom of that view to the first set of 3 Labels.
This is already done !
The BBCodeViewMe object is anchored top and bottom, this does the automatic height adaptation.
You see a big gap because the text is short.
Set a different background color for BBCodeViewMe and you will see it.
 
Last edited:
Upvote 1

klaus

Expert
Licensed User
Longtime User
The anchors depend on the screen size.
In your case, PanelBoth is anchored to the left.
Then, the standard screen width is 320dip, but the width of your device 360 (720 / 2).
Therefore, you have a bigger space at the right side.
I suppose that you want to keep the width / height ratio of the ImageViews.

You can center PanelBoth in the Designer Script:

1648197760198.png


On the step layout I checked the width and height.
You have 240dip in width, but 130dip in height and not 180 as you mention.
Then, you anchor to both vertically and horizontally this means that you stretch the ImageView according to the device screen width and height.
This can change the width / height ratio of the ImageView when the screen width / height ratio of the device is different from the standard screen.
Here too, set the width to 240, the height to 180 and the anchors to left and top and center the ImageView like above.
Or, if you want to adapt the dimensions of the ImageView for bigger screens you could also calculate the dimensions and position in the Designer Script.
As a first step you could anchor the ImageView to both horizontally, to top vertically and calculate the height.

1648198603173.png
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
Uncomment AutoScaleAll in the DesignerScript like:
B4X:
AutoScaleAll
PanelBoth.HorizontalCenter = 50%x

You can also play with the autoscale rate like:
B4X:
AutoScaleRate(0.6)
AutoScaleAll
PanelBoth.HorizontalCenter = 50%x
The default AutoScaleRate is AutoScaleRate(0.3).
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
They are increased but not as much as you expect.
Have you tried to add this line as suggested in post #23 ?
AutoScaleRate(0.6)
This sets the scale factor, for all Views. With 0.6 the text on top might be too big.
You can set the scale rate to 0.5 for a compromise.
If you really want to keep the text on top smaller and the images bigger you need to add code in the Designer Script.
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
When you comment these two lines:
B4X:
PanelBoth.HorizontalCenter = 50%x
'Panel1.HorizontalCenter = 50%x
'Panel2.HorizontalCenter = 50%x
Does it look OK?
If it is not satisfactory for you, show a screenshot of the result.
Then you probably need to readjust the views in the Designer Script.
 
Upvote 1

klaus

Expert
Licensed User
Longtime User
Attached your project modified.
I removed the two Panels leaving only PanelBoth.
Be aware that the Gravity for ImageView declared as a B4XView is set to CENTER not to FILL like in the Designer.
I set the upper row to ImageView and left the second row As B4XView so you see the difference.
 

Attachments

  • PaintingCoursesNew.zip
    122.4 KB · Views: 118
Upvote 1

johnaaronrose

Active Member
Licensed User
Longtime User
I don't recommend using variants at all. If you do use then use as few as possible.
If you are using B4XPages then the app orientation will be locked anyway.

The designer should normalize the variant parameters for you. It should be: 360x780, scale=1.


The best matching variant is chosen automatically.
I now have 1 variant, i.e. 360x780, scale=1 as you suggested. There is a BBCodeView with Left=0,Top=0,Width=360,Height=310. At runtime it is displayed directly underneath (i.e. touching) the title bar. However, I have the lowest View (which is a Button) touches the bottom bar (of the 3 standard buttons): it has Left=0,Top=660,Width=360,Height=40. Thus its bottom edge is at 700 dpi i.e. 80dpi or 160 pixels from the bottom of the screen). As I said in my first post, 100%Y=1394 (i.e. 166 pixels less that the phone screen's actual height): that seems to explain why the Button is touching the bottom bars. Conclusion is that the low side of the bottom most View in a layout should be more than than 100%Y/2. Is that correct?
Using B4XPages, you say that the"app orientation is locked". I understand that the app's orientation cannot be changed as the app is running. Since the orientation can be defined as unspecified in the Main module, it would imply that the orientation can be decided when the app initially starts to run. Is that so?
 
Last edited:
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
No. If I understand correctly you are comparing apples to oranges. The Designer normally uses a normalised scale of 1, at runtime it looks like your device scale is about 2 so the layout values will be doubled when the views are drawn. Don't worry about runtime pixels when laying out views. Don't overlook using anchors and scripting to make the layout work on different sizes and pixel density devices.

No. Defining the orientation as unspecified will allow Android to rotate your app while it is running which will do bad things to the user experience.
The basic problem is that the actual screen height of 1560 pixels at runtime (i.,e. 780 units when the layout is designed as the scale is 2) is more than 100%Y due to the actual screen containing the title bar & the bottom bar. So if the layout goes too near the bottom of the layout, it results in the bottom-most View touching/overlapping the Android bits at the bottom.
 
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
I've tried using anchors e.g. to anchor the bottom most view to the bottom (presumably having the downward pointing anchor on the view's properties selected?). However, if I want a reasoable gap to the next highest view what should I select for the vertical anchor (i.e. the downwards anchor or the upwards anchor)? If I use the downwards anchor it then has the bottom most view and the next highest view touching.
 
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
Klaus,
The project is small so I've posted it all. My problem refers to the Main layout loaded in B4XMaimPage. I would like there to be some space between the ButtonStart view and the ImageViewStep4 view. Generally, AFAIK there has to be a setting in each view for both the horizontal anchor & the vertical anchor. I would like the ImageViewStep4 view to have a gap between it and the ButtonStart view: at the moment they touch on my 720x1560 pixels phone, which on Erel's advice I have set in the Designer to 360x780 (as it's a scale=2 phone).
 

Attachments

  • PaintingCourses.zip
    120.9 KB · Views: 122
Upvote 0

Andrew (Digitwell)

Well-Known Member
Licensed User
Longtime User
Try adding this to your designer script:

B4X:
'Space the button half way between the imageview and the bottom of the screen
ButtonStart.VerticalCenter = ImageViewStep4.Bottom + (100%y-ImageViewStep4.Bottom)/2

You don't need the anchor in this case.
 
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
Attached you find a modified version.
If it does not fit your expectations you will need to use the Designer Script.
Klaus,
Thanks for that changed app. I've tried it and it does mostly what I want. I'm intrigued by the concepts in it: having top of 0 for the Labels with anchoring to upwards, having top of 30 for the ImageViews with anchoring upwards, the Button with bottom edge of 0 and anchoring of down. I never thought of doing such things.
Would it be reasonable to have the BBCodeView have a top of 0 with anchoring upwards in order to always have that view just underneath the title bar?
I would like to also increase the height of that view (i.e. BBCodeView) as on my phone it has a big gap from the bottom of that view to the first set of 3 Labels. What would be the code to cause automatic increase/decrease of that view to just have a small gap from the bottom of that view to the the first set of 3 Labels?
It seems to me that this might work on all phones and perhaps even tablets. I dislike the concept of writing an app which only works on some phones. And I particularly dislike having multiple variants.
 
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
Klaus,
I didn't realise that you had used Panels, probably because I never thought of looking at the Views Tree. I think that I'm beginning to understand how to use the Designer to write apps which will work on just about any Android phone or tablet if I specify either portrait or landscape (as desired) mode in SupportedOrientations (in the Main module) with a single chosen variant of 320x480 / 480x320 (using appropriate one) and scale=1 in the Designer.
I think that it would be a good idea to update the Designer booklet (not sure if you or Erel wrote it) with stuff like your solutions to the above as an example.
 
Upvote 0
Top