Xamarin.Formsでおばあちゃんのレシピを保存する

公開: 2022-03-10
クイックサマリー↬モバイルアプリを作成するときは、iOSとAndroidの両方のユーザーインターフェイスとアプリロジックを個別に作成して維持する必要があります。Objective-C/ SwiftとXCodeおよびJavaとAndroidStudioです。 それはすぐに痛みに変わる可能性があります。 ただし、Xamarin.Formsを使用すると、アプリのUIとアプリロジックが単一のコードベースに存在し、単一のIDEを使用してすべてを維持できるため、時間と頭痛の種を節約できます。 この記事では、Xamarin.Formsを一周して、Xamarin.Formsで何ができるかを確認します。

私のおばあちゃんは、誰もが今まで味わったことのない、最高の、最もふわふわした、ひざの弱いお団子を作ります。 問題は、それらのパンに入る秘密の材料がたくさんあり(そして私はただ愛を話しているだけではありません)、それらの材料と方向性はすべて私のおばあちゃんの頭に保存されているということです。

私たちは皆、そのような家族のレシピを持っています、そしておそらくそれらを忘れる代わりに、この記事では、Xamarin.Formsを使用してiOSとAndroid用のモバイルアプリを作成し、私と私の家族の将来の世代のためにそれらを保存します!

蒸気が上昇するパンの描画
美味しい温かいパン(大プレビュー)

したがって、モバイルアプリケーションの作成に興味があるが、プラットフォームごとに同じアプリを何度も作成する時間がない場合は、この記事が役に立ちます。 ストロベリープレッツェルサラダのC#を知らなくても心配しないでください。 私は8年以上Xamarinアプリを作成してきましたが、この記事はXamarin.Formsのツアーであり、自分で学習を開始するのに十分な情報を提供することを目的としています。

このXamarinのものは何ですか?

Xamarinを使用すると、開発者は、iOS用のSwiftとXCode、またはAndroid用のJavaとAndroid Studioとまったく同じSDKとUIコントロールを使用して、ネイティブのiOSおよびAndroidアプリケーションを作成できます。

ジャンプした後もっと! 以下を読み続けてください↓
iOSとAndroidのどちらで開発すべきか疑問に思っている棒人間の描画
どのプラットフォーム用に開発する必要がありますか? (大プレビュー)

違いは、アプリが.NET FrameworkとVisualStudioまたはVisualStudio for Macを使用してC#で開発されていることです。 ただし、結果として得られるアプリはまったく同じです。 それらは、Objective-C、Swift、またはJavaで記述されたネイティブアプリと同じように見え、感じ、動作します。

Xamarinは、コード共有に関して優れています。 開発者は、ネイティブコントロールとSDKを使用してプラットフォームごとにUIを作成および調整できますが、プラットフォーム間で共有される共有アプリロジックのライブラリを作成できます。

Xamarinを使用して両方のプラットフォーム用に同時に開発するというアイデアで棒人間を描く
あはは! Xamarinを選びます! (大プレビュー)

大幅な時間の節約を実現できるのは、このコード共有です。

そして、私のおばあちゃんが焼くおいしいパンのように、かつてコードを共有する味を与えられたら—これ以上欲しがらないのは難しい—そしてそれがXamarin.Formsの出番です。

Xamarin.Forms

Xamarin.Formsは、従来のXamarin開発の概念を採用し、それに抽象化レイヤーを追加します。

Xamarin.Formsでは、iOSとAndroidのユーザーインターフェイスを個別に開発する代わりに、単一のコードベースからネイティブモバイルアプリを作成できるUIツールキットが導入されています。

このように考えてください。ボタンが必要なアプリがあります。 各プラットフォームにはボタンの概念があります。 アプリのすべてのユーザーがボタンをタップするだけでよいことがわかっているのに、なぜユーザーインターフェイスを何度も作成する必要があるのでしょうか。

