AutoScale Code Module

klaus

Expert
Licensed User
Longtime User
The AutoScale function in the Designer Scripts scales only views added in the Designer but not views added in the code.

To overcome this drawback I wrote a Scale Code module, the first version is already included in the Desiger Scripts & AutoScale Tutorial.

There are two other drawbacks :
  • the internal Labels of ListViews are not scaled.
  • with the Designer Scripts AutoScale function for some smartphone screen sizes especially the 480 x 800 scale 1.5 screen the scaling is not optimal (at least for me).
    With AutoScale on a screen with a resolution of 480 x 800 scale 1.5 (the standard screen is 320 x 480 scale 1) the views are stretched too much horizontally and not enough vertically because of the different width/height ratio.
I added in the Scale Module a new set of equations with two scale factors one for X and one for Y. For smartphone screens (< 6'') the views are scaled according to the screen width and the screen height without the rate factor. For bigger screens the scale factors are modified with the rate factor. For the big screens a rate value of 0 means no scaling and a value of 1 is equivalent to a scaling with %x and %y.

The AutoScale function in the code module scales also the internal views in ScrollViews, ListViews and scales the TextSize property of Spinners.

The Scale code module contains following functions:
  • Initialize Calculates the scale factors
  • SetRate(Rate) Sets a new Rate value and calculates the scale factors
  • ScaleView(View) Scales the given view with its child views
    with the new equations.
  • ScaleViewDS(View) Scales the given view with its child views
    with the Designer Scripts equations
  • ScaleAll(Activity, True) Scales all views of the given Activity or Panel
    with the new equations.
  • ScaleAllDS(Activity, True) Scales all views of the given Activity or Panel
    with the Designer Scripts equations
  • GetDivicePhysicalSize Gets the approximate physical size of the device
  • GetScaleDS Returns the Disigner Scripts scale factor
  • GetScaleX Returns the X scale factor
  • GetScaleX_L Returns the X scale landscape factor
    independant of the current orientation
  • GetScaleX_P Returns the X scale portrait factor
    independant of the current orientation
  • GetScaleY Returns the Y scale factor
  • GetScaleY_L Returns the Y scale landscape factor
    independant of the current orientation
  • GetScaleY_P Returns the Y scale portrait factor
    independant of the current orientation
  • Bottom(View) Returns the Bottom coordinate of the View
  • Right(View) Returns the Right coordinate of the View
  • HorizonzalCenter(View, x1, x2) Centres the View horizontally the view between two coordinates
  • HorizonzalCenter2(V1, V2, V3) Centres the View V1 horizontally between two views V2 and V3
  • VerticalCenter(View, x1, x2) Centres the View horizontally the view between two coordinates
  • VerticalCenter2(V1, V2, V3) Centres the View V1 horizontally between two views V2 and V3
  • IsActivity(View) Returns True if the View is an activity
  • IsPanel(View) Returns True if the View is a Panel
  • SetRight(View, xRight) Sets the Left propety of the view according to the given right coordinate xRight and the views Width property.
  • SetBottom(View, yBottom) Sets the Top propety of the view according to the given bottom coordinate yBottom and the views Height property.
  • SetLeftAndRight(View, xLeft, xRight) Sets the Left and Width properties of view View according to the xLeft and xRight coordinates.
  • SetLeftAndRight2(V1, VL, dxL, VR, dxR) Sets the Left and Width properties of view V1 between the views VL and VR with the given spaces dxL and dxR.
  • SetTopAndBottom(View, yTop, yBottom) Sets the Top and Height properties of view View according to the yTop and yBottom coordinates.
  • SetTopAndBottom2(V1, VT, dyT, VB, dyB) Sets the Top and Height properties of view V1 between the views VT and VB with the given spaces dyT and dyB.
  • SetReferenceLayout(Width, Height, Scale) sets a new layout as the reference layout, allows downscaling. AutoScaleRate has no influence in this case !
