Android Tutorial Supporting multiple screens - tips and best practices

Status
Not open for further replies.
This is an old tutorial. I recommend to instead watch the visual designer video tutorial: https://www.b4x.com/etp.html

There are several features in B4A that help you target Android phones and tablets with different screen sizes and resolutions. The purpose of this page is to collect tips and best practices that will help you create flexible layouts.

If you are not familiar with the designer script feature then please start with this tutorial: Designer Scripts Tutorial

- 'dip' units
It is very simple. You should always use 'dip' units when specifying the size or position of a view (control). This way the view's physical position and size will be the same on any device.
This is correct for both regular code and designer script.
B4X:
Button1.Width = 100 'WRONG!
Button1.Width = 100dip 'Good job!
Note that text size is measured in physical units. So you should not use 'dip' units with text size values.

- Use few layout variants
It is easy to create many variants. However it is very difficult to maintain a layout made of many variants. You should use the designer script feature and the anchoring feature to adjust your layout instead of creating many variants.

- Understand the meaning of scale (dots per inch)
There are many questions starting with "I have a device with 480x800 screen...". There is no meaning to these dimensions without the scale value.

A scale of 1.0 means that there are 160 dots (pixels) per inch.
The scale values can be one of the following values: 0.75, 1.0, 1.33, 1.5 and 2.
Most phones today have a scale of 1.5 (160 * 1.5 = 240 dots per inch) or 2.0.
Most tablets have a scale of 1.0.

- "Normalized" variants
Normalized variants are variants with a scale of 1.0.
The layout you create with the designer is scaled (not stretched or resized) automatically. This means that the layout will look exactly the same on two phones with the same physical size. The scale doesn't matter.
It is highly recommended to work and design your layout with normalized variants only.
For example a variant of 480x800, scale=1.5 matches the normalized variant: 320x533, scale=1.0 (divide each value by the scale value). Now it is easy to see that this device is slightly longer than the "standard" variant: 320x480, scale=1.0.

- Scaling strategy

Use the anchoring feature to anchor the views to their parents.
See this video example: Designer anchors - Video example
And: https://www.b4x.com/android/forum/threads/64112

Decide which views should be anchored and which views should "fill" the available space.

You can also use the designer script to make a view fill the available space:

This is done with SetTopAndBottom and SetLeftAndRight methods.
B4X:
'Make an EditText fill the available height between two buttons:
EditText1.SetTopAndBottom(Button1.Bottom, Button2.Top)

'Make a Button fill the entire PARENT panel:
Button1.SetLeftAndRight(0, Parent1.Width)
Button1.SetTopAndBottom(0, Parent1.Height)

Starting from v3.20 you can set the vertical or horizontal (or both) anchor to BOTH to achieve the same result.

- How to change the views size and text size?
Larger devices offer a lot more available space. The result is that even if the physical size of a view is the same, it just "feel" smaller.
Some developers use %x and %y to specify the views size. However the result is far from being perfect. The layout will just be stretched.
The solution is to combine the "dock and fill" strategy with a smart algorithm that increases the views size and text size based on the running device physical size.

Basic4android v2.20 introduces three new keywords that help with scaling the views size and text size:
AutoScale - Scales the specified view. The scale size, position and text size will be scaled based on the device physical size compared to the chosen variant size.
Example:
B4X:
AutoScale(Button1)
AutoScaleAll - Scales all layout views.
AutoScaleRate - Sets the scale rate. This is a number between 0 to 1. The default value is 0.3.
A value of 0 means no scaling at all.
Value of 1 means that the scale factor is exactly proportional to the device physical size. The result is a "stretched" UI.

The recommended process is to first scale all views and then adjust their positions as required.

If done properly this saves the need to create many variants. Your layout will look good on all devices.

Test your layout

You can test your layout with a real device, an emulator, the abstract designer and the UI Cloud service (Tools - Send to UI Cloud).
 
Last edited:

klaus

Expert
Licensed User
Longtime User
You multiply by cScaleX, I did it (instinctively!) for a factor Y.
The reason why I multiply by ScaleX instead of ScaleY is depending on the heigt / width ratio, ScaleY can be bigger than ScaleX. If you mutiply by ScaleY you have the risc that the text doesn't fit anymore in the views width and you'll get two lines.
But It should be lbl.TextSize = lbl.TextSize * Min(cScaleX, cScaleY).
Replace in the Scale module line 211 by the line above.

