Home » Uncategorized » How to adapt to screen orientation in App Inventor

How to adapt to screen orientation in App Inventor

Introduction

NOTE:

This post was initially published for AppInventor classic, but currently sources are available also for AI2. However, I have not updated the comments and images because the code is roughly the same.

This post explains a mechanism to resize the visual components when the screen device changes its orientation (i.e. from vertical to horizontal or vice versa). The objective is to avoid that these components get out of view when the screen height or width is shorter than in the original design.

It’s important to remark that the technique explained in this post can be adapted to achieve other purposes such as those mentioned in the Further Ideas chapter:

  • Adapt the components size in order to fit in the screen for devices with different size
  • Provide multilingual capabilities to an app

What are we going to build

We’ll typically design our app with vertical orientation, so when the orientation changes we need to “flatten” the design. For example, the app we’re going to follow contains a menu screen designed in a vertical layout to show 4 square buttons and a small button below (see image), but when orientation changes this shape provokes the lower buttons to disappear from the screen. Our solution converts these buttons into rectangles in order for them to fit in the screen.

logintutorial_72

Of course this adaptation is not always necessary or desirable. Actually you’ll probably want to avoid it for textbox components because reducing its original height is not likely to be a good idea.

Instead of resizing components, we could consider the option of moving them (fpr example the central screen in the image would be perfectly valid if we were able to place the small red button in the empty right side zone). However this would be nearly impossible in AI because the components’ position attribute is not modifiable by code (it’s rather assigned automatically). Maybe a solution based on hiding and showing arrangements could be an idea to explore but I’m not sure this would really work.

How it works

The idea is to divide the screen in an imaginary grid, with each component being fully located in some of the resulting cells and taking into account both orientations. In our example the grid could have a size of 9 x 11 which would give the following appearance in both orientations:logintutorial_71

This division allows the algorithm to work out the X and Y position of each component by multiplying the left-top position within the grid by the width of each cell and the same for the Y position.

For example, if our screen size is 440 x 270, the button’s position would be:

  Cell Size Blue button Cyan button Green button Yellow button
Horizontal 30 x 40 (60, 80) (180, 80) (60, 240) (180, 240)
Vertical 40 x 30 (80, 60) (200, 60) (80, 240) (200, 240)

Installation

You can try the application by downloading these sources and uploading them into App Inventor. You’ll realise there’s some functionality that is not explained in this tutorial because this is actually a more general application (which is explained in the Login template post). The part that concerns us is just the menu window.

User interface

logintutorial_15 logintutorial_16

The components are very simple. No secrets with buttons: one for each option and an additional one for “Exit”. Labels are somewhat trickier because they’re used to leave some space between buttons. The TableArrangementMenu1 has 4 columns and 5 rows and the labels are positioned in:

  • Label1_3: Row 1, Column 3
  • Label_3_1: Row 3, Column 1
  • Label_5_3: Row 5, Column 3

To achieve the layout required, you can specify the desired height and width for these labels. However, these attributes will be overridden by code.

Code blocks

Variables

logintutorial_73

  • iScreenHeight, iScreenWidth: Store the screen height and width. They are updated at initialization time and each time the screen orientation changes
  • iHeight, iWidth: Auxiliary variables

Functions

logintutorial_74

  • Screen1.Initialize, Screen1.OrientationsChanged: These are the two events that concern us, as they are the points when the initialization of components size takes place by means of a call to the initMenusize function
  • initMenuSize: This is the actual function that places the components according to the screen current size. Since we cannot indicate the position, the secret consists in specifying the height and width for both the buttons and the spacer labels strategically placed between buttons (see above). The calculations should not be difficult to understand if we have the grid image in mind. Note that the example above was simplified so the numbers in the code are slightly different. For example the buttons occupy 3 x 4 cells (rather than 3 x 3) and the screen is divided in 13 x 11 cells (rather than 11 x 9) because we have some extra space occupied by a header bar. I advise you to experiment different combinations to fully understand the algorithm.

Further ideas

The work we’ve done in this tutorial can be a first step to achieve other useful functionalities. In this final chapter I expose a couple of such extensions that I’ve developed and are explained in this tutorial.

Adapt components size to different devices

Supporting different devices without having to create different versions of the app is probably a much more common requirement than adapting to orientation change. The good news is that our technique is quite close to the solution. For example, the menu built in this tutorial would be correctly displayed in a larger device such as a tablet. For the whole app to be smartly presented we must simply adapt the initMenuSize function in order to apply the same resizing technique to all of our compoments. Of course this would be much more tedious, so rather than explicitly indicating each component in the function, we must previously create a  list of components, and loop through this list in the initMenuSize function. This is not a five minutes task so please refer to the above mentioned tutorial for the details.

Multilingual capabilities

Similarly, if we intend our app to be able to “speak” several languages, we won’t obviously want to rewrite it for each supported language, but rather think of a means to modify the text of captions and labels at initialization time in order to show them in the language chosen by the user. Once again the idea is looping through all components in an initialization function, in order to set the caption corresponding to the current language. The captions mst be obtained from a list populated at design time and stored for example in a TinyWebDB component. Another fascinating project that deserves a tutorial on its own.

Advertisements

2 Comments

  1. Sofìa says:

    Hi, I don’t understand why, if the buttons occupy 3 x 4 cells (rather than 3 x 3), the screen is divided in 13 x 11 cells, it have to be 11×11..I don’t understand why. Thanks for your response.

    • eixerits says:

      Actually my numbers gave 12: 5 spacers + 3×2 buttons + 1 header
      However, when faced with practice I realised 13 led to better appearance, probably because of roundings. A good side of this mechanism is that you can make quick prototypes until you’re satisfied. For example in my case a heigth of 12 placed the “exit” button too low so I had to increase the number of cells. If it had been too high, I should have decreased it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: