Упражнение. Создание приложения-переводчика номеров телефона

Завершено

В этом упражнении вы создадите пользовательский интерфейс для приложения телефонного абонента и реализуйте логику этого пользовательского интерфейса.

Вы создадите пользовательский интерфейс, который использует возможности пользовательского интерфейса .NET MAUI и пакет .NET MAUI Essentials для набора номера телефона.

Приложение позволит пользователю вводить текст в поле ввода и преобразует этот текст в цифры. Оно будет использовать буквы, которые отображаются на клавиатуре телефона в качестве основы для перевода. Например, кабина букв переводится на 222, так как цифра 2 имеет все три буквы a, b и c.

Мы продолжим работу с решением Phoneword, созданным в предыдущем упражнении.

Добавление нового исходного файла C# в приложение

  1. Откройте решение Phoneword в Visual Studio, если это еще не сделано.

  2. В окне Обозреватель решений щелкните правой кнопкой мыши проект Телефон word, выберите "Добавить" и выберите "Класс".

  3. В диалоговом окне "Добавить новый элемент" назовите файл класса Телефон word Переводчик.cs, а затем нажмите кнопку "Добавить".

    A screenshot of the Add new item dialog box. The user has named the class file PhonewordTranslator.cs

Добавление логики преобразования

Замените содержимое файла класса следующим кодом и сохраните файл. Статический PhonewordTranslator метод ToNumber в классе преобразует число из буквенно-цифрового текста в обычный числовый номер телефона.

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;
    }
}

Создание пользовательского интерфейса

  1. Откройте файл MainPage.xaml в проекте Phoneword.

  2. Удалите элемент управления ScrollView и его содержимое, оставив только элемент управления 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. Добавьте в ContentPage элемент управления VerticalStackLayout с вертикальной ориентацией, интервалом в 15 единиц и заполнением 20 единиц:

    <ContentPage ... >
        <VerticalStackLayout Spacing="15" Padding="20">
    
        </VerticalStackLayout>
    </ContentPage>
    
  4. Добавьте элемент управления Label в StackLayout:

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label Text = "Enter a Phoneword"
                   FontSize ="20"/>
        </VerticalStackLayout>
    </ContentPage>
    
  5. Добавьте элемент управления Entry в StackLayout под меткой. Элемент управления Entry предоставляет текстовое поле, в которое пользователь может вводить данные. В этом коде свойство x:Name присваивает имя элементу управления. Позже вы будете ссылаться на этот элемент управления в коде приложения:

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label .../>
            <Entry x:Name = "PhoneNumberText"
                   Text = "1-555-NETMAUI" />
        </VerticalStackLayout>
    </ContentPage>
    
  6. Добавьте два элемента управления Button в VerticalStackLayout, после элемента управления Entry. Обе кнопки в настоящее время не выполняют никаких действий, а вторая была изначально отключена. Теперь вы добавите код для обработки события Clicked для этих двух кнопок в следующей задаче:

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

Ответ на нажатие кнопки TranslateButton

  1. В окне Обозреватель решений разверните запись MainPage.xaml и откройте файл кода MainPage.xaml.cs.

  2. В классе MainPage удалите переменную count и метод OnCounterClicked. Класс должен выглядеть следующим образом:

    namespace Phoneword;
    
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
    
  3. Добавьте строковую переменную translatedNumber и следующий метод OnTranslate в класс MainPage после конструктора. Метод OnTranslate извлекает номер телефона из Text свойства Entry элемента управления и передает его в статический ToNumber метод созданного PhonewordTranslator ранее класса.

    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:
            }
        }
    }
    

    Примечание.

    На следующем шаге вы заполните недостающие элементы кода, которые мы отложили на будущее.

  4. Добавьте в метод OnTranslate код, который изменяет свойство Text для кнопки Вызов, чтобы отображать успешно переведенный номер телефона. Вы можете использовать значение, сохраненное в поле translatedNumber. Кнопка включается и отключается в зависимости от успешности преобразования. Например, если TranslateNumber возвращает ноль, кнопка отключается, а если преобразование успешно — включается.

    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";
        }
    }
    

Создание метода события для кнопки CallButton

  1. Добавьте метод обработки событий OnCall в конец класса MainPage. Этот метод будет использовать асинхронные операции, поэтому помечайте его как async:

    public partial class MainPage : ContentPage
    {
    
        ...
        async void OnCall(object sender, System.EventArgs e)
        {
    
        }
    }
    
  2. В методе OnCall попросите пользователя, используя метод Page.DisplayAlert , попросить, хотите ли они набирать номер.

    В DisplayAlert передаются параметры заголовка, сообщения и две строки, используемые в качестве текста для кнопок подтверждения и отмены. Он возвращает логическое значение, указывающее, нажата ли кнопка "Принять", чтобы закрыть диалоговое окно.

    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
        }
    }
    

Тестирование приложения

  1. На панели инструментов Visual Studio выберите профиль Компьютер с Windows и начните отладку.

  2. Нажмите кнопку Перевести, чтобы преобразовать текст по умолчанию в допустимый номер телефона. Подпись кнопки Вызов должна измениться на Вызов 1-555-6386284:

    A screenshot of the Phoneword UI. The user has translated the text to a valid phone number.

  3. Нажмите кнопку Вызов. Убедитесь, что появился запрос на подтверждение операции. Выберите Нет.

    A screenshot of the PhoneWord user interface's Dial a Number prompt.

  4. Вернитесь в Visual Studio и остановите отладку.

Наберите номер телефона

  1. В файле кода MainPage.xaml.cs измените метод OnCall и замените комментарий TODO следующими try/catch блоками:

    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");
            }
        }
    }
    

    Класс Телефон Dialer в пространстве имен Microsoft.Maui.ApplicationModel.Communication предоставляет абстракцию функций набора телефонов (и других) для платформ Windows, Android, iOS (и iPadOS) и macOS. Статический метод Open пытается использовать телефон для вызова номера, указанного во входном параметре.

    Следующие шаги демонстрируют, как обновить манифест приложения Android, чтобы система Android могла использовать набор номера. Приложения Windows, iOS и MacCatalyst следуют тому же общему принципу, но для них в манифесте указывается другая возможность, зависящая от операционной системы.

  2. В окне Обозреватель решений разверните папку "Платформы", разверните папку Android, щелкните правой кнопкой мыши файл AndroidManifest.xml и выберите "Открыть с автоматическим>селектором редактора (XML)". Нажмите ОК.

  3. Добавьте следующий фрагмент XML в узел манифеста после существующего содержимого для этого узла.

    <?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. Сохраните файл.

  5. На панели Visual Studio выберите профиль Android emulators/Pixel 3a — API 30 (или аналогичный) и начните отладку.

  6. Когда приложение появится в эмуляторе (это может занять несколько минут), введите номер телефона (или примите значение по умолчанию) нажмите кнопку "Перевод", а затем нажмите кнопку "Звонок".

  7. В оповещении Dial a Number (Наберите номер) выберите Yes (Да). Убедитесь, что открывается приложение Android для набора телефонного номера с тем номером, который вы указали в приложении.

    The Android phone dialer containing the number provided by the app.

  8. Вернитесь в Visual Studio и остановите отладку.

Итоги

В этом упражнении вы добавили в приложение пользовательский интерфейс с помощью страниц и представлений. Вы также добавили поддержку совершения звонка с помощью платформенных API-интерфейсов, доступных в Android.