Part 1: Storing and accessing user interface components as variables

App Inventor programmers routinely store values, such as numbers or text strings (“Hello!”) in variables. For example,

stores the numeric value 6 in to the variable TOTALBUTTONS.

To illustrate by example, here is a global variable named SpecialButton. We can initialize it to anything we want at this point.

Next, inside our app, our blocks code assigns Button1 to the variable SpecialButton. SpecialButton now holds a reference to the actual user interface control Button1.

Since SpecialButton is a variable and not an actual button, we cannot directly use a SpecialButton.Click handler but we can use a feature of App Inventor to do the same thing in a different way. We will see how to do this in this a bit later.

You can store any App Inventor components – a Clock, a Bluetooth device – any component, in a variable.

Why would you want to do that? We will see in the example in this lesson.

This tutorial is in both written form and as an online video.

To those who may have programmed in other languages, you may have seen this idea elsewhere. This idea is common in “object oriented programming” (or OOP). In OOP, nearly everything is an “object”. A number, a string, a variable, a list, user interface components, code blocks – everything becomes an “object”. App Inventor “components” are basically the same idea – each is an “object” or a “something” that exists. If it exists, you can store it in a variable!

This is Part 1 of a 2-part tutorial. This tutorial continues in Part 2.

Topics Mentioned

  • Lists
  • Screen1.Initialize
  • Component references
  • For each loops
  • Selecting colors

Online Video or this Tutorial

Watch here or directly on Youtube – be sure to click on the Subscribe button on Youtube! More videos coming!

Source Code

Download source from the MIT App Inventor Gallery:

http://ai2.appinventor.mit.edu/?locale=en#6458280812216320

(The Gallery was not working when I published this post so use the alternate link if needed)

Or download here: UsingComponentsLists.aia

And then upload to App Inventor using Projects | Import project from my computer …

User Interface View

The user interface is simple – to demonstrate the idea of storing user interface components in a variable, we create 6 buttons on the screen, and store each of the components into a list. When the Change Button Colors button is pressed, the six buttons are changed to a random color selection.

After pressing Change Button Colors, we see the result:

Designer View

The user interface is set up using a VerticalArrangement layout with 6 buttons added inside the VerticalArrangement, and one additional button outside. In most apps, I change the names of the buttons to something like btnSaveFiles to show what the button does – but in this example, we are referencing the buttons to store them in variables, so their name is not important and we use the default names of Button1, Button2 and so on. Do change the text of each button, though, to read “Button 1”, “Button 2”, ….

A 7th button is added – when touched, this button causes all of the other buttons to change color.

Blocks View

For this demonstration we will store the six buttons in a list named ListOfButtons. We assign the buttons to the list inside Screen1’s .Initialize event handler.

 

Where do you find the references to Button1, Button2, etc?

Click on a button in the Blocks section, and then scroll all the way to the bottom of the list of events, procedures and properties:

As soon as our app begins running, it calls a procedure named ChangeButtonColors to immediately change the color of all the buttons (this procedure is explained below).

Once our buttons are saved in a list, we change the color of the buttons by going through the list to get each button.

First, for each number from creates an iteration loop – that is, this code will run through several times. The first time, the value of number is 1, and the code inside the for each block is executed. At the end of this code block number is increased by 1 to a value of 2. The loop continues, adding 1 to number at the end of the loop, until the value of number is greater than the value of TOTALBUTTONS (which is 6).

Next, we obtain the button corresponding to number – e.g. when 1, we fetch Button1, when 2, we fetch Button2. This action is performed using the select list item block which is used to obtain the element of the list corresponding to the value of number. Button1 is in position 1 of the list, Button2 is in position 2 of the list, due to how we created the list in the .Initialize routine, above.

Finally, we set the background color of the button control. Normally, you would set the Button background control using something like

Set Button1.BackgroundColor to some color value

But in our code, we are using the Button1 reference from the list – and need a different way to access Button1‘s BackgroundColor property. To do that, we use a semi secret block hidden at the bottom left of the Blocks.

Click on the + arrow next to Any component – you it opens to display additional blocks:

Since our app is  simple, we see only a few components here. In a large app, many components will be shown.

Next, click on Any Button and see a pop up of available blocks – select the Set Button.BackgroundColor block.

Putting this together, we end up with these blocks:

We could set the BackgroundColor to a color swatch available in the palette but we want to set the color to a randomly selected color. The block make color takes as input, three separate values, each in value from 0 to 255. The first value sets the Red color, the second value sets the Green color and the third sets the Blue color value. Combinations of red, green and blue produce any color. Values near 0 are very dark and values near 255 are very light. If we set the color values to [0, 0, 0] we get black and if set to [255, 255, 255] we get white. In between black and white, we get a rainbow of colors.

In our app, we set the values to a random number between the value of 20 to 240. This avoids selecting colors that are too dark or too bright.

To summarize, this code goes through our list of six buttons, obtains a reference to the button, and then uses the special set Button.BackgroundColor of component block to access the property of the selected button.

With the ChangeButtonColors procedure written, all we need to do is call the procedure each time our 7th button is pressed:

Why Do This?

The code above shows a way to change the background colors of a group of buttons without having to access every button individually. We could alternately write out this code for each individual button, something like:

Set Button1.BackgroundColor = make color …

Set Button2.BackgroundColor = make color …

Set Button3.BackgroundColor = make color …

In other words, repeat nearly identical code six times. While this is a simple example, in more complex programs, this could end up with a lot of duplicate code. Duplicate code not only uses more memory space but is harder to maintain – if we make a fix to one section we must then copy our fix to all of the other copies of that code!

There are other  examples where the same code needs to run for each control.

For example, previous tutorials on this blog have shown how to use Bluetooth to send serial data to and from another Android device or an Arduino board. I have a large, complex app that is a part of a commercial product and it communicates with six external devices using Bluetooth. Rather than write code to read and write from each of the six Bluetooth devices, I wrote one code block that does the reading and one code bock that does the writing. I reference the Bluetooth device in a manner similar to that described above, and store the Bluetooth device references in a list.

Reading or writing to the Bluetooth devices uses the same block of code – only the reference to the Bluetooth device itself changes, to select which of the six Bluetooth connections will be used.

This simplifies the code by

  • making the total app code smaller
  • makes bug fixing easier as bug fixes do not have to be copied to separate code blocks handling each device one by on
  • making performance improvements easier, as only one block of code needs to be improved, rather than several.

I hope to revise a previous on Bluetooth to show how to do this to support two Bluetooth devices with one code section.

The suggested exercise in the next section illustrates another example for using component references, as described in this tutorial.

Part 2 of this tutorial provides another example of why the use of reference is valuable to reduce code size, simplify programming and to make future maintenance and modification to your programs easier.

Suggested Exercise

Suppose you have a user interface screen that displays six Checkbox components. Write a procedure to set all of the Checkbox items so to “checked” by default. You can do this by putting the check box user interface components into a list and then, go through the list and change the component’s Checked property to true. To clear the check box selection, set the Checked property to false.