Android Tutorial Designer Scripts Tutorial

Background

One of the most common issues that Android developers face is the need to adopt the user interface to devices with different screen sizes.
As described in the visual designer tutorial, you can create multiple layout variants to match different screens.
However it is not feasible nor recommended to create many layout variants.

Basic4android v1.9 introduces a new tool named "designer scripts" that will help you fine tune your layout and easily adjust it to different screens and resolutions.

The idea is to combine the usefulness of the visual designer with the flexibility and power of programming code.

You can write a simple script to adjust the layout based on the dimensions of the current device and immediately see the results. No need to compile and install the full program each time.

You can also immediately see the results on the abstract designer. This allows you to test your layout on many different screen sizes.

How to

Every layout file can include script code. The script is written inside the visual designer under the new Designer Scripts tab:

SS-2012-03-20_12.55.44.png


Their are two types of scripts: the general script that will be applied to all variants, and a script specific to the current variant.

Once you press on the Run Script button (or F5), the script is executed and the connected device / emulator and abstract designer will show the updated layout.

The same thing happens when you run your compiled program. The (now compiled) script is executed after the layout is loaded.

The general script is first executed followed by the variant specific script.

The script language is very simple and is optimized for managing the layout.

Lets start with an example.

Example

In this example we will build the following layout:
SS-2012-03-20_13.08.05.png


btnLeft and btnRight should be located in the top corners.
btnDown should be located at the bottom and fill the entire width.
ListView1 should fill the entire available area.
ToggleButton1 should be located exactly in the center.

The first step is to add the views and position them with the visual designer (you do not need to be 100% accurate).
Now we will select the designer scripts tab and add the code.
Note that the views are locked when the designer scripts tab is selected.

The code in this case is:
B4X:
'All variants script
btnRight.Right = 100%x

btnDown.Bottom = 100%y
btnDown.Width = 100%x

EditText1.Width = 100%x
EditText1.Bottom = btnDown.Top - 5dip

ListView1.Width = 100%x
ListView1.SetTopAndBottom(btnLeft.Bottom, EditText1.Top)

ToggleButton1.HorizontalCenter = 50%x
ToggleButton1.VerticalCenter = 50%y

The result:

SS-2012-03-20_15.10.06.png


10'' tablet:
SS-2012-03-20_15.11.16.png


SS-2012-03-20_15.35.16.png


Reference

The following properties are supported:

- Left / Right / Top / Bottom / HorizontalCenter / VerticalCenter - Gets or sets the view's position. The view's width or height will not be changed.

- Width / Height - Gets or Sets the view's width or height.

- TextSize - Gets or sets the text size. You should not used 'dip' units with this value as it is already measured in physical units.

- Text - Gets or sets the view's text.
TextSize and Text properties are only available to views that show text.

- Image - Sets the image file (write-only). Only supported by ImageView.

- Visible - Gets or sets the view's visible property.

Methods:

- SetLeftAndRight (Left, Right) - Sets the view's left and right properties. This method changes the width of the view based on the two values.

- SetTopAndBottom (Top, Bottom) - Sets the view's top and bottom properties. This method changes the height of the view based on the two values.

Keywords:

- Min / Max - Same as the standard Min / Max keywords.
- AutoScale - Autoscales a view based on the device physical size.
Example:
B4X:
AutoScale(Button1)
- AutoScaleAll - Autoscales all layout views.
Example:
B4X:
AutoScaleAll
- AutoScaleRate - Sets the scaling rate, a value between 0 to 1. The default value is 0.3
Example:
B4X:
AutoScaleRate(0.2)

- ActivitySize - Returns the approximate activity size measured in inches.

- If ... Then condition blocks - Both single line and multiline statements are supported. The syntax is the same as the regular If blocks.

- Landscape (v3.20) - Returns True if the current orientation is landscape.
- Portrait (v3.20) - Returns True if the current orientation is portrait.

Notes and tips

- %x and %y values are relative to the view that loads the layout.
Usually it will be the activity. However it you use Panel.LoadLayout then it will be relative to this panel.
Note that ScrollView inner panel width is set to -1. This is a special value that causes the panel to fill its parent available size.
If you want to load a layout file (with a script) to the inner panel then you will need to first set the panel width: ScrollView.Panel.Width = ScrollView.Width.

- Use 'dip' units for all specified sizes (except of TextSize). By using 'dip' units the values will be scaled correctly on devices with higher or lower resolution.

- In most cases it is not recommended to create variants with scales other than 1.0. When you add such a variant you will be given an option to add a normalized variant instead with a scale of 1.0.

- Variables - You can use variables in the script. You do not need to declare the variables before using them (there is no Dim keyword in the script).

- Activity.RerunDesignerScript (LayoutFile As String, Width As Int, Height As Int) - In some cases it is desirable to run the script code again during the program. For example you may want to update the layout when the soft keyboard becomes visible. Activity.RerunDesignerScript method allows you to run the script again and specify the width and height that will represent 100%x and 100%y. In order for this method to work all the views referenced in the script must be declared in Sub Globals.
Note that this method should not be used to handle screen orientation changes. In that case the activity will be recreated and the script will run during the Activity.LoadLayout call.

It is recommended to continue to this tutorial: http://www.b4x.com/forum/basic4andr...ing-multiple-screens-tips-best-practices.html
 
Last edited:

moster67

Expert
Licensed User
Longtime User
Thank you Erel. I can understand your reasoning and of course I am aware that B4A has evolved a lot over time.

The solution to use a condition could be fine for me. However, would you be able to explain better how to interpret the value ActivitySize returns? I know it returns the approximate activity size measured in inches but how would it relate to resolution (for instance 480x800)? I mean there can be devices which has 4.3 inches with resolution of 480x800 but I guess there may be other phones with same inch-size (4.3) which may use a different resolution. Is there a way to determine resolution based on ActivitySize?

It might be useful from DesignerScript to be able to call GetDeviceLayoutValues and get its values such as scale, height, width...
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
ActivitySize returns the device size measured in inches. This value is more important than the actual resolution.

You should set all the values with 'dip' unit (or percentage). This way the scale doesn't matter.

(If you do want to get the actual resolution then you can get it with 100%x, 100%y, 100dip/100. But you shouldn't).
 

NJDude

Expert
Licensed User
Longtime User
Look at the attached sample, that's what I explained to you in the Chat Room. That's one way of doing it.
 

Attachments

  • SampleForPaul.zip
    415.5 KB · Views: 715
Last edited:

Johan Schoeman

Expert
Licensed User
Longtime User
I am trying to come to grips with Designer Scripts. In the above example I have removed ListView1 and replaced it with a panel i.e Panel1. I then made Panel1 the parent of ToggleButton1. But when I select the Designer Scripts tab the ToggleButton "disappears" and is no longer visible. How do I get ToggleButton1 to become visible?
 

RonC.

Member
Licensed User
Longtime User
- Landscape (v3.20) - Returns True if the current orientation is landscape.
- Portrait (v3.20) - Returns True if the current orientation is portrait.

Got an error trying to use: If Portrait = True Then

How do you access the variable?

Running version 3.50

Wanted to use this instead of Phone method or comparing Width and Height...
 

pilbazan

Member
Licensed User
Longtime User
Got an error trying to use: If Portrait = True Then

How do you access the variable?

Running version 3.50

Wanted to use this instead of Phone method or comparing Width and Height...

Hi RonC.
If you download the guide.zip of http://www.b4x.com/android/files/guide.zip , inside there are a PDF called B4ACodeSnippets.pdf with a lot of codes examples. One of this is:
2.36 Get the current screen orientation in the code
(posted by Erel). Requires the Reflection library.

I don't know if this or another code of that PDF can help you.
Regards
 

Loris Anoardi

Member
Licensed User
Longtime User
Question abount layout variants:

If the app will run on a device whose layout variant is not defined, which one will be consedered?
Example: i create layout varyant for 320x480 and for 1280x800. What happens if the app will run on a 1024x600 device?
Thanks !
 

Loris Anoardi

Member
Licensed User
Longtime User
Thanks Erel but i can't understand why in large screen devices the autoscaleall doesn't scale at 100%. I created now only a variant (320x480)
I read the tutorial but i don't understand this thing.
See attacched image:

Thank you very much
ScreenShot038.jpg
 
Last edited:

Mashiane

Expert
Licensed User
Longtime User
Question on Designer Scripts: Is it possible within the designer itself to have some kind of a generator button that will read each view on a layout and give one its coordinates, e.g. top, left, width and height position within the layout that you are working on? This then can be copied and pasted to the code window. I see the balconvertor b4j file and its such a cool app that I'm using, but then its outside the b4a.

#just a thought.
 

luke2012

Well-Known Member
Licensed User
Longtime User
Hi to all,
I have a layout problem to handle :)

In my app I handle the layout with a single "Script - General" script that works fine on devices with medium / big screen with an exception for 3,5" - 320 x 480 px (165 ppi).

I wrote a script variant (Variant specific script: 320x480,scale=1) thats works fine on 320 x 480 px screens but impact also the "Script - General" script and change the correct position of some views.

Is it possible to make a specific script that runs only on the above screen size and let the Script - General works on all other screen size and resolutions ?
 
Last edited:

JdV

Active Member
Licensed User
Longtime User
Hi

I have noticed on some devices I can see the views being moved into place after the layout has loaded. (The effect is more pronounced when there's a load layout animation.)

Would the following be possible?
- Set all views to invisible
- Load the layout
- Adjust the views into their final position
- Detect when the layout has finished loading
- Set all views to visible

Is there an event fired when the designer script has finished executing?

Regards

Joe
 
Top