Zapisywanie przepisów babci za pomocą Xamarin.Forms
Opublikowany: 2022-03-10Moja babcia robi najlepsze, najbardziej puszyste, słabe pod kolanami bułeczki, jakie ktokolwiek kiedykolwiek próbował. Problem polega na tym, że w tych bułeczkach jest mnóstwo tajnych składników (i nie mówię tu tylko o miłości), a te składniki i wskazówki są przechowywane w głowie mojej babci.
Wszyscy mamy takie rodzinne przepisy i zamiast o nich zapomnieć, w tym artykule stworzymy aplikację mobilną na iOS i Androida przy użyciu Xamarin.Forms, która zachowa je dla mnie i przyszłych pokoleń mojej rodziny!
Jeśli więc interesuje Cię pisanie aplikacji mobilnych, ale nie masz czasu na pisanie tej samej aplikacji na każdą platformę, ten artykuł jest dla Ciebie! Nie martw się, jeśli nie znasz C# z Sałatki z Truskawkowym Preclem; Piszę aplikacje Xamarin od ponad 8 lat, a ten artykuł jest przewodnikiem po platformie Xamarin.Forms, który ma na celu dostarczenie wystarczającej ilości informacji, aby rozpocząć samodzielną naukę.
Co to jest Xamarin?
Xamarin to coś więcej niż tylko zabawne słowo, które pozwala programistom tworzyć natywne aplikacje dla systemów iOS i Android przy użyciu dokładnie tych samych zestawów SDK i kontrolek interfejsu użytkownika, które są dostępne w Swift i XCode dla systemu iOS lub Java i Android Studio dla systemu Android.
Różnica polega na tym, że aplikacje są tworzone w C# przy użyciu .NET Framework i Visual Studio lub Visual Studio dla komputerów Mac. Jednak aplikacje, które dają wynik, są dokładnie takie same. Wyglądają, działają i zachowują się jak aplikacje natywne napisane w Objective-C, Swift lub Java.
Xamarin błyszczy, jeśli chodzi o udostępnianie kodu. Deweloper może tworzyć i dostosowywać swój interfejs użytkownika dla każdej platformy przy użyciu natywnych kontrolek i zestawów SDK, a następnie napisać bibliotekę udostępnionej logiki aplikacji, która jest udostępniana na różnych platformach.
To właśnie dzięki współdzieleniu kodu można osiągnąć ogromne oszczędności czasu.
I podobnie jak pyszne bułeczki, które piecze moja babcia, gdy poznałem smak dzielenia się kodem — trudno nie pragnąć więcej — i tu właśnie pojawia się Xamarin.Forms.
Xamarin.Forms
Xamarin.Forms przyjmuje koncepcję tradycyjnego programowania Xamarin i dodaje do niego warstwę abstrakcji.
Zamiast oddzielnie opracowywać interfejs użytkownika dla systemów iOS i Android, platforma Xamarin. Forms wprowadza zestaw narzędzi interfejsu użytkownika, który umożliwia pisanie natywnych aplikacji mobilnych z jednej bazy kodu.
Pomyśl o tym w ten sposób: masz aplikację, która potrzebuje przycisku. Każda platforma ma koncepcję przycisku. Dlaczego miałbyś pisać interfejs użytkownika kilka razy, skoro wiesz, że wszystko, co użytkownik Twojej aplikacji musi zrobić, to nacisnąć przycisk?
To jeden z problemów, które rozwiązuje platforma Xamarin.Forms.
Zapewnia zestaw narzędzi z najczęściej używanymi kontrolkami i zdarzeniami interakcji użytkownika dla nich, więc interfejsy użytkownika dla naszych aplikacji musimy napisać tylko raz. Warto zauważyć, że nie ograniczasz się do formantów udostępnianych przez platformę Xamarin. Forms — nadal możesz używać formantów znajdujących się tylko na jednej platformie w aplikacji Xamarin. Forms. Możemy również udostępniać logikę aplikacji między platformami, tak jak poprzednio.
Statystyki udostępniania kodu dla aplikacji opracowanych przy użyciu platformy Xamarin.Forms mogą być poza wykresami. Aplikacja do organizowania konferencji ma 93% kodu udostępnionego na iOS i 91% na Androida. Aplikacja jest typu open source. Rzuć okiem na kod.
Platforma Xamarin. Forms zapewnia więcej niż kontrolki interfejsu użytkownika. Zawiera również strukturę MVVM, usługę przesyłania komunikatów pub/sub, interfejs API animacji i usługę zależności oraz inne.
Ale dzisiaj skupimy się na możliwościach interfejsu użytkownika do tworzenia naszej aplikacji do zarządzania recepturami.
Aplikacja, którą zbudujemy
Aplikacja do zarządzania recepturami będzie miała prosty interfejs użytkownika. Będziemy pracować w kuchni, więc musi być łatwa w obsłudze!
Będzie się składać z 3 ekranów . Pierwszy pokaże listę wszystkich przepisów aktualnie załadowanych w aplikacji.
Następnie, dotykając jednego z tych przepisów, będziesz mógł zobaczyć jego szczegóły na drugim ekranie:
Stamtąd możesz dotknąć przycisku edycji, aby wprowadzić zmiany w przepisie na trzecim ekranie:
Możesz również przejść do tego ekranu, dotykając przycisku dodawania na ekranie listy przepisów.
Środowisko programistyczne
Aplikacje platformy Xamarin są tworzone w językach C# i .NET, przy użyciu programu Visual Studio w systemie Windows lub Visual Studio dla komputerów Mac na komputerze Mac, ale trzeba też mieć zainstalowane zestawy SDK i narzędzia dla systemu iOS lub Android. Zainstalowanie wszystkiego we właściwej kolejności może być pewnym problemem, jednak instalatorzy Visual Studio zajmą się tylko instalacją IDE, ale także oprzyrządowaniem platformy.
Chociaż komputer Mac jest zawsze wymagany do tworzenia aplikacji dla systemu iOS, za pomocą platformy Xamarin możesz nadal opracowywać i debugować te aplikacje z programu Visual Studio w systemie Windows! Jeśli więc Windows jest twoją przeszkodą, nie ma potrzeby całkowitej zmiany środowiska.
Zobaczmy teraz, jak Xamarin.Forms może pomóc nam zapisać niektóre rodzinne przepisy z jednej bazy kodu!
Strona listy przepisów: Układ interfejsu użytkownika
Zacznijmy od porozmawiania o tym, jak zamierzamy rozplanować interfejs dla naszej aplikacji do zapisywania przepisów!
Ogólnie każdy ekran w Xamarin.Forms składa się z 3 elementów. Page
. Co najmniej jeden element o nazwie Layout
. I przynajmniej jedna Control
.
Strona
Strona to obiekt, który obsługuje jednocześnie wszystko, co jest wyświetlane na ekranie. Page
jest również centralnym elementem nawigacji w aplikacji.
Poinformujemy platformę Xamarin. Forms, która Page
ma być wyświetlana za pośrednictwem usługi nawigacji . Ta usługa zajmie się wtedy wyświetlaniem dowolnej strony w sposób odpowiedni i natywny dla systemu operacyjnego.
Innymi słowy, kod do poruszania się między ekranami również został abstrakcyjny!
Wreszcie, chociaż nie jest to jedyny sposób, aby to zrobić, koduję interfejs użytkownika mojej Page
w XAML. (Innym sposobem byłoby użycie C#). XAML to język znaczników opisujący wygląd strony. A na razie wystarczy powiedzieć, że jest trochę podobny do HTML.
Układ
Wszystkie kontrolki na stronie są uporządkowane według czegoś, co nazywa się układem.
Do strony można dodać jeden lub więcej układów.
W Formularzach jest kilka różnych typów układów. Niektóre z najczęstszych to układy Stack, Absolute, Relative, Grid, Scroll i Flex.
Sterowanie
Wreszcie są kontrole. Są to widżety Twojej aplikacji, z którymi użytkownik wchodzi w interakcję.
Formularze zawierają wiele kontrolek, które będą używane bez względu na typ tworzonej aplikacji. Rzeczy takie jak etykiety, przyciski, pola wprowadzania, obrazy i oczywiście widoki list.
Dodając kontrolkę do ekranu, dodajesz ją do układu. Jest to układ, który zajmuje się określeniem, gdzie dokładnie na ekranie powinna pojawić się kontrolka.
Aby wygenerować następujące ekrany odpowiednio na iOS i Androida:
Użyłem tego 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>
Dzieje się tutaj kilka ważnych rzeczy.
Pierwszy to <StackLayout>
. To mówi Forms, aby ułożył wszystkie kontrolki w stosie.
Zdarza się, że w układzie jest tylko jedna kontrolka, a jest to <ListView>
, a my nadamy jej nazwę, aby móc się do niej później odwołać.
Potem następuje trochę ceremonii szablonowej w ListView
, zanim przejdziemy do tego, czego szukamy: <TextCell>
. Oznacza to, że formularze mają wyświetlać prosty tekst w każdej komórce listy.
Mówimy <TextCell>
tekst, który chcemy, aby był wyświetlany, za pomocą techniki zwanej Data Binding . Składnia wygląda tak: Text="{Binding Name}"
. Gdzie Name
jest właściwością klasy Recipe
, która modeluje… cóż, Receptury.
Jak więc dodać przepisy do listy?
Wraz z każdym plikiem XAML istnieje plik „z kodem”. Ten kod pozwala nam robić takie rzeczy, jak obsługa zdarzeń interakcji użytkownika, przeprowadzanie konfiguracji lub wykonywanie innej logiki aplikacji.
Istnieje funkcja, którą można nadpisać na każdej Page
o nazwie OnAppearing
— która, jak zapewne zgadłeś — jest wywoływana, gdy pojawia się Page
.
protected override void OnAppearing() { base.OnAppearing(); recipesList.ItemsSource = null; recipesList.ItemsSource = App.AllRecipes; }
Zwróć uwagę na recipesList.ItemsSource = AllRecipes;
To mówi ListView
— „Hej! Wszystkie twoje dane znajdują się w App.AllRecipes
(zmiennej obejmującej całą aplikację) i możesz użyć dowolnych właściwości jego obiektu podrzędnego, aby się z nim powiązać!”.
Lista przepisów jest w porządku — ale nie można niczego upiec bez uprzedniego zapoznania się ze szczegółami przepisu — i zajmiemy się tym w następnej kolejności.
Obsługa zdarzeń
Bez reagowania na dotyk użytkownika nasza aplikacja jest niczym innym jak listą pysznie brzmiących przepisów. Brzmią dobrze, ale bez wiedzy, jak je ugotować, nie ma to większego sensu!
Sprawmy, aby każda komórka w ListView
reagowała na dotknięcia, abyśmy mogli zobaczyć, jak zrobić przepis!
W pliku związanym z kodem RecipeListPage
możemy dodać obsługę zdarzeń do kontrolek, aby nasłuchiwać i reagować na zdarzenia interakcji użytkownika.
Obsługa zdarzeń dotknięcia w widoku listy, a następnie:
recipesList.ItemSelected += async (sender, eventArgs) => { if (eventArgs.SelectedItem != null) { var detailPage = new RecipeDetailPage(eventArgs.SelectedItem as Recipe); await Navigation.PushAsync(detailPage); recipesList.SelectedItem = null; } };
Dzieje się tam kilka fajnych rzeczy.
Za każdym razem, gdy ktoś wybierze wiersz, ItemSelected
jest wyzwalany w ListView
.
Spośród argumentów, które są przekazywane do programu obsługi, obiekt eventArgs
ma właściwość SelectedItem
, która jest tym, co jest powiązane z ListView
przed.
W naszym przypadku jest to klasa Recipe
. (Więc nie musimy szukać obiektu w głównym źródle - jest on do nas przekazywany.)
Strona ze szczegółami przepisu
Oczywiście jest strona, która pokazuje nam tajne składniki i wskazówki, jak przygotować każdy przepis, ale w jaki sposób ta strona jest wyświetlana?
Zwróć uwagę await Navigation.PushAsync(detailPage);
linia z góry. Obiekt Navigation
to obiekt niezależny od platformy, który obsługuje przejścia stron w sposób natywny dla każdej platformy.
Rzućmy teraz okiem na stronę ze szczegółami przepisu:
Ta strona jest również zbudowana przy użyciu XAML. Jednak użyty Layout
(FlexLayout) jest całkiem fajny, ponieważ jest inspirowany 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
rozmieści swoje kontrolki w wierszach lub kolumnach. Dużą zaletą jest jednak fakt, że może automatycznie wykryć, ile miejsca zostało na ekranie, aby umieścić kontrolkę, a jeśli nie ma wystarczającej ilości, może automatycznie utworzyć nowy wiersz lub kolumnę, aby je pomieścić!
To bardzo pomaga, gdy mamy do czynienia z różnymi rozmiarami ekranu, których jest mnóstwo w programowaniu mobilnym.
Cóż, ponieważ FlexLayout
pomaga nam utrzymać dobry wygląd ekranu szczegółów, nadal musimy edytować te przepisy, prawda?
Prawdopodobnie zauważyłeś to:
<ToolbarItem Text="Edit" Clicked="Edit_Clicked" />
Ta linia odpowiada za umieszczenie przycisku na pasku narzędzi aplikacji. Clicked="Edit_Clicked"
informuje przycisk, że po kliknięciu należy sprawdzić w kodzie znajdującym się za funkcją o tej nazwie, a następnie wykonać jej kod.
Co w tym przypadku oznaczałoby utworzenie instancji strony edycji receptury i umieszczenie jej na naszym stosie nawigacyjnym przy użyciu wspomnianego wcześniej obiektu Navigation
.
Strona edycji przepisu
Strona z listą przepisów: sprawdź! Strona ze wszystkimi szczegółami tworzenia przepisów: sprawdź! Teraz pozostało tylko utworzyć stronę, na której będziemy wprowadzać lub zmieniać przepis, podczas gdy babcia pracuje nad swoją magią!
Najpierw sprawdź ekrany:
A teraz kod:
<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>
Jest tu trochę więcej kodu, a to dlatego, że używam układu Grid
, aby określić, jak wszystko powinno być ułożone we wzorcu dwuwymiarowym.
A także zauważ, że nie ma tutaj wiązania danych. Ponieważ chciałem podać przykład, w jaki sposób można wypełnić kontrolki wyłącznie z kodu znajdującego się za plikiem:
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(); }; }
Widzisz tę właściwość TheRecipe
? Jest to poziom strony, przechowuje wszystkie dane dla konkretnego przepisu i jest ustawiany w konstruktorze strony.
Po drugie, procedury obsługi zdarzeń Clicked
dla saveButton
i cancelButton
są całkowicie .NET (i tak, często wymyślam własne słowa).
Mówię, że są .NET-ified, ponieważ składnia do obsługi tego zdarzenia nie jest natywna dla Javy ani Objective-C. Gdy aplikacja działa w systemie Android lub iOS, zachowanie będzie dokładnie takie, jak kliknięcie w systemie Android lub TouchUpInside w systemie iOS.
Jak widać, każdy z tych programów obsługi zdarzeń kliknięcia wywołuje odpowiednie funkcje, które albo zapisują przepis i zamykają stronę, albo tylko zamykają stronę.
To jest to — mamy interfejs użytkownika, aby zapisać przepisy od teraz do końca czasu!
CSS Co?!? Lub upiększyć aplikację
Najlepsze na koniec: Xamarin.Forms 3.0 daje nam — między innymi — możliwość stylizowania kontrolek za pomocą CSS!
Arkusz CSS Xamarin. Forms nie jest w 100% tym, do czego możesz być przyzwyczajony w programowaniu sieci Web. Ale jest na tyle blisko, że każdy, kto zna CSS, poczuje się jak w domu. Tak jak ja u babci!
Weźmy więc stronę Szczegóły przepisu i zmieńmy ją, aby używała kaskadowych arkuszy stylów do ustawiania elementów wizualnych zamiast ustawiania wszystkiego bezpośrednio w XAML.
Pierwszym krokiem jest stworzenie dokumentu CSS! W tym przypadku będzie to wyglądać następująco:
.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; }
W większości wygląda to jak CSS. Tam są zajęcia. Istnieje jeden selektor typu klasy, Image
. A potem banda decydentów majątkowych.
Niektóre z tych ustawień właściwości, takie jak flex-wrap
lub flex-basis
są specyficzne dla platformy Xamarin. Forms. Idąc dalej, zespół będzie przedrostkiem xf-
, aby postępować zgodnie ze standardowymi praktykami.
Następnym krokiem będzie zastosowanie go do kontrolek 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>
Oto jak to wyglądało wcześniej.
W Xamarin. Forms, aby odwołać się do dokumentu CSS, Dodaj <StyleSheet Source="YOUR DOC PATH" />
. Następnie możesz odwoływać się do klas w każdej kontrolce za pomocą właściwości StyleClass
.
Zdecydowanie czyści XAML i sprawia, że intencja formantu jest również wyraźniejsza. Na przykład teraz jest całkiem oczywiste, do czego zmierzają te <BoxView StyleClass="spacer" />
!
A Image
sam się stylizuje, ponieważ jest to Image
i sposób, w jaki zdefiniowaliśmy selektor w CSS.
Oczywiście CSS w Xamarin.Forms nie jest tak w pełni zaimplementowany jak jego kuzyn sieciowy, ale nadal jest całkiem fajny. Masz selektory, klasy, możesz ustawić właściwości i oczywiście cała ta kaskadowa rzecz!
Streszczenie
Zapisano trzy ekrany, dwie platformy, jeden artykuł i niekończące się przepisy! A wiesz co jeszcze? Możesz tworzyć aplikacje za pomocą platformy Xamarin. Forms dla systemów więcej niż Android i iOS. Możesz budować platformy UWP, macOS, a nawet Samsung Tizen!
Xamarin. Forms to zestaw narzędzi interfejsu użytkownika, który umożliwia tworzenie aplikacji przez jednokrotne napisanie interfejsu użytkownika i renderowanie interfejsu użytkownika natywnie na głównych platformach.
Robi to, udostępniając zestaw SDK, który jest abstrakcją dla najczęściej używanych kontrolek na platformach. Oprócz dobroci interfejsu użytkownika platforma Xamarin. Forms zapewnia również w pełni funkcjonalną platformę MVVM, usługę przesyłania komunikatów pub/sub, interfejs API animacji i usługę zależności.
Platforma Xamarin. Forms zapewnia również te same korzyści związane z kodem, co tradycyjne programowanie Xamarin. Dowolna logika aplikacji jest współdzielona na wszystkich platformach. I możesz tworzyć wszystkie swoje aplikacje za pomocą jednego IDE, używając jednego języka — to całkiem fajne!
Gdzie teraz? Pobierz kod źródłowy tej aplikacji platformy Xamarin. Forms, aby samodzielnie ją poznać. Następnie, aby dowiedzieć się więcej o platformie Xamarin. Forms, w tym o możliwości tworzenia aplikacji w przeglądarce, zapoznaj się z tym samouczkiem online!