Упражнение. Создание приложения-переводчика номеров телефона
В этом упражнении вы создадите пользовательский интерфейс для приложения телефонного абонента и реализуйте логику этого пользовательского интерфейса.
Вы создадите пользовательский интерфейс, который использует возможности пользовательского интерфейса .NET MAUI и пакет .NET MAUI Essentials для набора номера телефона.
Приложение позволит пользователю вводить текст в поле ввода и преобразует этот текст в цифры. Оно будет использовать буквы, которые отображаются на клавиатуре телефона в качестве основы для перевода. Например, кабина букв переводится на 222, так как цифра 2 имеет все три буквы a, b и c.
Мы продолжим работу с решением Phoneword, созданным в предыдущем упражнении.
Добавление нового исходного файла C# в приложение
Откройте решение Phoneword в Visual Studio, если это еще не сделано.
В окне Обозреватель решений щелкните правой кнопкой мыши проект Телефон word, выберите "Добавить" и выберите "Класс".
В диалоговом окне "Добавить новый элемент" назовите файл класса Телефон word Переводчик.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;
}
}
Создание пользовательского интерфейса
Откройте файл MainPage.xaml в проекте Phoneword.
Удалите элемент управления
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>
Добавьте в ContentPage элемент управления
VerticalStackLayout
с вертикальной ориентацией, интервалом в 15 единиц и заполнением 20 единиц:<ContentPage ... > <VerticalStackLayout Spacing="15" Padding="20"> </VerticalStackLayout> </ContentPage>
Добавьте элемент управления
Label
в StackLayout:<ContentPage ... > <VerticalStackLayout ...> <Label Text = "Enter a Phoneword" FontSize ="20"/> </VerticalStackLayout> </ContentPage>
Добавьте элемент управления
Entry
в StackLayout под меткой. Элемент управленияEntry
предоставляет текстовое поле, в которое пользователь может вводить данные. В этом коде свойствоx:Name
присваивает имя элементу управления. Позже вы будете ссылаться на этот элемент управления в коде приложения:<ContentPage ... > <VerticalStackLayout ...> <Label .../> <Entry x:Name = "PhoneNumberText" Text = "1-555-NETMAUI" /> </VerticalStackLayout> </ContentPage>
Добавьте два элемента управления
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
В окне Обозреватель решений разверните запись MainPage.xaml и откройте файл кода MainPage.xaml.cs.
В классе
MainPage
удалите переменнуюcount
и методOnCounterClicked
. Класс должен выглядеть следующим образом:namespace Phoneword; public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } }
Добавьте строковую переменную
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: } } }
Примечание.
На следующем шаге вы заполните недостающие элементы кода, которые мы отложили на будущее.
Добавьте в метод
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
Добавьте метод обработки событий
OnCall
в конец классаMainPage
. Этот метод будет использовать асинхронные операции, поэтому помечайте его какasync
:public partial class MainPage : ContentPage { ... async void OnCall(object sender, System.EventArgs e) { } }
В методе
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 } }
Тестирование приложения
На панели инструментов Visual Studio выберите профиль Компьютер с Windows и начните отладку.
Нажмите кнопку Перевести, чтобы преобразовать текст по умолчанию в допустимый номер телефона. Подпись кнопки Вызов должна измениться на Вызов 1-555-6386284:
Нажмите кнопку Вызов. Убедитесь, что появился запрос на подтверждение операции. Выберите Нет.
Вернитесь в Visual Studio и остановите отладку.
Наберите номер телефона
В файле кода 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 следуют тому же общему принципу, но для них в манифесте указывается другая возможность, зависящая от операционной системы.
В окне Обозреватель решений разверните папку "Платформы", разверните папку Android, щелкните правой кнопкой мыши файл AndroidManifest.xml и выберите "Открыть с автоматическим>селектором редактора (XML)". Нажмите ОК.
Добавьте следующий фрагмент 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>
Сохраните файл.
На панели Visual Studio выберите профиль Android emulators/Pixel 3a — API 30 (или аналогичный) и начните отладку.
Когда приложение появится в эмуляторе (это может занять несколько минут), введите номер телефона (или примите значение по умолчанию) нажмите кнопку "Перевод", а затем нажмите кнопку "Звонок".
В оповещении Dial a Number (Наберите номер) выберите Yes (Да). Убедитесь, что открывается приложение Android для набора телефонного номера с тем номером, который вы указали в приложении.
Вернитесь в Visual Studio и остановите отладку.
Итоги
В этом упражнении вы добавили в приложение пользовательский интерфейс с помощью страниц и представлений. Вы также добавили поддержку совершения звонка с помощью платформенных API-интерфейсов, доступных в Android.