これは、Xamarin.Formsが解決する問題の1つです。

最も一般的に使用されるコントロールとユーザーインタラクションイベントのツールキットを提供するため、アプリのユーザーインターフェイスを作成する必要があるのは1回だけです。 ただし、Xamarin.Formsが提供するコントロールに限定されないことに注意してください。Xamarin.Formsアプリ内の単一のプラットフォームでのみ使用できるコントロールを引き続き使用できます。 また、以前と同様に、プラットフォーム間でアプリケーションロジックを共有できます。

Xamarin.Formsで開発されたアプリのコード共有統計は、チャートから外れる可能性があります。 会議開催アプリでは、コードの93%がiOSで共有され、91%がAndroidで共有されています。 アプリはオープンソースです。 コードをのぞいてみましょう。

Xamarin.Formsは、UIコントロール以上のものを提供します。 また、MVVMフレームワーク、pub / subメッセージングサービス、アニメーションAPI、依存関係サービスなども含まれています。

しかし、今日は、レシピマネージャーアプリを構築するためのUI機能に焦点を当てます。

構築するアプリ

レシピマネージャーアプリには、わかりやすいユーザーインターフェイスがあります。 キッチンで作業しますので、使い勝手が良いです!

3つの画面で構成されます。 1つ目は、アプリに現在読み込まれているすべてのレシピのリストを表示します。

iOSのレシピリスト画面のスクリーンショット
(大プレビュー)

次に、これらのレシピの1つをタップすると、2番目の画面でその詳細を確認できます。

iOSのレシピ詳細画面のスクリーンショット
iOSのレシピ詳細画面(大プレビュー)

そこから、編集ボタンをタップして、3番目の画面でレシピを変更できます。

iOSのレシピ編集画面のスクリーンショット
iOSのレシピ編集画面(大プレビュー)

レシピリスト画面から追加ボタンをタップしてこの画面に移動することもできます。

開発環境

XamarinアプリはC#と.NETで構築されており、Windowsの場合はVisual Studio、Macの場合はVisual Studio for Macを使用しますが、iOSまたはAndroidのSDKとツールもインストールする必要があります。 すべてを正しい順序でインストールするのは少し問題になる可能性がありますが、Visual Studioインストーラーは、IDEだけでなく、プラットフォームツールもインストールすることに注意します。

iOSアプリのビルドには常にMacが必要ですが、Xamarinを使用すると、Windows上のVisualStudioからそれらのアプリを開発およびデバッグできます。 したがって、Windowsが問題である場合は、環境を完全に変更する必要はありません。

Xamarin.Formsを使用して、1つのコードベースからいくつかのファミリーレシピを保存する方法を見てみましょう。

レシピリストページ:UIのレイアウト

レシピ保存アプリのUIをどのようにレイアウトするかについて話すことから始めましょう!

全体として、Xamarin.Formsの各画面は3つの要素で構成されています。 PageLayoutと呼ばれる少なくとも1つの要素。 そして、少なくとも1つのControl

ページ

ページは、画面に表示されるすべてのものを一度にホストするものです。 Pageは、アプリ内のナビゲーションの中心でもあります。

Xamarin.Formsのページを表す図面
ページ(大プレビュー)

Xamarin.Formsに、ナビゲーションサービスを介して表示するPageを指示します。 そのサービスは、オペレーティングシステムに適切でネイティブな方法でページを表示する処理を行います。

つまり、画面間を移動するためのコードも抽象化されています。

