In the last post, we introduced some concepts for building “creative” App Inventor user interfaces that feature visually appealing user interface controls rather than the usual bland buttons.
In this post, we look at creating an array of toggle switches. Tapping a switch flips the switch from left to right, or right to left.
In developing this user interface, we learn two concepts:
- We expand on the previous post and its use of images to create custom buttons.
- We see how a user interface control can be stored in a list and referenced like a variable within our apps.
The User Interface
I called my app “Mission Control” because any good mission control panel needs lots of switches!
The user interface features 9 toggle switches in a 3 x 3 array. The purpose of this app is to demonstrate how to implement this type of interface – the app does not otherwise do anything interesting.
Tapping any toggle switch causes the switch lever to move to the other side of the switch. Here is a screen shot showing some toggle switches to the left and some to the right.
Create the interface using a combination of horizontal layouts (for the title line) and a table arrangement to hold the buttons. The title Mission Control Console is a label centered inside a horizontal arrangement layout.
The buttons are placed in to a table arrangement having 3 columns and 3 rows. Assign an each button using the button’s properties.
The Blocks View
Our app needs to keep track of the “state” of each toggle switch. Each switch is said to be either “on” or “off”. We could also say a switch is “closed” (like when an electrical circuit is active and electricity passes across the switch) or “open” (the switch is set so that no electricity can cross).
In our app we use the logic values of true or false. A switch setting is recorded as “true” or “false”. When the switch is shown to the left, we say the switch has a value of “true” and when the toggle switch is to the right, the switch has a value of “false”.
To track the setting of each of the 9 switches in our app, we create a list named ToggleSwitches having 9 elements. Initially, we set all of the switches to “true”.
For each of the toggle switches, named Toggle1, Toggle2, … Toggle9, we implement a “Click” event handler. The event handler for Toggle1 calls the procedure named FlipSwitch and passes to it parameters specifying toggle switch 1.
Only the first 3 “Click” event handlers are shown here – handlers for toggle 4 through 9 are identical except that they specify the appropriate toggle switch for the call to FlipSwitch.
Here is where we introduce that a user interface component (Toggle1, Toggle2) is itself an object that can be referenced similar to a variable. Select the component in the Blocks components list, at the left of the Blocks editor – click on Toggle1. When the list of methods (procedure calls) and properties appear, scroll to the very bottom of the list to find a reference to Toggle1:
The property circled in red is a reference to the Toggle1 switch object. We may assign this value to a variable or, as done here, pass it as a parameter variable in a procedure call.
But what can we do with a variable that holds a control? The answer is most everything! How this works is not obvious since these features are hidden beneath the “Any component” item in the components list. Chances are you have not looked here before and if you did you likely thought “what is that for?”
Suppose we clicked on “Any Ball” (in an app that contains ball objects). We see the usual set of methods and properties for balls, but each has an additional “for component” or “of component” parameter. It is here that we plug in the control value.
In the case of our toggle switches, each switch is a button. We select the “Any button” option to access the methods and properties of the button that acts as a toggle switch.
When a toggle switch is tapped on screen, we change the image of the toggle switch from showing the toggle on the left to showing the toggle on the right. To do this, the variable that holds the reference to our switch control is plugged in to the “of component”:
If ToggleSwitch had been set to Toggle1 (the named control), then App Inventor interprets this as if we had written “set Toggle1.Image” to “ToggleSwitch2.png”.
Let us now look at the procedure FlipSwitch. Upon calling FlipSwitch, the parameter variable ToggleSwitch holds a reference to the control, and SwitchNum is the number of the switch that is being changed. A sample call acts something like:
to FlipSwitch Toggle1 1
Remember that the global ToggleSwitches list contains the true or false setting of each switch. We can check if a toggle switch is true by checking the SwitchNum element of the list. In other words, if SwitchNum is 4, this code says, basically, if the 4th element of ToggleSwitches is true then do the following – and what it then does is to set the image of the button specified by the ToggleSwitch parameter to the image with the toggle pointed to the right. Simultaneously, we set the 4th element of ToggleSwitches to false to keep track of the switch being set to the right.
If the switch is currently “false” (to the right), then the image is reset back to the image showing the toggle to the left and our tracking value in ToggleSwitches is set to true.
In this way, a toggle switch has been implemented by using two images – one showing the switch to the left and one showing the switch to the right. The code “flips” the image from one to the other whenever the switch is touched on screen.
To simplify the amount of code that needed to be created, each switch button handler calls the same FlipSwitch procedure, passing to it the button and the switch number that needs to be changed.
To do this, we introduced the concept that a control can itself be stored in a variable or list, and passed as a parameter. To access the methods and properties of a control stored in this way, we use the “Any component” options in the palette.