The project contains following activities showing different examples of the use of either Designer Scripts AutoScale or scaling with the Code Module.
Activities:
  • Main Main screen with an image and buttons.
  • Setup The setup screen from the GPSExample program.
  • About An about screen example.
  • DBWebView A database table in a WebView with a modified DBUtils version
    scaling the table text size.
  • DBScrollView A database table in a ScrollView.
  • Keyboard A keyboard with views added in the code.
  • ListView A ListView with the internal Labels and Bitmap scaled.
  • Calculator A calculator layout from the RPNCalc project without the functions
    scaled with the new equations.
  • Calculator1 Same as Calculator but scaled with the Designer Scripts equations.
  • Positioning Example with the different positioning routines.
Code modules:
  • Scale The scaling module
  • DBUtils The modified DBUtils module
If you run Calculator and Calculator1 on a 480 x 800 scale 1.5 device you'll see the difference between Designer Scripts scaling and the scaling with the new equations.

If you don't need all routines in the Scale module you can remove those not needed.
The Scale module scales also ScrollView2D views, if you don't use such a view you must comment the corresponding lines or remove them.

I think the code is enough self explanatory.

Best regards.

EDIT: 2013.09.27
Added SetReferenceLayout
Added HorizontalScrollView

EDIT: 2014.11.20
Amended error reported HERE.
 

Attachments

  • AutoScaleExample7.zip
    74 KB · Views: 2,328
Last edited:

klaus

Expert
Licensed User
Longtime User
The height is somewhat different form width because of the Top line, the Title line and the Bottom line.
The physical heights of these lines are almost the same idependant of the screen size.
On my two devices both have the same with 1920 pixels.
On my device Sony xperia Z1 scale 3
GetDeviceLayoutValues = 1080
100%Y = 930
On my Asus TF700 scale 1.5
GetDeviceLayoutValues = 1128
100%Y = 1090
So the usable height is not the same in pixels.

But anyway, if you take a given layout and use %y you don't need to bother with the pixels, %y remains a given proportion on all screens. If all properties are in % values no problem. But if you use, somewhere after scaleing, any dip value then you could get some not expected results because these values are not rescaled.
For me, using a same layout defined for a 3.5'' screen and streching it up to a 10'' screen is not a good solution. On a big screen it's a very bad use of the avalable surface.

If you setup a layout in the Designer and also add views in the code, with properties adapted to the reference layout the Scale module, with a ScaleRate of 1 does transform the layout in %x and %y values.
That was the starting point why I wrote it.

There is no built in function to convert pixels to %x nor %y.

(by the way what error did you get in doButtonListView on your device?)
Clicking in the third line on 'more' the program simply crashes.
 
Last edited:
Upvote 0

mbatgr

Active Member
Licensed User
Longtime User
It's ok.
Your code is interesting and I will try to study it, too advanced for me though!
thanks again Klaus
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
The AutoScale function in the Designer Scripts scales only views added in the Designer but not views added in the code.

To overcome this drawback I wrote a Scale Code module, the first version is already included in the Desiger Scripts & AutoScale Tutorial.

There are two other drawbacks :
  • the internal Labels of ListViews are not scaled.
  • with the Designer Scripts AutoScale function for some smartphone screen sizes especially the 480 x 800 scale 1.5 screen the scaling is not optimal (at least for me).
    With AutoScale on a screen with a resolution of 480 x 800 scale 1.5 (the standard screen is 320 x 480 scale 1) the views are stretched too much horizontally and not enough vertically because of the different width/height ratio.
I added in the Scale Module a new set of equations with two scale factors one for X and one for Y. For smartphone screens (< 6'') the views are scaled according to the screen width and the screen height without the rate factor. For bigger screens the scale factors are modified with the rate factor. For the big screens a rate value of 0 means no scaling and a value of 1 is equivalent to a scaling with %x and %y.

The AutoScale function in the code module scales also the internal views in ScrollViews, ListViews and scales the TextSize property of Spinners.