When you use SetReferenceLayout the ScaleRate is automatically set to 1.
 

LucaMs

Expert
Licensed User
Longtime User
The reason why I multiply by ScaleX instead of ScaleY is depending on the heigt / width ratio, ScaleY can be bigger than ScaleX. If you mutiply by ScaleY you have the risc that the text doesn't fit anymore in the views width and you'll get two lines.
But It should be lbl.TextSize = lbl.TextSize * Min(cScaleX, cScaleY).
Replace in the Scale module line 211 by the line above.

When you use SetReferenceLayout the ScaleRate is automatically set to 1.

i'll try to modify line 211, ok, i understood, but you set lbl.TextSize in other subs too...
perhaps it would be better to use a variable as cScaleTxt and initialize it in the same place of cScaleX, cScaleY ... ?

P.S. I had forgotten that I have already done the test, using: cScaleX, cScaleY and (cScaleX cScaleY +) / 2 ... none of these is sufficient.

setting min(...) is equal to select cScaleX or cScaleY
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
upload_2013-12-1_0-3-32.png


upload_2013-12-1_0-3-52.png
 

Attachments

  • upload_2013-12-1_0-3-6.png
    upload_2013-12-1_0-3-6.png
    52.4 KB · Views: 539
  • upload_2013-12-1_0-50-40.png
    upload_2013-12-1_0-50-40.png
    363.3 KB · Views: 586
Last edited:

klaus

Expert
Licensed User
Longtime User
The default properties are different in emulators for different Android versions and also on different devices.
Attached you find the result of an emulator on my computer for a 480_600_240_API10 which looks different than yours !?
I also tested the TableV1_29 program like in your image on my Nexus One Android API 10 and on an API10 Emulator the default text size on the device is 14 and in the emulator it's 18 !?
I can't take into acount these differences in the scaling routines.
 

Attachments

  • Emul_480_600_240_API10.jpg
    Emul_480_600_240_API10.jpg
    53.3 KB · Views: 578

LucaMs

Expert
Licensed User
Longtime User
The default properties are different in emulators for different Android versions and also on different devices.
Attached you find the result of an emulator on my computer for a 480_600_240_API10 which looks different than yours !?
I also tested the TableV1_29 program like in your image on my Nexus One Android API 10 and on an API10 Emulator the default text size on the device is 14 and in the emulator it's 18 !?
I can't take into acount these differences in the scaling routines.


In your 480... textsize is better, but not perfect (bottom of "Aggiungi").

However, since we have not found a solution ... I wonder how everyone else is doing, including big software house!

I'm trying to adapt further in relation to the relationship lbl.textsize / lbl.Height (using various tricks).
But I should know if the text is laid out on more than one line, in the view. Can you help me about this?

But the strange thing is that it seems that it is only me to complain about this problem!
 

moster67

Expert
Licensed User
Longtime User
Even if I knew the property value, I don't know what to do with it because I don't know what the developper nor the user really want.
So for me it's up to the developper to take care of this.

Klaus, by all means, my point was not meant for you. It was just, as you say, a suggestion for the developer to take into consideration since you with your module cannot cover it all.
 

LucaMs

Expert
Licensed User
Longtime User
Even if I knew the property value, I don't know what to do with it because I don't know what the developper nor the user really want.
So for me it's up to the developper to take care of this.


As a developer, I would "simply" this (resized image using IrfanViewer):
upload_2013-12-1_13-13-28.png


I do not want that B4A develops my app following my voice commands! (or maybe yes? :) )
 

LucaMs

Expert
Licensed User
Longtime User
@moster67

You wrote:
"The other day I received a report (along with screenshots) from a user saying that certain labels on his Galaxy S3 were truncated or simply did not show up correctly. I found this rather odd since my developer-phone is also a Galaxy S3 and of course I had made sure that everything (my layouts) looked OK, not only on my S3, but also in other resolutions."

I have not read the whole thread, but ...
how you sized texts, in other resolutions? This is the question.
 

