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

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

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

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: 120
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

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

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

johnaaronrose

Active Member
Licensed User
Longtime User
Thanks, Klaus, particularly your patience with me.

I've amended the app a little more. On the main layout, the 2 panels are now in 1 panel (named PanelBoth) so as to prevent them separating. All the Panels are now 10 pixels away from the left & right sides as previously it made them a little difficult to read. So all the Panels are 300 pixels in width. Both Panel1 & Panel2 have their right hand Labels & ImageViews anchored to the right horizontally of their respective Panels: however, at runtime those views are a longer distance than I expected from the right hand side of my 720x1560scale=2 phone. I feel that it must be obvious why that is but I don't see why. Can you explain why?

I expected the photo (in the ImageView) on the step layout to be scaled up appropriately on my phone from 240 pixels width and 180 pixels height i.e. a 4x3 aspect photo. However, it seems to be that width but much bigger in height (I guess at over 300 pixels high on my 720x1560scale=2 phone). Can you explain why?
 

Attachments

  • PaintingCourses.zip
    121 KB · Views: 126
Last edited:
Upvote 0

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

johnaaronrose

Active Member
Licensed User
Longtime User
On the main layout:
I've anchored PanelBoth horizontally central. I've also done the PanelBoth.HorizontalCenter = 50%x. However, looking at the 6 ImageViews: 1,3,4,6 are the same size and seem to be 4:3 aspect; but 2 & 5 are wider but of the same height as the others.

On the step layout:
I agree with you about the width of the ImageView (i.e. = ScreenWidth-Left-RightEdgeDistance=320-40-40=240) but disagree with you about the ImageView (i.e.=ScreenHeight-Top-BottomEdgeDistance=480-150-150=180). Am I correct or wrong?
I've anchored the ImageView horizontally & vertical as centered. I've put this code into its Script-General:
B4X:
ImageViewStep.Height = ImageViewStep.Width * 0.75
ImageViewStep.HorizontalCenter = 50%x
I've ended up with on my phone with the ImageView's Width as 5.1cm and its Height as 4.0cm. This is almost exactly an aspect of 4:3 which is what I wanted. Only minor quibble is that it could be wider and also have a larger height but still preserving the 4:3 aspect. So i'll do that next.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
I've anchored PanelBoth horizontally central.
What do you mean with this ?
I suppose that you anchored PanelBoth to Both and not Left.
ImageViewStep2 and ImageViewStep5 are also anchored to both and become wider.
Set the anchor of PanelBoth to Left.

For the ImageViewStep height.
I set the anchors to Left and Top to display the Height and got 130dip.
This means that on a standard screen the height will be 130dip.
Maybe on your device you get 180dip.
If you set the horizontal anchor of ImageViewStep to Both, and the margin on both sides are the same, no need to set HorizontalCenter.

Only minor quibble is that it could be wider and also have a larger height but still preserving the 4:3 aspect.
As long as the aspect ratio of the images is 4:3 they will be displayed correctly.
 
Upvote 0

johnaaronrose

Active Member
Licensed User
Longtime User
By creating a layout for 360x480 phone and putting a panel on the whole of the layout, it shows that that panel is 360x430. So 50 pixels/dip is allocated to the Title bar and the Android bottom views.
 
Upvote 0
Top