The Scale code module contains following functions:
  • Initialize Calculates the scale factors
  • SetRate(Rate) Sets a new Rate value and calculates the scale factors
  • ScaleView(View) Scales the given view with its child views
    with the new equations.
  • ScaleViewDS(View) Scales the given view with its child views
    with the Designer Scripts equations
  • ScaleAll(Activity, True) Scales all views of the given Activity or Panel
    with the new equations.
  • ScaleAllDS(Activity, True) Scales all views of the given Activity or Panel
    with the Designer Scripts equations
  • GetDivicePhysicalSize Gets the approximate physical size of the device
  • GetScaleDS Returns the Disigner Scripts scale factor
  • GetScaleX Returns the X scale factor
  • GetScaleX_L Returns the X scale landscape factor
    independant of the current orientation
  • GetScaleX_P Returns the X scale portrait factor
    independant of the current orientation
  • GetScaleY Returns the Y scale factor
  • GetScaleY_L Returns the Y scale landscape factor
    independant of the current orientation
  • GetScaleY_P Returns the Y scale portrait factor
    independant of the current orientation
  • Bottom(View) Returns the Bottom coordinate of the View
  • Right(View) Returns the Right coordinate of the View
  • HorizonzalCenter(View, x1, x2) Centres the View horizontally the view between two coordinates
  • HorizonzalCenter2(V1, V2, V3) Centres the View V1 horizontally between two views V2 and V3
  • VerticalCenter(View, x1, x2) Centres the View horizontally the view between two coordinates
  • VerticalCenter2(V1, V2, V3) Centres the View V1 horizontally between two views V2 and V3
  • IsActivity(View) Returns True if the View is an activity
  • IsPanel(View) Returns True if the View is a Panel
  • SetRight(View, xRight) Sets the Left propety of the view according to the given right coordinate xRight and the views Width property.
  • SetBottom(View, yBottom) Sets the Top propety of the view according to the given bottom coordinate yBottom and the views Height property.
  • SetLeftAndRight(View, xLeft, xRight) Sets the Left and Width properties of view View according to the xLeft and xRight coordinates.
  • SetLeftAndRight2(V1, VL, dxL, VR, dxR) Sets the Left and Width properties of view V1 between the views VL and VR with the given spaces dxL and dxR.
  • SetTopAndBottom(View, yTop, yBottom) Sets the Top and Height properties of view View according to the yTop and yBottom coordinates.
  • SetTopAndBottom2(V1, VT, dyT, VB, dyB) Sets the Top and Height properties of view V1 between the views VT and VB with the given spaces dyT and dyB.
  • SetReferenceLayout(Width, Height, Scale) sets a new layout as the reference layout, allows downscaling. AutoScaleRate has no influence in this case !
The project contains following activities showing different examples of the use of either Designer Scripts AutoScale or scaling with the Code Module.
Activities:
  • Main Main screen with an image and buttons.
  • Setup The setup screen from the GPSExample program.
  • About An about screen example.
  • DBWebView A database table in a WebView with a modified DBUtils version
    scaling the table text size.
  • DBScrollView A database table in a ScrollView.
  • Keyboard A keyboard with views added in the code.
  • ListView A ListView with the internal Labels and Bitmap scaled.
  • Calculator A calculator layout from the RPNCalc project without the functions
    scaled with the new equations.
  • Calculator1 Same as Calculator but scaled with the Designer Scripts equations.
  • Positioning Example with the different positioning routines.
Code modules:
  • Scale The scaling module
  • DBUtils The modified DBUtils module
If you run Calculator and Calculator1 on a 480 x 800 scale 1.5 device you'll see the difference between Designer Scripts scaling and the scaling with the new equations.

If you don't need all routines in the Scale module you can remove those not needed.
The Scale module scales also ScrollView2D views, if you don't use such a view you must comment the corresponding lines or remove them.

I think the code is enough self explanatory.

Best regards.

EDIT: 2013.09.27
Added SetReferenceLayout
Added HorizontalScrollView


I have a 480 x 800 scale 1.5 device and I had so many problems.
(my bad English did not allow me to understand "SetReferenceLayout").

Thank you very much, great job.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
The 'standard' scale functions are based on the standard screen size 320 x 480 x 1.
In some cases it could be useful to have another screen size as the referenc screen, this can be set with SetReferenceLayout.
In your case you could set a 480 x 800 scale 1.5 screen as the reference screen with SetReferenceLayout(480, 800, 1.5).
When you set a new reference layout the scaling is done like %x and %y no scale rate.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
The 'standard' scale functions are based on the standard screen size 320 x 480 x 1.
In some cases it could be useful to have another screen size as the referenc screen, this can be set with SetReferenceLayout.
In your case you could set a 480 x 800 scale 1.5 screen as the reference screen with SetReferenceLayout(480, 800, 1.5).
When you set a new reference layout the scaling is done like %x and %y no scale rate.

