Esercizio: creare l'app di conversione dei numeri di telefono

Completato

In questo esercizio si crea l'interfaccia utente per l'app di composizione telefonica e si implementa la logica sottostante.

Viene creata un'interfaccia utente che sfrutta le funzionalità dell'interfaccia utente di .NET MAUI (interfaccia utente dell'applicazione multipiattaforma) e del pacchetto .NET MAUI Essentials per comporre un numero di telefono.

L'app consente all'utente di digitare del testo in un campo di input e converte tale testo in cifre numeriche. Usa le lettere presenti sul tastierino di un telefono come base per la conversione. Ad esempio, le lettere cab vengono convertite in 222 perché la cifra 2 contiene tutte e tre le lettere a, b e c.

Si continua con la soluzione Phoneword creata nell'esercizio precedente.

Aggiungere un nuovo file di origine C# all'app

  1. Aprire la soluzione Phoneword in Visual Studio, se non è già aperta.

  2. Nella finestra Esplora soluzioni fare clic con il pulsante destro del mouse sul progetto Phoneword, scegliere Aggiungi e selezionare Classe.

  3. Nella finestra di dialogo Aggiungi nuovo elemento assegnare al file di classe il nome PhonewordTranslator.cs e quindi selezionare Aggiungi.

    Uno screenshot della finestra di dialogo Aggiungi nuovo elemento. L'utente ha denominato il file di classe PhonewordTranslator.cs

Aggiungere la logica di conversione

Sostituire il contenuto del file di classe con il codice seguente e salvare il file. Il metodo statico ToNumber nella classe PhonewordTranslator converte il numero da testo alfanumerico in un normale numero di telefono composto di soli numeri.

using System.Text;

namespace Core;

public static class PhonewordTranslator
{
    public static string ToNumber(string raw)
    {
        if (string.IsNullOrWhiteSpace(raw))
            return null;

        raw = raw.ToUpperInvariant();

        var newNumber = new StringBuilder();
        foreach (var c in raw)
        {
            if (" -0123456789".Contains(c))
                newNumber.Append(c);
            else
            {
                var result = TranslateToNumber(c);
                if (result != null)
                    newNumber.Append(result);
                // Bad character?
                else
                    return null;
            }
        }
        return newNumber.ToString();
    }

    static bool Contains(this string keyString, char c)
    {
        return keyString.IndexOf(c) >= 0;
    }

    static readonly string[] digits = {
        "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"
    };

    static int? TranslateToNumber(char c)
    {
        for (int i = 0; i < digits.Length; i++)
        {
            if (digits[i].Contains(c))
                return 2 + i;
        }
        return null;
    }
}

Creare l'interfaccia utente

  1. Aprire il file MainPage.xaml nel progetto Phoneword.

  2. Rimuovere il controllo ScrollView e il relativo contenuto, lasciando solo il controllo ContentPage:

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Phoneword.MainPage">
    
    </ContentPage>
    
  3. Aggiungere un controllo VerticalStackLayout con orientamento verticale, una spaziatura di 15 unità e una spaziatura interna di 20 unità a ContentPage:

    <ContentPage ... >
        <VerticalStackLayout Spacing="15" Padding="20">
    
        </VerticalStackLayout>
    </ContentPage>
    
  4. Aggiungere un controllo Label a StackLayout:

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label Text = "Enter a Phoneword"
                   FontSize ="20"/>
        </VerticalStackLayout>
    </ContentPage>
    
  5. Aggiungere un controllo Entry a StackLayout, sotto l'etichetta. Un controllo Entry fornisce una casella di testo in cui l'utente può immettere dati. In questo codice la proprietà x:Name assegna un nome al controllo. Si fa riferimento a questo controllo nel codice dell'app in un secondo momento:

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label .../>
            <Entry x:Name = "PhoneNumberText"
                   Text = "1-555-NETMAUI" />
        </VerticalStackLayout>
    </ContentPage>
    
  6. Aggiungere due controlli Button a VerticalStackLayout, dopo il controllo Entry. Entrambi i pulsanti attualmente non eseguono operazioni e il secondo è inizialmente disabilitato. Il codice per gestire l'evento Clicked per questi due pulsanti viene aggiunto nell'attività successiva:

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label .../>
            <Entry ... />
            <Button x:Name = "TranslateButton"
                    Text = "Translate"
                    Clicked = "OnTranslate"/>
            <Button x:Name = "CallButton"
                    Text = "Call"
                    IsEnabled = "False"
                    Clicked = "OnCall"/>
        </VerticalStackLayout>
    </ContentPage>
    

Rispondere al tocco del pulsante TranslateButton

  1. Nella finestra Esplora soluzioni espandere la voce MainPage.xaml e aprire il file code-behind MainPage.xaml.cs.

  2. Nella classe MainPage rimuovere la variabile count e il metodo OnCounterClicked. La classe dovrebbe risultare simile alla seguente:

    namespace Phoneword;
    
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
    
  3. Aggiungere la variabile di stringa translatedNumber e il metodo OnTranslate seguente alla classe MainPage, dopo il costruttore. Il metodo OnTranslate recupera il numero di telefono dalla proprietà Text del controllo Entry e lo passa al metodo statico ToNumber della classe PhonewordTranslator creata in precedenza.

    public partial class MainPage : ContentPage
    {
        ...
        string translatedNumber;
    
        private void OnTranslate(object sender, EventArgs e)
        {
            string enteredNumber = PhoneNumberText.Text;
            translatedNumber = Core.PhonewordTranslator.ToNumber(enteredNumber);
    
            if (!string.IsNullOrEmpty(translatedNumber))
            {
                // TODO:
            }
            else
            {
                // TODO:
            }
        }
    }
    

    Nota

    I bit TODO mancanti di questo codice vengono compilati nel passaggio successivo.

  4. Nel metodo OnTranslate aggiungere codice per modificare la proprietà Text del pulsante Call in modo da accodare il numero di telefono convertito. È possibile usare il valore archiviato nel campo translatedNumber. Abilitare e disabilitare inoltre il pulsante in base alla riuscita della conversione. Ad esempio, se TranslateNumber ha restituito Null, disabilitare il pulsante. Se invece l'operazione è riuscita, abilitarlo.

    private void OnTranslate(object sender, EventArgs e)
    {
        string enteredNumber = PhoneNumberText.Text;
        translatedNumber = Core.PhonewordTranslator.ToNumber(enteredNumber);
    
        if (!string.IsNullOrEmpty(translatedNumber))
        {
            CallButton.IsEnabled = true;
            CallButton.Text = "Call " + translatedNumber;
        }
        else
        {
            CallButton.IsEnabled = false;
            CallButton.Text = "Call";
        }
    }
    

Creare il metodo dell'evento per il pulsante CallButton

  1. Aggiungere il metodo di gestione degli eventi OnCall alla fine della classe MainPage. Questo metodo usa operazioni asincrone, contrassegnarlo quindi come async:

    public partial class MainPage : ContentPage
    {
    
        ...
        async void OnCall(object sender, System.EventArgs e)
        {
    
        }
    }
    
  2. Nel metodo OnCall chiedere all'utente, usando il metodo Page.DisplayAlert, se vuole comporre il numero.

    I parametri per DisplayAlert sono un titolo, un messaggio e due stringhe usate per il testo dei pulsanti Accept e Cancel. Restituisce un valore booleano che indica se il pulsante Accept è stato selezionato per chiudere la finestra di dialogo.

    async void OnCall(object sender, System.EventArgs e)
    {
        if (await this.DisplayAlert(
            "Dial a Number",
            "Would you like to call " + translatedNumber + "?",
            "Yes",
            "No"))
        {
            // TODO: dial the phone
        }
    }
    

Testare l'applicazione

  1. Nella barra degli strumenti di Visual Studio selezionare il profilo Computer Windows e avviare il debug.

  2. Toccare il pulsante Translate per convertire il testo predefinito in un numero di telefono valido. La didascalia sul pulsante Call dovrebbe cambiare in Call 1-555-6386284:

    Uno screenshot dell'interfaccia utente di Phoneword. L'utente ha tradotto il testo in un numero di telefono valido.

  3. Toccare il pulsante Call. Verificare che venga visualizzata una richiesta di conferma dell'operazione. Selezionare No.

    Screenshot del comando Dial a Number dell'interfaccia utente di Phoneword.

  4. Tornare in Visual Studio e interrompere il debug.

Comporre il numero di telefono

  1. Nel file code-behind MainPage.xaml.cs modificare il metodo OnCall e sostituire il commento TODO con i blocchi try/catch seguenti:

    async void OnCall(object sender, System.EventArgs e)
    {
        if (await this.DisplayAlert(
            "Dial a Number",
            "Would you like to call " + translatedNumber + "?",
            "Yes",
            "No"))
        {
            try
            {
                if (PhoneDialer.Default.IsSupported)
                    PhoneDialer.Default.Open(translatedNumber);
            }
            catch (ArgumentNullException)
            {
                await DisplayAlert("Unable to dial", "Phone number was not valid.", "OK");
            }
            catch (Exception)
            {
                // Other error has occurred.
                await DisplayAlert("Unable to dial", "Phone dialing failed.", "OK");
            }
        }
    }
    

    La classe PhoneDialer nello spazio dei nomi Microsoft.Maui.ApplicationModel.Communication fornisce un'astrazione della funzionalità di composizione del numero di telefono (e altre) per le piattaforme Windows, Android, iOS (e iPadOS) e macOS. Il metodo Open statico tenta di usare il sistema di composizione telefonica per chiamare il numero fornito come parametro.

    La procedura seguente illustra come aggiornare il manifesto dell'applicazione Android per consentire ad Android di usare il sistema di composizione telefonica. Per Windows, iOS e MacCatalyst, le applicazioni seguono lo stesso principio generale, tranne per il fatto che va specificata una diversa funzionalità dipendente dal sistema operativo nel manifesto.

  2. Nella finestra Esplora soluzioni espandere la cartella Piattaforme, espandere la cartella Android, fare clic con il pulsante destro del mouse sul file AndroidManifest.xml e scegliere Apri con>selettore editor automatico (XML). Seleziona OK.

  3. Aggiungere il frammento di codice XML seguente all'interno del nodo manifest, dopo il contenuto esistente per questo nodo.

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android">
        ...
        <queries>
            <intent>
                <action android:name="android.intent.action.DIAL" />
                <data android:scheme="tel"/>
            </intent>
        </queries>
    </manifest>
    
  4. Salvare il file.

  5. Nella barra degli strumenti di Visual Studio selezionare il profilo Emulatori Android/Pixel 3a - API 30 (o analogo) e avviare il debug.

  6. Quando l'app viene visualizzata nell'emulatore (questo può richiedere alcuni minuti), immettere un numero di telefono (o accettare il valore predefinito), selezionare Converti, quindi selezionare Chiama.

  7. Nell'avviso Dial a Number selezionare Yes. Verificare che il sistema di composizione telefonica di Android venga visualizzato con il numero specificato nell'app.

    Il sistema di composizione telefonica di Android contenente il numero fornito dall'app.

  8. Tornare in Visual Studio e interrompere il debug.

Riepilogo

In questo esercizio è stata aggiunta all'applicazione un'interfaccia utente personalizzata usando pagine e visualizzazioni. È anche stato aggiunto il supporto per l'esecuzione di una chiamata tramite API specifiche della piattaforma disponibili in Android.