Aquest tutorial estén el tutorial Text Group. L’aplicació enviava un missatge de text a una llista fixa de números de telèfon, i només el programador podia canviar els números de la llista. L’aplicació en aquest tutorial permet a l’usuari afegir i treure números de telèfon de la llista, i emmagatzema la llista de manera permanent en una base de dades. 
Primers passos
Connecta’t al lloc web de App Inventor i obre el teu projecte textgroup (si no has completat aquest tutorial, fes-ho ara abans de continuar). Fes clic a SaveAs (guardar com) i anomeneu “TextGroup2”. Pots deixar eltítol de la pantalla com “Text Group”. Obre l’editor de blocs i conéctalo al telèfon.
Introducció
Dissenyaràs l’aplicació perquè l’usuari afegeixi números de telèfon al grup triant-los de la llista de contactes del telèfon, i pugui llevar triant elements que ja estiguin en el grup. Almacenaras la llista de nombres en una base de dades perquè estiguin disponibles fins i tot després de tancar l’aplicació i reiniciar.
El tutorial cobreix els següents components i conceptes de App Inventor:
- El bloc foreach per repetir operacions en una llista.
- El component PhoneNumberPicker per accedir als contactes del telèfon.
- El component ListPicker per permetre a l’usuari triar un número de la llista per treure’l.
- El component texting per enviar missatges de text.
- El component base de dades TinyDB per emmagatzemar la llista de números de telèfon en una base de dades.
Prepara els components
La interfície d’usuari per Text Group, Part II té una caixa de text, un botó, i una etiqueta d’estat per a l’enviament del missatge al grup, igual que en la part I. Si has triat SaveAs per iniciar aquest projecte, aquests components han d’estar ja en la pantalla. Si és així, has de llavors afegir un component PhoneNumberPicker i un component ListPicker per afegir i treure números de telèfon de la llista, juntament amb un component texting i un component TinyDB, els quals apareixeran al camp “non-visual components” (components no visibles). A sota hi ha una taula amb instruccions detallades per al disseny dels components, però pots també construir-la a partir la la següent imatge de com haurien de quedar:

Els components que es mostren a continuació són els usats per crear la pantalla del dissenyador mostrada més amunt. Els quatre primers eren part del projecte TextGroup pel que ja haurien d’estar a la pantalla del dissenyador si has fet clic a SaveAs (guardar com) per iniciar aquest. Necessitaràs arrossegar cada un dels altres components des de la Paleta al Visor i nomenar com s’especifica a continuació:
| Tipus de component | Grup de la paleta | Com ho diràs | Propòsit del component |
| TextBox | Basic | MessageText | L’usuari introduirà el missatge aquí. |
| Button | Basic | TextGroupButton | S’enviarà el missatge fent clic aquí |
| Label | Basic | StatusLabel | Informa quan el missatge ha estat enviat. |
| Texting | Social | Texting1 | El component que envia el missatge. |
| Label | Basic | GroupHeadingLabel | Capçalera per a la llista de números de telèfon que apareixeran |
| Label | Basic | MembersLabel | Aquí és on apareixerà la llista de números de telèfon |
| Horitzontal Arrangement | Screen Arrangement | Horitzontal Arrangement1 | Per organitzar horitzontalment els botons (pickers) per afegir i treure |
| PhoneNumberPicker | Social | PhoneNumberPicker1 | Permet a l’usuari triar números de la llista de contactes |
| ListPicker | Basic | RemoveListPicker | Permet a l’usuari treure un nombre dels números de telèfon del grup |
| TinyDB | Basic | TinyDB1 | Per emmagatzemar i recuperar els números de telèfon del grup des d’una base de dades |
Ajusta les propietats dels components de la manera:
- Ajusta Hint (suggeriment) de MessageText a “enter a message” (introdueix un missatge)
- Ajusta Text de TextGroupButton a “Text Group”
- Canvia la propietat Text de StatusLabel a “estatus”.
- Ajusta Text de GroupHeadingLabel a “- Group -“.
- Ajusta Text de MembersLabel a “members will appear here” (els membres apareixeran aquí).
- Ajusta Text de PhoneNumberPicker1 a “Add Member” (afegir membre).
- Canvia Text de RemoverListPicker a “Remove Member” (treure membre)
Afegeix comportaments als components
Si has completat Text Group, Part I, has de tenir la següent llista definida en l’editor de blocs:

Per aquesta aplicació, encara necessitaràs la llista però no amb nombres predefinits-hi – els números seran afegits per l’usuari de l’aplicació. Per tant treu els blocs de de text amb els nombres i deixa el bloc make a list buit:

Necessitaràs afegir els següents comportaments:
1. Quan l’usuari fa clic al botó “Add Member” (el botó afegir membre associat amb el selector PhoneNumberPicker), el selector apareixerà perquè l’usuari triï un nombre. Quan la selecció estigui feta, l’aplicació afegirà el nombre escollit a la llista PhoneNumbers i actualitzarà la base de dades.
2. Quan l’usuari fa clic al botó “Remove Member” (el botó treure membre associat al selector RemovListPicker), el selector apareixerà perquè l’usuari triï un dels nombres existents en PhoneNumbers. Quan la selecció estigui feta, l’aplicació traurà el número de la llista i actualitzarà la base de dades.
3. Quan l’aplicació s’inicia, els números emmagatzemats a la base de dades es recuperen i es carreguen en PhoneNumbers.
Afegint un número de telèfon (membre) al grup
La llista de números de telèfon a la llista de contactes apareixerà quan l’usuari faci clic a botó associat a PhoneNumberPicker: aquest comportament està inclòs en el component. Quan l’usuari fa una selecció de la llista de contactes, l’esdeveniment AfterPicking de PhoneNumberPicker s’inicia – el teu treball és programar aquest esdeveniment per afegir l’element seleccionat a la llista i actualitzar la base de dades.
Necessitaràs els següents blocs:
| Tipus de bloc | Calaix | Propòsit |
| PhoneNumberPicker1.AfterPicking | PhoneNumberPicker1 | el controlador d’esdeveniment que és iniciat quan l’usuari tria de la llista de contactes |
| add items to list | Lists | el teu objectiu és afegir el nombre escollit a la llista |
| global PhoneNumbers | My Definitions | posi el a la ranura list de add ítems to list |
| PhoneNumberPicker1.PhoneNumber | PhoneNumberPicker1 | això manté el número de telèfon triat, col · loca a la ranura ítem de add items to list (afegir element a la llista) |
| TinyDB1.StoreValue | TinyDB1 | després d’actualitzar la llista, necessites actualitzar la base de dades. |
| text (“textGroup”) | Text | col · loca a la ranura tag de StoreValue |
| global PhoneNumbers | My Definitions | posi el a la ranura value (valor) de StoreValue |
| setembre MembersLabel.Text to | MembersLabel | mostra la llista al telèfon |
| global PhoneNumbers | My Definitions | col · loca en set MembersLabel.Text to |
Els blocs han de quedar així:

Com treballen els blocs
Quan l’usuari fa una elecció des PhoneListPicker, l’esdeveniment PhoneListPicker1.AfterPicking s’inicia. Un dels treballs de PhoneListPicker ‘és col · locar l’elecció de l’usuari en la seva propietat PhoneNumber, de manera que el controlador d’esdeveniment crida a add items to list (afegir elements a la llista) per col · locar l’elecció en la llista PhoneNumbers.
PhoneNumbers és una variable, i les variables són memòries de curta durada que desapareixen quan es tanca l’aplicació. És per això que, després d’afegir l’element a la variable, s’usa el bloc TinyDB1.StoreValue per copiar aquesta llista a la base de dades – la memòria de llarga durada del telèfon. Les dades s’etiqueten com “textGroup”. Més tard, usaràs aquesta etiqueta per recarregar la llista de números de telèfon des de la base de dades cada vegada que s’iniciï l’aplicació.
Després d’actualitzar la base de dades, es diu a set MembersLabel.Text to per mostrar la llista. Això és requerit per que aquestes variable de llista estan ocultes per a l’usuari fins que es col · loquen en un element visible. Col · locar directament la llista en una etiqueta és un mètode rudimentari de mostrar – la llista apareixerà amb la forma (111-1111 222-2222). A la següent secció, programarás una manera més elegant de mostrar la llista.
Prova el comportament. Al telèfon fes clic a “Add Member” i tria un número de la llista de contactes que apareix. Apareix el número en MembersLabel? Prova a afegir alguns nombres més per veure com es mostra la llista.
Mostrant la llista amb els elements en línies separades
En aquest moment l’aplicació mostra a l’usuari els números de telèfon que s’han afegit, però no d’una manera molt elegant. Crea un procediment displayMembers, el qual mostri la llista cada telèfon en una línia separada. Assegura’t i crida al procediment en l’esdeveniment PhonePicker1.AfterPicking, event, després del bloc add items to list, per mostrar la llista actualitzada. La crida al procediment ha de substituir els blocs que col · loquen MembersLabel.Text directament a la llista. Per obtenir ajuda per mostrar la llista i línies separades, mira Displaying a List
Necessitaràs els següents blocs:
| Tipus de bloc | Calaix | Propòsit |
| procedure (“displayMembers”) | Definitions | crea un procediment perquè puguis dir des de múltiples llocs |
| setembre MembersLabel.Text to | MembersLabel | Mostra la llista aquí |
| text (“”) | Text | comença amb un text buit |
| foreach | Control | Es repeteix per als nombres |
| name number | in the foreach | nomena la variable foreach “number ‘. És l’element actual de foreach |
| global PhoneNumbers | My Definitions | Es col · loca a la ranura in list de foreach |
| setembre MembersLabel.Text to | MembersLabel | Es modifica amb cada un dels nombres |
| make text | Text | Crea un objecte de text des de diverses peces |
| MembersLabel.Text | MembersLabel | S’afegeix a l’etiqueta en cada repetició de foreach |
| text (“\ n”) | Text | El caràcter de nova línia, perquè el següent nombre aparegui en una nova línia |
| value number | My Definitions | El nombre actual de la llista |
Així és com han de quedar els blocs:

Com treballen els blocs
El bloc foreach en displayMembers successivament afegeix un número de telèfon al final de l’etiqueta, col · locant un caràcter nova línia entre cada element.
Per descomptat ens procediment no farà res fins que tu ho diguis: has d’afegir una crida al procediment en l’esdeveniment PhonePicker1.AfterPicking, per sota del bloc add items to list. El bloc call displayMembers pots trobar al calaix My Definitions, i ha de substituir als blocs que posen directament a MembersLabel.Text a la llista.
Prova aquest comportament. Al telèfon fes clic a “Add Member” per triar un altre nombre d’afegir a la llista. Quan es mostra la llista modificada, Apareixen els nombres en línies separades?
Llevant un número de la llista
Per permetre a l’usuari treure un número de la llista, primer has de tenir la llista PhoneNumbers al gestor RemoveListPicker que apareix quan l’usuari fa clic a “Remove Member”. A diferència del component PhonePicker, el qual pren les dades de lalista de contactes del telèfon, ListPicker requereix explícitament que el teu carreguis els elements que apareixeran. Pots fer això canviant la propietat Elements del component ListPicker. Faràs això dins de l’esdevenimentRemoveListPicker.BeforePicking, el qual és iniciat just quan l’usuari fa clic al botó però abans de mostrar la llista.
Els blocs han de quedar així:

A continuació, crea l’esdeveniment RemoveListPicker.AfterPicking perquè la selecció de l’usuari sigui llevada de la llista PhoneNumbers. Necessitaràs els següents blocs:
| Tipus de bloc | Calaix | Propòsit |
| RemoveListPicker.AfterPicking | RemoveListPicker | aquest s’inicia després que l’usuari triï un número de la llista |
| remove list item | Lists | treu l’element indicat d’una llista donada |
| global PhoneNumbers | My Definitions | col · loca a la ranura list de remove list item |
| position in list | Lists | donat un element a una llista, aquest t’indica seu índex (la seva posició en la llista) |
| RemoveListPicker.Selection | RemoveListPicker | el nombre escollit per l’usuari, col · loca a la ranura thing de position in list |
| global PhoneNumbers | My Definitions | col · loca a la ranura list de position in list |
| call displayMembers | My Definitions | una vegada que l’usuari treu un element, mostra la llista modificada |
Els blocs han de quedar així:

Com treballen els blocs
Quan l’usuari tria un nombre de RemoveListPicker, l’esdeveniment AfterPicking és iniciat. El controlador d’esdeveniment fa servir position in list per obtenir la posició en la llista del nombre triat, llavors utilitza aquesta posició per treure el número de la llista PhoneNumbers. La base de dades és actualitzada i la llista mostrada.
Prova el comportament. Al telèfon fes clic a “Remove Member” i tria un número de la llista que apareix. Quan la llista torna a aparèixer, S’ha tret el nombre triat?
Carregant la llista des de la base de dades
L’aplicació funciona fins ara, i quan es realitzen canvis en la llista PhoneNumbers, aquests són també emmagatzemats a la base de dades. Ara només necessites afegir el comportament perquè les dades guardats a la base de dades es carreguin quan s’iniciï l’aplicació.
Programa el controlador d’esdeveniment Screen1.Initialize perquè la llista de números de telèfon guardada sigui presa de la base de dades i col · locada en la llistaPhoneNumbers i la pantalla s’actualitzi per mostrar la llista. Necessitaràs comprovar les dades obtingudes per assegurar-te que hi ha algun – això és perquè la primera vegada que s’usa l’aplicació, la base de dades no conté cap número.
Necessitaràs els següents blocs:
| Tipus de bloc | Calaix | Propòsit |
| def variable (“valueFromDB”) | Definitions | Una variable temporal per emmagatzemar les dades recuperats |
| text (buit) | Text | El valor inicial de la variable pot ser qualsevol cosa |
| Screen1.Initialize | Screen1 | Aquest és activat quan s’inicia l’aplicació |
| setembre valueFromDB to | My Definitions | canviessis la variable el valor recuperat de la base de dades |
| TinyDB1.GetValue | TinyDB1 | pren la resposta de text emmagatzemada a la base de dades |
| text (“textGroup”) | Text | col · loca a la ranura tag de GetValue, assegura’t que el text és el mateix que es va usar més amunt en StoreValue |
| if test | Control | per preguntar si el valor recuperat conté algun text |
| is list? | Text | comprova si el valor retornat és una llista (si no hi ha dades retornats, això serà fals) |
| global valueFromDB | My Definitions | aquesta variable manté el valor retornat des GetValue |
| setembre PhoneNumbers to | PhoneNumbers | si se’ns torna una mica, el col · loca en PhoneNumbers |
| global valueFromDB | My Definitions | aquesta variable manté el valor retornat des GetValue |
Els blocs han de quedar així:

Com treballen els blocs
Quan s’inicia l’aplicació, l’esdeveniment Screen1.Initialize és activat. El controlador d’esdeveniment pregunta a la base de dades amb GetValue i l’etiqueta (tag) “textGroup”. Si hi ha algun valor amb aquesta etiqueta a la base de dades, el seu valor corresponent es col · locarà en la variable valueFromDB. El controlador d’esdeveniment comprova si aquest valor – és una llista? – I si és així col · loca la llista en la variable PhoneNumbers i crida a displayMembers.
Prova l’aplicació. Per provar l’aplicació final, primer empaquétala, instal · la en un telèfon i ejecútala. Tastar “en viu” no funcionarà en aquest cas, perquè cada vegada que “reinicieu l’aplicació”, esborrarà la base de dades: fins i tot si has emmagatzemat les dades de forma persistent, seran esborrats quan reinicieu l’aplicació. Surt de l’aplicació i torna a arrencar perquè es reiniciï. Hi surt la llista de telèfons que has introduït al recarregar? Treu tots els elements i prova un altre cop. ¿S’inicia l’aplicació sense cap error?
Text Group Part II, programa final

Variacions
UNa vegada que tinguis l’aplicació Text Group treballant, potser vulguis explorar algunes variacions. Per exemple.
- Escriu una versió que gravi tots dos, el número de telèfon i el nom de cada membre del grup. Pots també utilitzar ContactPicker per permetre a l’usuari triar des del nom d’un contacte en lloc d’un nombre.
- Escriu una versió que permeti a usuari definir i utilitzar múltiples grups. Necessitaràs una llista en la qual cada element sigui una llista de contactes / números, i necessitaràs una interfície d’usuari més complexa.
Revisió
Aquestes són algunes de les idees examinades en aquest tutorial:
- PhoneListPicker permet a l’usuari triar de la llista de números de telèfon dels seus contactes. L’elecció es col · loca en la propietat Selection i l’esdeveniment AfterPicking és anomenat quan l’usuari fa una elecció.
- ListPicker és similar a PhoneListPicker però mostra una llista definida pel programador, per exemple, la llista de números de telèfon al grup. La teva defineixes la llista que apareixerà a ListPicker ajustant la propietat Elements, i pots fer-ho a l’esdeveniment BeforePicking. L’elecció de l’usuari es col · loca en la propietat Selection, i l’esdeveniment AfterPicking s’inicia quan l’usuari fa una elecció.
- TinyDB s’usa per emmagatzemar les dades de manera persistent i que puguin ser carregats cada vegada que s’iniciï l’aplicació. StoreValue emmagatzema amb una etiqueta (tag) per identificar a la dada i la dada en si mateix (el valor). GetValue retorna les dades d’una etiqueta donada. Sovint, una aplicació cridarà GetValue quan l’aplicació s’iniciï (Screen1.Initialize) per carregar les dades persistents.
- Actualment, App Inventor no proveeix accés i funcionalitat complets per als contactes i grups al telèfon. En aquest tutorial, has creat el teu propi grup i una aplicació per processar el grup (afegint, traient i enviant missatges a tots).
Escaneja l’aplicació d’exemple per al teu telèfon
Escaneja el codi Qr amb el teu telèfon per instal · lar i executar l’aplicació d’exemple.
