演習: 電話番号変換アプリの作成

完了

この演習では、ダイヤラー アプリの UI を構築し、この UI の背後のロジックを実装します。

.NET MAUI (Multi-platform Application User Interface) と .NET MAUI Essentials パッケージの UI 機能を利用して電話をかける UI を構築します。

ユーザーはこのアプリを使用して入力フィールドにテキストを入力し、そのテキストを数値に変換できます。 変換のベースとして電話キーパッドに表示される文字が使用されます。 たとえば、文字 cab222 に変換されます。これは、数字 2abc の 3 つの文字がすべて含まれているためです。

前の演習で作成した Phoneword ソリューションを続行します。

新しい C# ソース ファイルをアプリに追加する

  1. Phoneword ソリューションをまだ開いていない場合は、Visual Studio で開きます。

  2. ソリューション エクスプローラー ウィンドウで、Phoneword プロジェクトを右クリックし、[追加][クラス] の順に選択します。

  3. [新しい項目の追加] ダイアログ ボックスで、クラス ファイルに PhonewordTranslator.cs という名前を付けて、[追加] を選択します。

    [新しい項目の追加] ダイアログ ボックスのスクリーンショット。ユーザーはクラス ファイルに 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;
    }
}

UI を作成する

  1. Phoneword プロジェクトで MainPage.xaml ファイルを開きます。

  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 に、垂直方向の、間隔が 15 単位でパディングが 20 単位の VerticalStackLayout コントロールを追加します。

    <ContentPage ... >
        <VerticalStackLayout Spacing="15" Padding="20">
    
        </VerticalStackLayout>
    </ContentPage>
    
  4. StackLayout にLabel コントロールを追加します。

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label Text = "Enter a Phoneword"
                   FontSize ="20"/>
        </VerticalStackLayout>
    </ContentPage>
    
  5. StackLayout に Entry コントロールを、ラベルの下に追加します。 Entry コントロールは、ユーザーがデータを入力できるテキスト ボックスを提供します。 このコードでは、プロパティ x:Name がコントロールに名前を付けます。 このコントロールは、後でアプリのコードで参照します。

    <ContentPage ... >
        <VerticalStackLayout ...>
            <Label .../>
            <Entry x:Name = "PhoneNumberText"
                   Text = "1-555-NETMAUI" />
        </VerticalStackLayout>
    </ContentPage>
    
  6. VerticalStackLayout に 2 つの Button コントロールを、Entry コントロールの後に追加します。 どちらのボタンもこの時点では何も行わず、2 つ目は最初は無効になっています。 次のタスクで、これら 2 つのボタンの 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 メソッドは、Entry コントロールの Text プロパティから電話番号を取得し、それを前に作成した PhonewordTranslator クラスの静的な ToNumber メソッドに渡します。

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

    Note

    次の手順では、このコードの不足している TODO ビットを入力します。

  4. OnTranslate メソッドに、正常に変換された電話番号を追加するように [発信] ボタンの Text プロパティを変更するコードを追加します。 translatedNumber フィールドに格納した値を使用できます。 さらに、成功した変換に基づいてボタンを有効または無効にします。 たとえば、TranslateNumber が null 値を返した場合はボタンを無効にし、成功した場合は有効にします。

    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. MainPage クラスの末尾に OnCall イベント処理メソッドを追加します。 このメソッドは非同期操作を使用するため、async とマークします。

    public partial class MainPage : ContentPage
    {
    
        ...
        async void OnCall(object sender, System.EventArgs e)
        {
    
        }
    }
    
  2. OnCall メソッドで、Page.DisplayAlert メソッドを使用して、ユーザーに番号をダイヤルするかどうかを確認するプロンプトを表示します。

    DisplayAlert に対するパラメーターは、タイトル、メッセージ、[承諾] および [キャンセル] ボタンのテキストに使用される 2 つの文字列です。 これは、ダイアログ ボックスを閉じるために [承諾] ボタンが押されたかどうかを示すブール値を返します。

    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 Machine プロファイルを選択し、デバッグを開始します。

  2. [変換] ボタンをタップして、既定のテキストを有効な電話番号に変換します。 [通話] ボタンのキャプションは [通話 1-555-6386284] に変化するはずです。

    Phoneword UI のスクリーンショット。ユーザーはテキストを有効な電話番号に変換しました。

  3. [通話] ボタンをタップします。 操作の確認を求めるプロンプトが表示されることを確認します。 このため、 [いいえ] を選択します。

    PhoneWord ユーザー インターフェイスの番号をダイヤルするプロンプトのスクリーンショット。

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

    Microsoft.Maui.ApplicationModel.Communication 名前空間の PhoneDialer クラスでは、Windows、Android、iOS (および iPadOS)、macOS プラットフォームの電話ダイヤル機能 (およびその他) を抽象化します。 静的 Open メソッドは、電話ダイヤラーを使用して、パラメーターとして指定された番号を呼び出そうとします。

    次の手順では、Android アプリケーション マニフェストを更新して Android で電話ダイヤラーを使用できるようにする方法を示します。 Windows、iOS、MacCatalyst のアプリケーションは、オペレーティング システムに応じてマニフェストで異なる機能を指定する点を除いて、同じ一般原則に従います。

  2. ソリューション エクスプローラー ウィンドウで、[プラットフォーム] フォルダー、[Android] フォルダーの順に展開し、AndroidManifest.xml ファイルを右クリックして、[プログラムから開く]>[自動エディター セレクター (XML)] の順に選択します。 [OK] を選択します。

  3. manifest ノード内に次の 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. [番号をダイヤルする] アラートで [はい] を選択します。 アプリで指定した番号で Android 電話ダイヤラーが表示されることを確認します。

    アプリによって指定された番号を含む Android 電話ダイヤラー。

  8. Visual Studio に戻り、デバッグを停止します。

まとめ

この演習では、ページおよびビューを使用してアプリケーションにカスタム UI を追加しました。 また、Android で利用可能なプラットフォーム固有の API を使用して電話をかけるためのサポートも追加しました。