Explore MIT App Inventor - Multiple Screens http://dev-explore.appinventor.mit.edu/tutorial-type/multiple-screens en Colored Dots http://dev-explore.appinventor.mit.edu/content/colored-dots <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">Colored Dots</span>: Creating Apps with Multiple Screens</h2> <p>This tutorial shows how to create apps that have multiple screens. In App Inventor, you can have a screen open a second screen. Later, the second screen can return to the screen that opened it. You can have as many screens as you like, but each screen closes by returning to the screen that opened it. The screens can share information by passing and returning values when they open and close. The screens also share the same TinyDB data, which they can use to store and share values.</p> <p>Building an app with multiple screens is a lot like creating several individual apps. Every screen that you create has its own components in the Designer window. In the Blocks Editor, you will be able to see only the components of the screen currently selected in the Designer. Similarly, the blocks of code related to a screen cannot refer to blocks of code in another screen.</p> <p>This program, ColoredDots, has two screens. ColoredDots is similar to <a href="http://explore.appinventor.mit.edu/content/paintpot-part-1">PaintPot</a>, but it uses a second screen to let the user create new colors by providing numerical values for the red, green, and blue color composition (RGB). In the PaintPot app, a user can only paint with one of the three predefined colors. Adding more colors to Paintpot would have required new buttons on the screen, reducing the amount of space available for painting. In ColoredDots, the new color is chosen on a second screen called Brush_Picker. Once a new color has been created in this second screen, its value is passed back to the first screen. You can also save and name the colors you create in the second screen, then use the saved colors later when painting. By using ListPicker to store the colors you create, it eliminates the need for the user to remember the name of the color they saved and spell it correctly in accessing it again. This makes the database of stored colors more accessible, making it easier to share the app among a group of people.</p> <p>Here are the two screens for the ColoredDots app:</p> <p><img src="/sites/all/files/tutorials/coloredDots/brush_picker.PNG" style="float:right;" /></p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1.PNG" /></p> <h4 class="ai-header">Objectives</h4> <p>By the end of this tutorial, you should have a understanding of:</p> <ul><li>How to make an app with multiple screens.</li> <li>How to pass values from one screen to another via <b>TinyDB</b>.</li> <li>How to fill and use the <b>ListPicker</b> element.</li> </ul><h4 class="ai-header">Building the Main Screen (Screen1)</h4> <p>You start building a multiscreen app by creating a new project, just as with any other app. As usual, App Inventor automatically creates the main screen and names it <b>Screen1</b> and you can add components. Here's the Designer and the Components panel when all the components for <b>Screen1</b> have been added.</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1designer_0.PNG" /></p> <p>The components are:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> <td> Component Settings </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">TitleLabel</td> <td>Shows the title "Paint with Colored Dots"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ColorLabel</td> <td>Shows the text "Current Color"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ColorSample</td> <td>Blank label whose background color is the current color</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotSizeLabel</td> <td>Shows the text "Dot size"</td> <td></td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotSizeValue</td> <td>Shows the current dot size</td> <td></td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>Shows dots at the places you touch</td> <td></td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">EraseButton</td> <td>Clears the canvas</td> <td>Set text to "Erase"</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">openBrushPicker</td> <td>Launches the second screen</td> <td>Shows the text "Customize Brush"</td> </tr><tr><td> <b>ListPicker</b> </td> <td>Basic</td> <td style="color:green;">ListPicker1</td> <td>Loads the list of colors from the data base</td> <td>Shows the text "Stored Color"</td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>Stores color names and values</td> </tr></table><p>We'll look at the blocks for <b>Screen1</b> below. But first let's add the other screen.</p> <h4 class="ai-header">Adding a second screen</h4> <p>To add a new screen to your app, click the Add Screen button in the top toolbar of the Designer window. A dialog window will appear, in which you can provide a name for the new screen.</p> <p><img src="/sites/all/files/tutorials/coloredDots/newscreenname_0.PNG" style="float:right; width:250px;" /></p> <p><img src="/sites/all/files/tutorials/coloredDots/addscreen.png" style="width:400px;" /></p> <pre class="ai-box"><b>Note:</b> You should make the name of the new screen something meaningful when you add it. Do that now, because once a screen has been added, its name cannot be changed -- the Rename button for the screen component itself is disabled -- it's good to have meaningful names for the parts of your program. One limitation here is that <b>Screen1</b> cannot be renamed. Remember also that the screen's title (shown in the title bar when the app is running) is different from its name. You can change the screen title in the Properties pane.</pre><p>When you create a new screen, the Designer window switches to display it. Initially there will be no components, just like with a new app, and you add new components by dragging them from the Palette, just as with any screen. Here's the Designer window for the second screen, named <b>Brush_Picker</b>, after the components have been added. Notice that <b>Brush_Picker</b> is a dark green color, meaning <b>Brush_Picker</b> is the current screen.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerdesigner.PNG" /></p> <p>The components for the brush picker screen are:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">RedLabel</td> <td>Shows the text "Red"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Red</td> <td>For entering the amount of red in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">GreenLabel</td> <td>Shows the text "Green"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Green</td> <td>For entering the amount of green in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">BlueLabel</td> <td>Shows the text "Blue"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">Blue</td> <td>For entering the amount of blue in the color (0-255)</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">DotRadius</td> <td>Shows the text "Dot size"</td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">RadiusTextBox</td> <td>Shows the current dot size</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">TestColorButton</td> <td>Press to create the new color and prompts the user to store this color</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">LabelTestColorSample</td> <td>Blank label whose background color is the new color</td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>Displays the size and color of the test color</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResetColorButton</td> <td>Resets all the values to the default color, black</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ReturnToPainting</td> <td>Returns to the main screen with the new color and dot size</td> </tr><tr><td> <b>Notifier</b> </td> <td>Other stuff</td> <td style="color:green;">Notifier1</td> <td>Shows a dialog for saving the color and entering a color name</td> </tr><tr><td> <b>TinyDB</b> </td> <td>Basic</td> <td style="color:green;">TinyDB1</td> <td>Stores color names and values</td> </tr></table><p>Here and in general with multiple screen apps, only the components that belong to the current screen (in this case <b>Brush_Picker</b>) are shown in the Designer and the Components pane. You can switch between screens by pressing the <b>Brush_Picker</b> and the <b>Screen1</b> buttons, and the view in the Designer will show the corresponding screen. The same is true for the Blocks Editor: When you're working on a screen you'll see only the blocks for that screen.</p> <pre class="ai-box">None of the components, variable definitions, and procedures that you define in one screen will be accessible from any other screen. We'll see below how to pass information between screens.</pre><pre class="ai-warning">Warning: When you switch between screens, you are effectively telling the Blocks Editor to load a new project, and this takes a little time. Wait until the Blocks Editor is done loading the blocks for the new screen before changing things. Most especially, wait until the new screen has finished loading before clicking on blocks or links with the mouse. If you don't wait, you may get errors, or even lose blocks from your project.</pre><h4 class="ai-header">Blocks for the main screen (Screen1)</h4> <p>The <b>Screen1</b> is essentially a drawing program. When you touch the Canvas, the app draws a dot of the current radius and color. The color is specified by the background of the <b>ColorSample</b> label. The erase button clears the canvas. When the screen opens, it initializes the radius to 3 and the color to black. Here are the corresponding blocks:</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1basicblocks.PNG" /></p> <p>It is worth noting that the <span class="basicblock">Initialize</span> block uses the procedure <span class="callblock">TinyDB1.StoreValue</span> and sets the ListPicker to <span class="callblock">populateList</span> using the <span class="setterblock">set ListPicker1.Elements to</span> block. Each of these actions will be discussed in more detail later. Basically, when the screen starts, it stores the default color, Black, and adds that to the list of colors that can be selected using the ListPicker. </p> <pre class="ai-testing"><b>Testing the behavior.</b>Test to make sure the drawing behavior acts as you expect it to. You won't be able to add new colors yet, but see what happens when you try to draw dots of the page.</pre><h4 class="ai-header">Communicating with the brush picker screen</h4> <p>The multiple screen aspect of the app involves getting the "new brush": the new color and the new dot radius. It's the job of <b>Brush_Picker</b> to create these values and return these to <b>Screen1</b> as a list of three items: the color, the dotsize, and the total number of colors stored. The number of colors is necessary for creating the list that ListPicker will reference. We'll see how <b>Brush_Picker</b> does this below, but from the perspective of <b>Screen1</b>, all it needs to do is open <b>Brush_Picker</b> and get the result.</p> <p>Here's how this happens: when the Customize Brush button is pressed, <b>Screen1</b> uses <span class="" controlblock="">open another screen with start value</span> to open <b>Brush_Picker</b>. When the user finishes with Brush_Picker, it will signal the other screen closed event, which provides the name of the screen (here Brush_Picker) and the value returned (here the three-element list). The event handler for <b>Screen1</b> extracts the three items from the list and sets the ColorSample background and the DotSizeValue text properties. It also calls the procedure <span class="callblock">populateList</span>, which is defined below. Here are the blocks:</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1communicating.PNG" /></p> <p>ColoredDots uses <span class="controlblock">open another screen with value</span> to open <b>Brush_Picker</b> with values passed to it from <b>Screen1</b>. The other screen then accesses these opening values using <span class="controlblock">get start value</span> blocks. In general, a screen opens another screen with <span class="controlblock">open another screen</span> and gets a result back though the <span class="controlblock">when other screen closed</span> event. In this case, the values are passed from <b>Screen1</b> to <b>Brush_Picker</b> so the app can keep track of how many colors are stored and what the current values are.</p> <pre class="ai-testing"><b>Testing the behavior.</b> If you want to make sure that your blocks for opening a new screen are working, you will have to package the app to your phone or emulator. App Inventor does not currently allow live development for multi-screen apps, so make sure you package the phone before trying to test the behavior.</pre><h4 class="ai-header">Sharing data via TinyDB</h4> <p>Besides opening screens and returning values, the different screens in a multiple screen app can communicate through TinyDB. To do this, give every screen its individual TinyDB component. Even though these will be "different" TinyDB components, they will in fact all share the same keys and values: If one screen stores a value under a key, the other screen can get that value by using the same key.</p> <p>ColoredDots uses TinyDB to let you name the colors you create and save them to later use. The saving and naming will be done in <b>Brush_Picker</b>, as shown in the blocks later. When you open ListPicker (labelled Stored Color) in <b>Screen1</b>, the app uses opens the list of colors that you have stored for you to choose one and then sets the drawing color to the result. The elements are added to this list by creating the procedure <span class="callblock">populateList</span>. As shown in these blocks, <span class="callblock">populateList</span> iterates through the all of the stored entries in the database up to the number of stored colors and adds them to the list tinyDBlist. It returns this list, which ListPicker1 points to.</p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1populatelist.PNG" /></p> <p>When ListPicker is opened, you will see a list of all the colors you created. <span class="basicblock">ListPicker1.AfterPicking</span> sets the Color value stored for that name to be the current drawing color, as shown here. </p> <p><img src="/sites/all/files/tutorials/coloredDots/screen1listpicker.PNG" /></p> <h4 class="ai-header">Blocks for the Brush_Picker screen</h4> <p>The main job of <b>Brush_Picker</b> is to create a color from the red-green-blue values entered in the text boxes and provide that color to <b>Screen1</b>. When you click ReturnToPainting the new color, the new dot size (taken from the RadiusTextBox), and the total number of colors are returned to <b>Screen1</b> as a three-item list.As mentioned above, when Brush_Picker is open, Screen1 passes it values of the current color, the number of colors, and the current dot radius size. <b>Brush_Picker</b> uses <span class="controlblock">get start value</span> when it is initialized to access these values.</p> <p>When you click the TestColorButton, the color is created for you as the background of LabelTestColorSample and the Canvas shows a circle of the appropriate size and color. To return the list to Screen1, <b>Brush_Picker</b> uses <span class="controlblock">close screen with value</span>, which takes as an argument the value to be returned (in this case, the list). When a screen closes, the app returns to the screen that opened it.</p> <p>Here are the blocks that do this. <b>Brush_Picker</b> uses the procedures <span class="callblock">CheckColor</span> and <span class="callblock">LimitRange</span> to ensure that the values entered in the text boxes are valid numbers for colors and dot size. We'll examine these procedure below."</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickercommunicate.PNG" /></p> <p>When TestColorButton is clicked, is displays the created color. Notifier1 is then used to give you a choice to save the color or cancel using the <span class="basicblock">Notifier1.ShowChooseDialog</span> block. The response from this will trigger further Notifier events so that you can save the color.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickertestcolor.PNG" /></p> <p>The next blocks show how Brush_Picker associates a name with a color for use by Screen1. The <span class="basicblock">Notifier1.ShowChooseDialog</span> block triggers a <span class="basicblock">Notifier1.AfterChoosing</span> event. In these blocks, the <b>ifelse</b> block checks the response to whether or not the color should be saved. If the response is "OK," <span class="basicblock">Notifier1.AfterChoosing</span> calls <span class="basicblock">Notifier1.ShowTextDialog</span> which prompts you to store a name for this color.</p> <p>Once you make your entry, the color is stored with two tags two ways in TinyDB1. First, it stores the name with the current number of colors as the key. This is used when iterating through the list of colors for ListPicker in <b>Screen1</b> so that the names will be displayed for the user. Secondly, the color is stored in TinyDB, using the name you entered as a key. <b>Screen1</b> can then retrieve the color using its own TinyDB component and access it via the stored name as chosen in ListPicker.</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerstorecolor.PNG" /></p> <p>The Reset button allows the user to clear all of the entries in the red, green, and blue fields so they can start over easily. The blocks for this are shown here:</p> <p><img src="/sites/all/files/tutorials/coloredDots/brushpickerresetcolor.PNG" /></p> <h4 class="ai-header">Limiting numbers to a range</h4> <p>The only thing left is to show how <b>Brush_Picker</b> checks that it's using good values for colors and dot size. Each of the red, green, blue values should be a number between 0 and 255. But you could have entered anything in those text boxes. The <span class="callblock">checkColor</span> procedure takes a value and limits its range to between 0 and 255: If it's less than 0 (or not a number at all) the result will be 0. It it's greater than 255, the result will be 255:</p> <p><img src="/sites/all/files/tutorials/coloredDots/checkColor.png" /></p> <p>The final bit is <span class="callblock">LimitRange</span>. This is a general procedure that takes an input, a lower limit, and an upper limit, and restricts the input to lie within that range (and it returns the lower limit if the input is not a number). The procedure is simple, but tricky: To restrict the range, take the maximum of the input and the lower limit, then take the minimum of the result and the upper limit. This programming "trick" has little to do with multiple screens or App Inventor. You might want to take a few moments to convince yourself that it really works.</p> <p><img src="/sites/all/files/tutorials/coloredDots/LimitRange.png" /></p> <h4 class="ai-header">Comments on multiple screens</h4> <p>You can have many screens in an App Inventor app, but a screen always returns to the screen that opened it. On the other hand, you can get the effect of screens switching to arbitrary other screen by setting up a "manager screen" that is used for opening all the other screens. When a screen wants to switch, it returns to the manager with a value saying which screen to open next.</p> <pre class="ai-testing"><b>Testing the behavior.</b> In the current version of App Inventor, it is not yet possible to test a multiple-screen app in live development mode. You can test each screen separately, but you cannot test the communication between two screens. When try to switch between screens, you'll get an error message. To test whether the screens are properly communicating, you'll need to <b>Package for Phone</b> and open the installed app.</pre><h4 class="ai-header">Further exploration</h4> <p>Now that you are able to create your own colors and access them for drawing, try some variations!</p> <ul><li>Make Brush_Picker warn the user if they are trying to store a color with the same name as something that has already been stored (e.g. don't let them make two colors named "red"). </li><li>Have the starting color be the last one that the user was using in the app instead of always starting with black. </li></ul><h4 class="ai-header">Summary</h4> <p>In this tutorial you have learned:</p> <ul><li>How to make an app with multiple screens</li> <li>How to share data between those two screens using <b>TinyBD</b></li> <li>How to use a counter to add all of the values in <b>TinyDB</b> to add to a list.</li> <li>How to use <b>ListPicker</b> to select from a list of items</li> </ul><pre class="ai-box">This tutorial is based on work by Eni Mustafaraj of Wellesley College. Done with <span style="color:black;">Colored Dots</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/drawing-canvas" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Drawing Canvas</a> </li> <li class="field-item odd"> <a href="/tutorial-type/multiple-screens" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Multiple Screens</a> </li> </ul> </section> Fri, 14 Jun 2013 15:47:16 +0000 aaron 310 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/colored-dots#comments