最後に、それを行う唯一の方法ではありませんが、 PageのUIをXAMLでコーディングします。 (もう1つの方法は、C#を使用することです。)XAMLは、ページの外観を記述するマークアップ言語です。 そして今のところ、それはHTMLにちょっと似ていると言えば十分です。

レイアウト

ページ上のすべてのコントロールは、レイアウトと呼ばれるものによって配置されます。

Xamarin.Formsのいくつかのレイアウトを表す図面
レイアウト(大プレビュー)

1つまたは複数のレイアウトをページに追加できます。

レイアウトがページとどのように相互作用するかの描画
ページ上のレイアウト(大きなプレビュー)

フォームにはいくつかの異なるタイプのレイアウトがあります。 最も一般的なものには、スタック、絶対、相対、グリッド、スクロール、およびフレックスレイアウトが含まれます。

いくつかのXamarin.Formsレイアウトの描画と、それらが子要素をどのように配置するか。
一般的なXamarin.Formsレイアウト(大プレビュー)

コントロール

そして最後にコントロールがあります。 これらは、ユーザーが操作するアプリのウィジェットです。

それぞれがボックスとして描画された、いくつかのXamarin.Formsコントロールの描画
一部のコントロール(大プレビュー)

フォームには、作成しているアプリの種類に関係なく使用される多くのコントロールが付属しています。 ラベル、ボタン、入力ボックス、画像、そしてもちろんリストビューのようなもの。

コントロールを画面に追加するときは、それをレイアウトに追加します。 これは、画面上のどこにコントロールが表示されるかを正確に把握するためのレイアウトです。

2つのレイアウトを保持するページの描画、およびレイアウトタイプに応じてコントロールを配置するレイアウト。
すべてが調和します! (大プレビュー)

したがって、iOSとAndroidでそれぞれ次の画面を生成するには:

iOSとAndroidのレシピリスト画面のスクリーンショット
iOS(左)とAndroid(右)のレシピリスト(大プレビュー)

私はこのXAMLを使用しました:

 <?xml version="1.0" encoding="UTF-8"?> <ContentPage xmlns="https://xamarin.com/schemas/2014/forms" xmlns:x="https://schemas.microsoft.com/winfx/2009/xaml" x:Class="SmashingRecipe.RecipeListPage" Title="Recipes"> <ContentPage.Content> <StackLayout> <ListView x:Name="recipesList"> <ListView.ItemTemplate> <DataTemplate> <TextCell Text="{Binding Name}"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content> <ContentPage.ToolbarItems> <ToolbarItem Text="Add" /> </ContentPage.ToolbarItems> </ContentPage>

ここで起こっている重要なことがいくつかあります。

1つ目は<StackLayout>です。 これは、後続のすべてのコントロールをスタックに配置するようにフォームに指示しています。

レイアウトにはたまたま1つのコントロールしかなく、それは<ListView>です。後で参照できるように、名前を付けます。

次に、目的の<TextCell>に到達する前に、 ListViewに対して少し定型文があります。 これは、リストの各セルに単純なテキストを表示するようにフォームに指示しています。

<TextCell>に、データバインディングと呼ばれる手法で表示するテキストを通知します。 構文はText="{Binding Name}"のようになります。 Nameは、Recipesをモデル化するRecipeクラスのプロパティです。

では、レシピはどのようにしてリストに追加されますか?

すべてのXAMLファイルに加えて、「分離コード」ファイルがあります。 このコードビハインドを使用すると、ユーザーインタラクションイベントの処理、セットアップの実行、その他のアプリロジックの実行などを行うことができます。

OnAppearingと呼ばれるすべてのPageでオーバーライドできる関数があります。これは、ご想像のとおり、 Pageが表示されたときに呼び出されます。

 protected override void OnAppearing() { base.OnAppearing(); recipesList.ItemsSource = null; recipesList.ItemsSource = App.AllRecipes; }

レシピリストに注意してrecipesList.ItemsSource = AllRecipes;

これは、 ListViewに次のように伝えています。 すべてのデータは列挙可能なApp.AllRecipes (アプリケーション全体の変数)にあり、その子オブジェクトの任意のプロパティを使用してバインドできます!」

レシピのリストはすべて問題ありませんが、最初にレシピの詳細を確認しないと何も焼けません。次にそれを処理します。

イベント処理

ユーザーのタッチに応答することなく、私たちのアプリはおいしいサウンドのレシピのリストにすぎません。 それらは良い音に聞こえますが、それらを調理する方法を知らなければ、それはあまり役に立ちません!

ListViewの各セルをタップに応答させて、レシピの作成方法を確認しましょう。

RecipeListPageコードファイルでは、ユーザーインタラクションイベントをリッスンして反応するためのイベントハンドラーをコントロールに追加できます。

次に、リストビューでタップイベントを処理します。

 recipesList.ItemSelected += async (sender, eventArgs) => { if (eventArgs.SelectedItem != null) { var detailPage = new RecipeDetailPage(eventArgs.SelectedItem as Recipe); await Navigation.PushAsync(detailPage); recipesList.SelectedItem = null; } };

そこにはいくつかのきちんとしたことが起こっています。

誰かが行を選択するたびに、 ItemSelectedListViewで起動されます。

ハンドラーに渡される引数のうち、 eventArgsオブジェクトにはSelectedItemプロパティがあり、これはたまたま以前からListViewにバインドされていたものです。

私たちの場合、それはRecipeクラスです。 (したがって、マスターソースでオブジェクトを検索する必要はありません。オブジェクトが渡されます。)

レシピ詳細ページ

もちろん、秘訣と各レシピの作り方を紹介するページもありますが、そのページはどのように表示されるのでしょうか?

焼き始める準備ができているシェフに扮した棒人間の絵。
料理を始めましょう! (大プレビュー)

await Navigation.PushAsync(detailPage);ことに注意してください。 上からの線。 Navigationオブジェクトは、プラットフォームに依存しないオブジェクトであり、プラットフォームごとにネイティブな方法でページ遷移を処理します。

それでは、レシピの詳細ページを見てみましょう。

iOSとAndroidのレシピ詳細画面のスクリーンショット
iOS(左)とAndroid(右)のレシピ詳細画面(大プレビュー)

このページもXAMLで作成されています。 ただし、使用されるLayout (FlexLayout)は、CSS Flexboxに触発されているため、非常に優れています。

 <ContentPage.Content> <ScrollView> <FlexLayout AlignItems="Start" AlignContent="Start" Wrap="Wrap"> <Image Source="buns.png" FlexLayout.Basis="100%" /> <Label Text="{Binding Name}" HorizontalTextAlignment="Center" TextColor="#01487E" FontAttributes="Bold" FontSize="Large" Margin="10, 10" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="Ingredients" FontAttributes="Bold" FontSize="Medium" TextColor="#EE3F60" Margin="10,10" HorizontalOptions="FillAndExpand" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="{Binding Ingredients}" Margin="10,10" FontSize="Small" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="Directions" FontAttributes="Bold" FontSize="Medium" TextColor="#EE3F60" Margin="10,10" HorizontalOptions="FillAndExpand" /> <BoxView FlexLayout.Basis="100%" HeightRequest="0" /> <Label Text="{Binding Directions}" Margin="10,10" FontSize="Small" /> </FlexLayout> </ScrollView> </ContentPage.Content>

FlexLayoutは、そのコントロールを行または列のいずれかに配置します。 大きな利点は、コントロールを配置するために画面に残っているスペースの量を自動的に検出できるという事実です。十分でない場合は、それに対応するために新しい行または列を自動的に作成できます。

これは、モバイル開発で多く存在するさまざまな画面サイズを処理するときに非常に役立ちます。

FlexLayoutを使用すると、詳細画面の見栄えを良くすることができますが、それでもこれらのレシピを編集する必要がありますね。

あなたはおそらくこれに気づいたでしょう:

 <ToolbarItem Text="Edit" Clicked="Edit_Clicked" />

その行は、アプリのツールバーにボタンを配置する役割を果たします。 Clicked="Edit_Clicked"は、クリックされたときに、その名前の関数の背後にあるコードを調べて、そのコードを実行するようにボタンに指示します。

この場合、レシピ編集ページをインスタンス化し、前述のNavigationオブジェクトを使用してナビゲーションスタックにプッシュします。

レシピ編集ページ

レシピのリストがあるページ:チェックしてください! レシピを作成するためのすべての詳細が記載されたページ:チェックしてください! 残っているのは、おばあちゃんが魔法をかけるのを見ながら、レシピを入力または変更するために使用するページを作成することだけです。

まず、画面を確認してください。

iOSとAndroidのレシピ編集画面のスクリーンショット
iOS(左)とAndroid(右)のレシピ編集画面(大プレビュー)

そして今、コード:

 <ContentPage.Content> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TableView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Intent="Form" HasUnevenRows="true"> <TableSection Title="General"> <EntryCell x:Name="recipeNameCell" Label="Name" /> </TableSection> <TableSection Title="Ingredients"> <ViewCell> <StackLayout Padding="15"> <Editor x:Name="ingredientsCell" /> </StackLayout> </ViewCell> </TableSection> <TableSection Title="Directions"> <ViewCell> <StackLayout Padding="15"> <Editor x:Name="directionsCell" /> </StackLayout> </ViewCell> </TableSection> </TableView> <Button Text="Save" Grid.Row="1" Grid.Column="0" BackgroundColor="#EE3F60" TextColor="White" x:Name="saveButton" /> <Button Text="Cancel" Grid.Row="1" Grid.Column="1" BackgroundColor="#4CC7F2" TextColor="White" x:Name="cancelButton" /> </Grid> </ContentPage.Content>

ここにはもう少しコードがあります。これは、 Gridレイアウトを使用して、すべてを2次元パターンでレイアウトする方法を指定しているためです。

また、ここではデータバインディングがないことに注意してください。 純粋にコードビハインドファイルからコントロールにデータを入力する方法の例を示したかったので、次のようにします。

 void InitializePage() { Title = TheRecipe.Name ?? "New Recipe"; recipeNameCell.Text = TheRecipe.Name; ingredientsCell.Text = TheRecipe.Ingredients; directionsCell.Text = TheRecipe.Directions; saveButton.Clicked += async (sender, args) => { SaveRecipe(); await CloseWindow(); }; cancelButton.Clicked += async (sender, args) => { await CloseWindow(); }; }

そのTheRecipeプロパティを参照してください? これはページレベルであり、特定のレシピのすべてのデータを保持し、ページのコンストラクターで設定されます。

次に、 saveButtoncancelButtonClickedイベントハンドラーは完全に.NET化されています(もちろん、私は自分の言葉を頻繁に作成します)。

そのイベントを処理する構文はJavaにもObjective-Cにもネイティブではないため、これらは.NET化されていると言えます。 アプリがAndroidまたはiOSで実行されている場合、動作はAndroidClickまたはiOSTouchUpInsideとまったく同じになります。

ご覧のとおり、これらのクリックイベントハンドラーはそれぞれ、レシピを保存してページを閉じるか、ページのみを閉じる適切な関数を呼び出しています。

そこにあります—今から時間の終わりまでレシピを保存するためのUIがあります!

CSS Wha?!? またはアプリをきれいにする

最後に最善を尽くす:Xamarin.Forms 3.0は、とりわけ、CSSを使用してコントロールのスタイルを設定する機能を提供します。

Xamarin.Forms CSSは、Web開発で慣れているものとは100%異なります。 しかし、CSSに精通している人なら誰でも自宅にいるように感じることができるほど近くにあります。 おばあちゃんの私のように!

それでは、レシピの詳細ページを取得してリファクタリングして、XAMLですべてを直接インラインで設定するのではなく、カスケードスタイルシートを使用して視覚要素を設定しましょう。

最初のステップはCSSドキュメントを作成することです! この場合、次のようになります。

 .flexContent { align-items: flex-start; align-content: flex-start; flex-wrap: wrap; } image { flex-basis: 100%; } .spacer { flex-basis: 100%; height: 0; } .foodHeader { font-size: large; font-weight: bold; color: #01487E; margin: 10 10; } .dataLabel { font-size: medium; font-weight: bold; color: #EE3F60; margin: 10 10; } .data { font-size: small; margin: 10 10; }

ほとんどの場合、CSSのように見えます。 そこにはクラスがあります。 クラスタイプImageの単一のセレクターがあります。 そして、プロパティセッターの束。

flex-wrapflex-basisなど、これらのプロパティセッターの一部は、Xamarin.Formsに固有のものです。 今後、チームは標準的な慣行に従うために、それらの前にxf-を付けます。

次は、XAMLコントロールに適用します。

 <ContentPage.Resources> <StyleSheet Source="../Styles/RecipeDetailStyle.css" /> </ContentPage.Resources> <ContentPage.Content> <ScrollView> <FlexLayout StyleClass="flexContent"> <Image Source="buns.png" /> <Label Text="{Binding Name}" StyleClass="foodHeader" /> <BoxView StyleClass="spacer" /> <Label Text="Ingredients" StyleClass="dataLabel" HorizontalOptions="FillAndExpand" /> <BoxView StyleClass="spacer" /> <Label Text="{Binding Ingredients}" StyleClass="data" /> <BoxView StyleClass="spacer" /> <Label Text="Directions" StyleClass="dataLabel" HorizontalOptions="FillAndExpand" /> <BoxView StyleClass="spacer" /> <Label Text="{Binding Directions}" StyleClass="data" /> </FlexLayout> </ScrollView> </ContentPage.Content>

以前は次のようになりました。

Xamarin.Formsで、CSSドキュメントを参照するには、 <StyleSheet Source="YOUR DOC PATH" />を追加します。 次に、 StyleClassプロパティを介して各コントロールのクラスを参照できます。

XAMLを確実にクリーンアップし、コントロールの意図も明確にします。 たとえば、これらの<BoxView StyleClass="spacer" />が何をしているのかがはっきりとわかります。

また、 Imageは画像であり、CSSでセレクターを定義した方法であるため、 Image自体がすべてスタイル設定されます。

確かに、Xamarin.FormsのCSSは、Webのいとこほど完全には実装されていませんが、それでもかなりクールです。 セレクター、クラスがあり、プロパティを設定できます。もちろん、カスケード全体が進行中です。

概要

3つの画面、2つのプラットフォーム、1つの記事、そして無限のレシピが保存されました! そして、あなたは他に何を知っていますか? Xamarin.Formsを使用して、AndroidやiOS以外のアプリを構築できます。 UWP、macOS、さらにはSamsungTizenプラットフォームを構築できます。

蒸気が上昇するパンの描画
美味しい! (大プレビュー)

Xamarin.Formsは、ユーザーインターフェイスを一度作成し、主要なプラットフォーム間でUIをネイティブにレンダリングすることで、アプリを作成できるUIツールキットです。

これは、プラットフォーム全体で最も一般的に使用されるコントロールを抽象化したSDKを提供することで実現されます。 Xamarin.Formsは、UIの優れた点に加えて、フル機能のMVVMフレームワーク、pub / subメッセージングサービス、アニメーションAPI、および依存関係サービスも提供します。

Xamarin.Formsは、従来のXamarin開発と同じコードの利点もすべて提供します。 すべてのアプリケーションロジックは、すべてのプラットフォームで共有されます。 そして、単一の言語を使用して単一のIDEですべてのアプリを開発することができます。これは非常にすばらしいことです。

次はどこへ? このXamarin.Formsアプリのソースコードをダウンロードして、自分で試してみてください。 次に、すべてブラウザ内でアプリを作成する機能など、Xamarin.Formsの詳細については、このオンラインチュートリアルをご覧ください。