You are very kind to answer, but I am not awake to understand.

I HOPE that i understood well.

If I used your function (property, I guess) SetReferenceLayout (480, 800, 1.5) I should not worry about anything else?
Without making any other changes to the "whole" my work done?
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
If I used your function (property, I guess) SetReferenceLayout (480, 800, 1.5) I should not worry about anything else?
I would say no because it depends on what you want to display and how.
If you use SetReferenceLayout (480, 800, 1.5) and you show this layout on a 10'' screen all views will be streched according to the screen width and screen height ratios. Which, at least for me, doesn't look good. In some cases we want to show more on a big screen than on a small screen. In this case it could be better to have different layout variants for small and big screens.
I added the SetReferenceLayout function especially for two of my projects dedicated only for tablets. In this project I have one layout different from the standard one and use SetReferenceLayout. Stretching between 7'' and 10'' screens is OK.
In another project written at first only for tablets I used it too and then I wanted this application also for smartphones. To do it I have written a new project with a complete different layout because I cannot display on a small screen at the same time what I display on the big screen. As the layouts are much different their management is also different, so two projects.
Unfortunately there is no unique 'magic' principle nor method to fullfill all screen sizes with good looking layouts.
I am currently adding two new scaling methods to the module ScaleAllX and ScaleViewX because I have a new xperia Z1 and the screen width is wider than the standard screen and the height is much higher than the standard screen giving more vertical space. If all the views were streched according to the height ratios they would be stretched too much and look too heigh so I strech both directions with the width ratio.
Most of the views in my layouts are on ScrollViews to be less dependant on the height/width ratios.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
I would say no because it depends on what you want to display and how.
If you use SetReferenceLayout (480, 800, 1.5) and you show this layout on a 10'' screen all views will be streched according to the screen width and screen height ratios. Which, at least for me, doesn't look good. In some cases we want to show more on a big screen than on a small screen. In this case it could be better to have different layout variants for small and big screens.
I added the SetReferenceLayout function especially for two of my projects dedicated only for tablets. In this project I have one layout different from the standard one and use SetReferenceLayout. Stretching between 7'' and 10'' screens is OK.
In another project written at first only for tablets I used it too and then I wanted this application also for smartphones. To do it I have written a new project with a complete different layout because I cannot display on a small screen at the same time what I display on the big screen. As the layouts are much different their management is also different, so two projects.
Unfortunately there is no unique 'magic' principle nor method to fullfill all screen sizes with good looking layouts.
I am currently adding two new scaling methods to the module ScaleAllX and ScaleViewX because I have a new xperia Z1 and the screen width is wider than the standard screen and the height is much higher than the standard screen giving more vertical space. If all the views were streched according to the height ratios they would be stretched too much and look too heigh so I strech both directions with the width ratio.
Most of the views in my layouts are on ScrollViews to be less dependant on the height/width ratios.


Zeus help me :)

I understood what you wrote. I also read somewhere (maybe the Android SDK documentation) that it would be better to use the larger screen to add information, rather than enlarge the views.

But I'll explain what I meant with my previous question.

I already have a project (which is much more useful to smartphones that to tablets), for which I set a non-standard variant, 480x800 1.5-in the designer and designed all the layouts for that size.

After, I developed a function that SHOULD resize all views depending of "misures" of the other host display. Only now I realized that it is not accurate (especially for the textsize).

Now, I was hoping that your SetReferenceLayout did this: I set SetReferenceLayout 480x800 - 1.5, use Scale.ScaleAll (Activity, True) and the resizing occurs relative to my 480 instead of the 320 "standard".

However, I'm realizing that if I had made an attempt, I would not have bothered you and I would not be puzzled with English :)

I will study well your module.

Thank you so much again
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
When I load an old project in version 3.00 of B4A, I get two sections attributes: Project and Module. Everything ok, compilation included.

If i create a new project and to this I add ONLY the unique layout from the old project, I get the Project and Activity sections and, in this case, an error occurs at compile time:

Convert byte code - optimized dex. 9:17
Optimized Dexer failed. Switching to Standard Dexer.


and the layout is beyond the screen (vertically).

The layout is 480x800 - 1.5. No other variant.

