Jeszcze trochę o Xamarin.Forms, a nawet i samym Xamarin. Kolejną wspaniałą rzeczą w C#, z której możemy tutaj skorzystać jest async (póki co w innych językach nie występuje w tak wygodnej postaci albo dopiero jest w trakcie wymyślania jak w TypeScript/JavaScript). Data binding i Grid są bardzo wyraźnie wzorowane na frameworkach XAML Microsoft. Widzimy nowoczesne podejście do nawigacji i okien dialogowych, gdzie mamy metody async. Widać też trochę ideowych naleciałości z Android (np. AbsoluteLayout) czy iOS (np. nawigacja), jak również realizację własnych pomysłów na zwiększenie wygody pisania (np. możliwość stosowania lambda expressions w definicjach bindingów i bindable properties).
Wprowadzanie tekstu
InputView - klasa bazowa
- Keyboard: Keyboard (Chat, Default, Email, Numeric, Telephone, Text, Url)
Entry: InputView - pojedyncza linia tekstu
- TextColor
- IsPassword
- Placeholder
Keyboard
- CapitalizeSentence
- Spellcheck
- Suggestions
- All
editor.Keyboard = Keyboard.Create(KeyboardFlags.All);
Editor: InputView - wiele linii
Entry, Editor
- Text
- Completed
- TextChanged
Chowanie klawiatury
- dotknięcie czegoś innego na ekranie
- dotknięcie przycisku
- iPhone: Return w Entry, Done w Editor
- Android: Done w Entry, przycisk na dole ekranu do Editor
- WP: Enter w Entry, sprzętowy przycisk Back do EditorView
- Focus
Dostęp do plików
iOS i Android - klasy tak jak w “klasycznym” .NET
Standardowo w PCL klasy do obsługi plików nie są widoczne, z uwagi na WinRT API
Async
http://developer.xamarin.com/guides/cross-platform/advanced/async_support_overview/
Implementując funkcjonalność przy pomocy DependencyService na różne platformy, można używać metod z async (w Windows często mogą to być metody z WinRT API, na innych platformach używamy asynchronicznej wersji metod z .NET np. do operacji na plikach albo zwracamy taska na podstawie danych pozyskanych w sposób synchroniczny)
return Task<bool>.FromResult(exists)
Device.BeginInvokeOnMainThread(() => { … }); - wymuszenie wykonania w wątku UI
Data binding
BindableObject (implementuje INotifyPropertyChanged, definiuje SetValue i GetValue)
w klasach wizualnych kontrolek pola statyczne read-only typu BindableProperty (coś ala DependencyProperty)
entry.Text = “Xxx”;
entry.SetValue(Entry.TextProperty, “Xxx”);
public static readonly BindableProperty TextProperty;
public string Text
{
set { SetValue(Entry.TextProperty, value); }
get { return (string) GetValue(Entry.TextProperty); }
}
BindableProperty
- definiowanie propercji
- domyślne wartości
- przechowywanie bieżących wartości
- walidacja
- utrzymywanie spójności między powiązanymi propercjami w klasie
- zmiany propercji
- notyfikacje o zamiarze zmiany i po zmianie
- mechanizmy do animacji i data bindingu
BindingContext – propagacja w dół drzewa wizualnego
entry.BindingContext = data;
entry.SetBinding(Entry.TextProperty, “Title”);
Domyślny rodzaj data bindingu w BindableProperty
BindingMode
- Default
- OneWay
- OneWayToSource
- TwoWay
Nawigacja
NavigationPage
public interface INavigation
{
Task PushAsync(Page page);
Task<Page> PopAsync();
Task PopToRootAsync();
Task PushModalAsync(Page page);
Task<Page> PopModalAsync();
}
VisualElement
Navigation: INavigation
Aby włączyć nawigację metoda App.GetMainPage musi zwracać instancję NavigationPage (można do niej przekazać instancję ContentPage)
public class App
{
public static Page GetMainPage()
{
return new NavigationPage(new HomePage());
}
}
…
//Home page
this.Navigation.PushAsync(new DetailsPage());
ContentPage
- protected virtual void OnAppearing()
- protected virtual void OnDisappearing()
ListView
- ItemsSource
- SelectedItem
- event ItemSelected
INotifyCollectionChanged, ObservableCollection
Okno dialogowe
Page
- DisplayAlert(…)
bool confirm = await this.DisplayAlert("Xxx", "Yyy?”, "Yes", "No"); //true – przy naciśnięciu pierwszego przycisku
Element listy
ViewCell
- TextCell
- …
ListView listView = new ListView
{
ItemsSource = App.NoteFolder.Notes,
ItemTemplate = new DataTemplate(typeof(TextCell)),
VerticalOptions = LayoutOptions.FillAndExpand
};
listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Xxx");
ToolbarItem
- Name
- Icon - nazwa pliku (najczęściej png, w iOS trzeba dostarczyć ikony samemu)
- Order: ToolbarItemOrder (Default, Primary - obrazek, Secondary - tekst)
- Priority: int
- event Activated
- Command
- CommandParameter
Page
- ToolbarItems
Restrykcja w iOS i Android: NavigationPage lub strona nawigowana z NavigationPage
WP: może być ContentPage
Image
- Source: ImageSource
- Aspect: Aspect (AspectFit, Fill)
ImageSource
- ImageSource.FromUri - z sieci
- ImageSource.FromResource - bitmapa trzymana jako zasób w PCL (EmbeddedResource)
- ImageSource.FromFile - bitmapa trzymana jako content w projektach na platformy lub w SAP (iOS: BundleResource, Android: AndroidResource, WP: Content)
- ImageSource.FromStream - ładowanie bitmapy przy użyciu strumienia .NET
- UriImageSource
- FileImageSource
- StreamImageSource
new Image { Source = “http://xxx.yyy.zzz/aaa/bbb” };
AbsoluteLayout
Rectangle rect = new Rectangle(x, y, width, height);
AbsoluteLayout.SetLayoutBounds(child, rect);
child.SetValue (AbsoluteLayout.LayoutBoundsProperty, rect); //attached bindable property
absoluteLayout.Children.Add(child, new Rectangle(x, y, width, height));
absoluteLayout.Children.Add(child, new Point(x, y)); // auto size
AbsoluteLayout.SetLayoutFlags(child, flags); // automatyczne skalowanie i pozycjonowanie dzieci w zależności od swojego rozmiaru
absoluteLayout.Children.Add(child, rect, flags);
AbsoluteLayoutFlags
- None
- XProportional
- YProportional
- PositionProportional
- WidthProportional
- HeightProportional
- SizeProportional
- All
Kontrolki
- Slider (nie wspiera wertykalnej orientacji)
- Stepper
- Entry
- Editor
- Switch
- DatePicker
- TimePicker
- SearchBar
- WebView
- Picker - wybór
- ListView
- TableView - lista elementów podzielonych na kategorie
- ActivityIndicator
- ProgressBar
- OpenGLView
Data bindingi
view-to-view bindings = element binding w technologiach XAML Microsoft
targetView.BindingContext = sourceView;
konwerter danych:
stepperValueLabel.BindingContext = stepper;
stepperValueLabel.SetBinding (Label.TextProperty,
new Binding ("Value", BindingMode.Default, null, null,
"The Stepper value is {0}"));
sliderValueLabel.SetBinding<Slider> (Label.OpacityProperty, src => src.Value);
sliderValueLabel.SetBinding (Label.TextProperty,
Binding.Create<Slider> (src => src.Value, BindingMode.OneWay, null, null,
"The Slider value is {0:F2}"));
własna kontrolka dziedzicząca po ContentView:
- propercje typu BindableProperty
public static readonly BindableProperty FontProperty = BindableProperty.Create<RadioButton, Font>
(radio => radio.Font, Font.SystemFontOfSize(NamedSize.Large));
kontrolka kontekstem bindingów kontrolek zawartych w jej contencie
public static readonly BindableProperty IsToggledProperty = BindableProperty.Create("IsToggled",
typeof(bool), //typ propercji
typeof(RadioButton), //typ kontrolki
false, //wartość początkowa
BindingMode.TwoWay,
null, //walidacja
OnIsToggledPropertyChanged);
static void OnIsToggledPropertyChanged(BindableObject sender, object oldValue, object newValue) { … }
Grid
grid.Children.Add (child, 2, 3); //kolumny i wiersze od zera, automatyczne wnioskowanie o liczbie wierszy i kolumn na podstawie wywołań Add
odstępy: ColumnSpacing, RowSpacing
grid.Children.Add (child, left, top);
grid.Children.Add (child, left, right, top, bottom);
grid.Children.Add (child, 2, 5, 7, 8); // kolumny 2,3,4; wiersz 7
domyślnie kolumny i wiersze przyjmują rozmiary elementów, ale poprzez ColumnDefinitions i RowDefinitions możemy narzucić im określone rozmiary albo zdefiniować podział proporcjonalny.
ColumnDefinition
- Width: GridLength (Auto, Absolute, Star)
RowDefinition
- Height: GridLength
grid.ColumnDefinitions.Add(new ColumnDefinition {
Width = new GridLength(1, GridUnitType.Star)
});
Grid.SetColumn (child, 2);
Grid.SetRow (child, 3);
//także SetColumnSpan, SetRowSpan
child.SetValue (Grid.ColumnProperty, 2);
Konwerter
IValueConverter - analogicznie jak w WPF
label.SetBinding(Label.TextProperty, new Binding("Value", BindingMode.OneWay, valueConverter, null, format));
Brak komentarzy:
Prześlij komentarz