Android Question AutoScale on views created by code?

Jerryk

Active Member
Licensed User
Longtime User
How to scale views created by code in B4XPages?
I found Klaus's Scale module (from 2012) which works on old Activity. On B4XPages it ends with an error in this module.

B4X: Copy
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Root, True) - error

Error occurred on line: 641 (Scale)
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference


I am attaching a small project.

Screenshot_2025.07.28_10.03.04.854.png
 

Attachments

Solution
The Scale module is a quite old module and many things have changed since its publication and especially B4XPages.
I added a warning on top of the thread to not use it anymore.

In your example, you are not using the scaling correctly.
You mix layouts from the Designer with layout in code.
In the MainPage layout you have AutoScaleAll.
In the lbl1 layout, no AutoScale.
Then you use this for the scaling:
B4X: Copy
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Root, True)
The problem is that the MainPage layout has already been scaled in the Designer and you scale it again.
I replaced above two lines by these:
B4X: Copy
    Scale.SetReferenceLayout(320, 480, 1)
    Scale.ScaleAllDS(tilesPanel, False)
Your reference layout or...
The Scale module is a quite old module and many things have changed since its publication and especially B4XPages.
I added a warning on top of the thread to not use it anymore.

In your example, you are not using the scaling correctly.
You mix layouts from the Designer with layout in code.
In the MainPage layout you have AutoScaleAll.
In the lbl1 layout, no AutoScale.
Then you use this for the scaling:
B4X: Copy
    Scale.SetReferenceLayout(480, 800, 1.5)
    Scale.ScaleAll(Root, True)
The problem is that the MainPage layout has already been scaled in the Designer and you scale it again.
I replaced above two lines by these:
B4X: Copy
    Scale.SetReferenceLayout(320, 480, 1)
    Scale.ScaleAllDS(tilesPanel, False)
Your reference layout or layout variant in the Designer is 320, 480, 1 and not 480, 800, 1.5.
You should use Scale.ScaleAllDS(tilesPanel, False).
ScaleAll scales differently vertically and horizontally.
ScaleAllDS scales like the DesignerScript.
The second parameter in ScaleAllDS must be False because the ScrollView has already been scaled.
And it works almost as you expect it.
I am not sure if the equation of AutoScaleAll in the Desiger is exactly the same as the one in the Scale module.

Effectively, with B4XPages the call of ScaleAll throws an error.
I have not used the Scale module for a long time.
I do not intend to adapt it, because it would take quite some work to adapt it to B4XPages and i have never tried it with CustomViews.

I suppose that you want to fill ScrollViews with given layouts.
Can you please give some more explanations on what exactly you want to do, to find a concrete solution.
In your example, in the lbl1 layout, maybe you could put the Labels on a Panel and set AutoScaleAll, and then load them and reposition them correctly.
 
Upvote 1
Solution
Thanks for the answer.

The example is a mix of code and designer, because the designer is used as a template. In a real project I only need to use views created by code.

Your code works as expected.

Regarding the layout settings for "lbl1", I did some experiments: It doesn't matter if the three Labels are in the Panel or not. It depends on AutoScaleAll - it must not be used, otherwise the scaling is incorrect. (when used the Labels are larger and the third Label is cut off). Probably there is a double scaling, once with AutoScaleAll, the second time with ScaleAllDS.
 
Upvote 0
In your example, in the lbl1 layout, maybe you could put the Labels on a Panel and set AutoScaleAll, and then load them and reposition them correctly.
This proposal was thought without the Scale module.

Instead of this code:
B4X: Copy
    Dim pnl As Panel
    pnl.Initialize("")
    pnl.Width = 140dip
    pnl.Height = 120dip
    pnl.LoadLayout("lbl1")
    pnl.Color = xui.Color_Cyan
    tilesPanel.AddView(pnl, 0, 0, pnl.Width, pnl.Height)
   
    Dim pnl2 As Panel
    pnl2.Initialize("")
    pnl2.Width = 140dip
    pnl2.Height = 120dip
    pnl2.LoadLayout("lbl1")
    pnl2.Color = xui.Color_Magenta
    tilesPanel.AddView(pnl2, 0, pnl.Height, pnl2.Width, pnl2.Height)

    Scale.SetReferenceLayout(320, 480, 1)
    Scale.ScaleAllDS(tilesPanel, False)

You could have this:
B4X: Copy
    For i = 0 To 5
        Private pnlLables As Panel
        tilesPanel.LoadLayout("lbl2")
        pnlLables = tilesPanel.GetView(i)
        pnlLables.Color = xui.Color_RGB(Rnd(0, 256), Rnd(0, 256), Rnd(0, 256))
        pnlLables.Top = i * pnlLables.Height
    Next
    tilesPanel.Height = i * pnlLables.Height
In the lbl2 layout the three Labels are on a Panel with Width = 140 and Height = 120 and with AutoScalingAll.
I added more than two Panels to show what can be done in a Scrollview.

And how it looks like:

1753781769924.png
 

Attachments

Upvote 0
I added code that is independent of the panel dimensions in the designer. I added an invisible reference panel PanelRef with dimensions of 100 x 100 to the Scrollview. Then I adjust the dimensions by calculating the ratio.
B4X: Copy
    For i = 0 To 1
        Private pnlLables As Panel
        tilesPanel.LoadLayout("lbl2")
        pnlLables = tilesPanel.GetView(i)
        pnlLables.Color = xui.Color_RGB(Rnd(0, 256), Rnd(0, 256), Rnd(0, 256))
        pnlLables.Top = i * pnlLables.Height
    Next
    For i = 2 To 3
        Private pnlLables As Panel
        tilesPanel.LoadLayout("_pnl")
        pnlLables = tilesPanel.GetView(i)
        pnlLables.Color = xui.Color_RGB(Rnd(0, 256), Rnd(0, 256), Rnd(0, 256))
    
        Dim x As Float = 140dip  'required dimensions
        Dim y As Float = 120dip  'required dimensions
        Dim xratio As Float = x / 100dip 
        Dim yratio As Float = y / 100dip
        pnlLables.Height = PanelRef.Height * yratio
        pnlLables.Width = PanelRef.Width * xratio
    
        pnlLables.Top = i * pnlLables.Height
    Next
    
    tilesPanel.Height = i * pnlLables.Height
 
Upvote 0

Similar Threads

Replies
3
Views
3K
Replies
1
Views
2K
Replies
3
Views
4K
  • Question Question
Android Question AutoScale Code Module
Replies
70
Views
63K
Back
Top