If I delete the Activity Attributes from the new project, I have no compilation error but I still have one of the layout. So these things are not connected to each other.
(I suppose that the 3:00 does not recognizes the Main and then inserts a Module Attributes).

Old project, loaded into v. 3.00, creates:
B4X:
#Region  Project Attributes
    #ApplicationLabel: test
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: test
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region
upload_2013-11-25_2-25-7.png



New project:
B4X:
#Region  Project Attributes
    #ApplicationLabel: test
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region

#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: test
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: portrait
    #CanInstallToExternalStorage: False
#End Region
upload_2013-11-25_2-25-36.png


P.S.
I'm blind! I now see the Project Icon on image 1. But so, how can i use well the designer?
 

Attachments

  • laymain.bal
    3.2 KB · Views: 390
Last edited:
Upvote 0

klaus

Expert
Licensed User
Longtime User
Answer to post #28.
Attached you find a new module which works.
I tested it with your layout file from post #30, I added also a landscape variant.
Using :
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("laymain")
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Activity, True)
End Sub

It works on
- a 320 x 480 x 1 Emulator 3.5' screen
- a 480 x 800 x 1.5 device 3.5' screen
- a 1080 x 1920 x 4 device 5' screen
- a 1080 x 1920 x 1.5 device 10' screen
in both orientations.
 

Attachments

  • LayoutTest.zip
    10.9 KB · Views: 510
Upvote 0

klaus

Expert
Licensed User
Longtime User
Answer to post #30.
When I load an old project I get on top:
B4X:
#Region Module Attributes
    #FullScreen: True
    #IncludeTitle: False
    #ApplicationLabel: GPS
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region
No Project nor Application regions !
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Answer to post #28.
Attached you find a new module which works.
I tested it with your layout file from post #30, I added also a landscape variant.
Using :
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("laymain")
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Activity, True)
End Sub

It works on
- a 320 x 480 x 1 Emulator 3.5' screen
- a 480 x 800 x 1.5 device 3.5' screen
- a 1080 x 1920 x 4 device 5' screen
- a 1080 x 1920 x 1.5 device 10' screen
in both orientations.
Answer to post #28.
Attached you find a new module which works.
I tested it with your layout file from post #30, I added also a landscape variant.
Using :
B4X:
Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("laymain")
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Activity, True)
End Sub

It works on
- a 320 x 480 x 1 Emulator 3.5' screen
- a 480 x 800 x 1.5 device 3.5' screen
- a 1080 x 1920 x 4 device 5' screen
- a 1080 x 1920 x 1.5 device 10' screen
in both orientations.


on my 480x800 - 1.5 your new module works perfectly!
I tried only that simple layout, but soon on my entire project.

If it works, as I'm sure, I propose to change your username in... Santa Klaus :D

I do not know how to thank you enough.

THANK YOU, KLAUS
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Answer to post #30.
When I load an old project I get on top:
B4X:
#Region Module Attributes
    #FullScreen: True
    #IncludeTitle: False
    #ApplicationLabel: GPS
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region
No Project nor Application regions !


You have rightly said that I had to put the question in another thread.
However, it is enough to change to the right directives.

Thank you for trying it.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Klaus, I have not tried everything, but there are problems with the text in the ListView.
I used AddTwoLinesAndBitmap2 and AddSingleLine2 in a ListView: the text does not appear in the AddSingleLine2 (first 3 items are with Bitmap, the other are single line).


PS on 480x800x1.5
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
For me it works !
Where did you define the ListView layouts, before or after Scale.ScaleAll ?
You must define them before Scale.ScaleAll !
The attached project works on my three devices.
 

Attachments

  • LayoutTest.zip
    21.7 KB · Views: 448
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
For me it works !
Where did you define the ListView layouts, before or after Scale.ScaleAll ?
You must define them before Scale.ScaleAll !
The attached project works on my three devices.

Ehm sorry, i'm TOOOO tired.

The ListViews are defined in the designer, but, obviously, are "filled" by code... AFTER :) (and i know, it's logic that i MUST call Scale.ScallAll after this!); and when or if i add a new item... scale.ScaleView(myItem) [metacode] BEFORE adding to the list.

Great job, Klaus. Very very well.

Io ti farei un monumento (use you Google Translate, this time, lol)

BEST regards.
 
Upvote 0
Top