moster67

Expert
Licensed User
Longtime User
@LucaMs

Everything is not "magic" - there is no universal formula in my opinion, especially with Android and all the resolutions available and great modules, such as the one by Klaus or the built-in script cannot cover them all.

Many times I simply add specific layouts for different resolutions. Then with help of the UI-cloud offered by B4A, I test my layouts on different devices and I also take note which layout is being used (you can see that in the web-page generated by UI-cloud in B4A) and then I adapt my code/my specific layout.
 

LucaMs

Expert
Licensed User
Longtime User
@LucaMs

Everything is not "magic" - there is no universal formula in my opinion, especially with Android and all the resolutions available and great modules, such as the one by Klaus or the built-in script cannot cover them all.

Many times I simply add specific layouts for different resolutions. Then with help of the UI-cloud offered by B4A, I test my layouts on different devices and I also take note which layout is being used (you can see that in the web-page generated by UI-cloud in B4A) and then I adapt my code/my specific layout.


... "manually"... ok, thanks.
 

moster67

Expert
Licensed User
Longtime User
... "manually"... ok, thanks.

Purtroppo sì - si deve smanettare un po'....

That said, I am very pleased with the design-script and although I have not tried Klaus' module, I am sure it generates nice results as well, perhaps with even more flexibility. I think what generated by the design-scripts gives satisfactory results in at least 95% of the cases. When there is a discrepancy, I will make a specific layout.

Remember that you can regenerate the layout by using activity.RerunDesignerScript, perhaps after obtaining some needed information by code regarding the device.

Although I have not tried it but if you prefer the Android-way of building layouts using XML-files, I believe you can now also use Erel's XMLLayoutBuilder-library (http://www.b4x.com/android/forum/threads/xmllayoutbuilder-load-xml-layouts.33762/). However, personally I prefer design-scripts which is a huge time-saver and gets good results in most cases.

Just my 2 cents :)
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I still don't understand why you want to create such a layout:

upload_2013-12-1_13-13-28-png.20906


The user expects to see more content in a tablet. There is no reason to create huge buttons, huge images and so on. The physical size of the text, buttons and the other views should be more or less similar. It doesn't matter if the user is holding a phone or a tablet.

AutoScaleAll does help by slightly increasing the values for larger tablets.
 

LucaMs

Expert
Licensed User
Longtime User
Purtroppo sì - si deve smanettare un po'....

That said, I am very pleased with the design-script and although I have not tried Klaus' module, I am sure it generates nice results as well, perhaps with even more flexibility. I think what generated by the design-scripts gives satisfactory results in at least 95% of the cases. When there is a discrepancy, I will make a specific layout.

Remember that you can regenerate the layout by using activity.RerunDesignerScript, perhaps after obtaining some needed information by code regarding the device.

Although I have not tried it but if you prefer the Android-way of building layouts using XML-files, I believe you can now also use Erel's XMLLayoutBuilder-library (http://www.b4x.com/android/forum/threads/xmllayoutbuilder-load-xml-layouts.33762/). However, personally I prefer design-scripts which is a huge time-saver and gets good results in most cases.

Just my 2 cents :)


I understood only: "Purtroppo sì - si deve smanettare un po'...." (compliments :) )

I will try to follow your advice.

My main problem is laziness: I'm afraid I'll have to recreate my layouts (v.1.80) and also some suited to the various resolutions.

The strange thing is that the difference Klaus pointed out: "same" emulator, etc..
In addition, there is the problem Holo Light / Dark, and as usual, I read too quickly and not in my language, but i knew that regards the API 11.

Moreover, "when" I'll have solved the graphics problems, I expect those of db data pseudo-synchronization and then export Mobile to PC.
I'll announce the publication of my first app in 2025 ;)

Thanks for your interest.

Regards
 

dexMilano

Active Member
Licensed User
Longtime User
Hello all,
I've a stupid problem related to multiresolution application: having different icons of the launcher on different device.
I want to have an icon 48x48 for 1.0 scaling and another for 1.5 scaling (it should be 72x72).
In the Android iconography page it is described bu I don't know how to do with B4A.
Thanks in advance.

dex
 
Status
Not open for further replies.
Top