Jeszcze jedna dawka możliwości Xamarin.Forms. Dysponujemy siłą frameworków XAML pozwalającą budować swoje elementy list. Pewnym uzupełnieniem w tematyce layoutów jest przybliżenie możliwości AbsoluteLayout i RelativeLayout. Uzupełnieniem odnośnie stron są MasterDetailPage, TabbedPage i CarouselPage. Z pewnością warto wiedzieć jak zrobić fotkę w iOS i Android z Xamarin / Xamarin.Forms. Dostajemy API z async! Filozofia Androida w tej materii przekłada się na zauważalnie dłuższy kod niż w iOS, ale nie jest to zaskakujące. Pamiętajmy o MessageCenter jako o wygodnym sposobie na komunikację publish/subscribe.
var cell = new DataTemplate(typeof(TextCell));
// cell.SetBinding(TextCell.TextProperty, new Binding(“.”));
cell.SetBinding(TextCell.TextProperty, new Binding(“Title”));
cell.SetBinding(TextCell.DetailProperty, new Binding(“Author”));
cell.SetValue(TextCell.TextColorProperty, Color.Red);
cell.SetValue(TextCell.DetailColorProperty, Color.Yellow);
listView.ItemTemplate = cell;
class MyCell: ViewCell
{
public MyCell()
{
//label1
label1.SetBinding(Label.TextProperty, new Binding(“Title”));
…
View = new StackLayout
{
Children = { label1, … }
};
}
}
…
listView.ItemTemplate = new DataTemplate(typeof(MyCell));
AbsoluteLayout
<AbsoluteLayout>
<BoxView Color=”Blue”
AbsoluteLayout.LayoutBounds=”0, 0, 0.5, 0.5” //pół ekranu od lewego górnego rogu
AbsoluteLayout.LayoutFlags=”All”
</AbsoluteLayout>
RelativeLayout
var layout = new RelativeLayout();
…
layout.Children.Add(label,
Constraint.Constant(0),
Constraint.RelativeToParent(parent => {
return parent.Height / 2; //od lewej, w połowie wysokości strony
}));
…
layout.Children.Add(label2,
Constraint.RelativeToView(label1, (parent, otherView) => {
return otherView.X + otherView.Width;
}),
Constraint.RelativeToView(label1, (parent, otherView) => {
return otherView.Y + otherView.Height;
}));
…
layout.Children.Add(label3,
Constraint.RelativeToView(label2, (parent, otherView) => {
return (otherView.X + otherView.Width) - label3.Width; //nie zadziała bez wymuszenia
}),
Constraint.RelativeToView(label1, (parent, otherView) => {
return otherView.Y;
}));
label3.SizeChanged += (o, e) => { layout.ForceLayout(); }; //wymuszenie, wymiar jest liczony po pozycjonowaniu
Strony
class AlbumMasterDetail: MasterDetailPage //odsuwana zawartość przykrywa listę
{
public AlbumMasterDetail()
{
…
listView.ItemSelected += (sender, e) =>
{
if (e.SelectedItem != null)
{
//Detail = new AlbumPage(e.SelectedItem as Album);
Detail.BindingContext = e.SelectedItem;
IsPresented = false;
}
};
Master = new ContentPage
{
Title = “Albumy”,
Content = listView
};
//Detail = new AlbumPage(/*pierwsza pozycja*/);
Detail = new AlbumPage(); //wewnątrz strony zdefiniowane bindingi
Detail.BindingContext = /* pierwszy element */;
}
}
strona z zakładkami:
var page = new TabbedPage();
page.Title = “Albumy”;
foreach (var album in albums)
{
var albumPage = new AlbumPage();
albumPage.BindingContext = album;
page.Children.Add(albumPage);
}
karuzela:
var page = new CarouselPage(); //przewijanie z jednej strony do kolejnej
page.Title = “Albumy”;
foreach (var album in albums)
{
var albumPage = new AlbumPage();
albumPage.BindingContext = album;
page.Children.Add(albumPage);
}
Device
- BeginInvokeOnMainThread(Action)
- StartTimer(TimeSpan, Func<bool>)
- OpenUri(Uri)
Xamarin.Mobile
iOS:
var picker = new MediaPicker();
var mediaFile = await picker.PickPhotoAsync();
Android:
var activity = Forms.Context as Activity; //pozyskiwanie kontekstu Android w Xamarin.Forms
var picker = new MediaPicker(activity /*Android Context, zwykle this w aktywności */);
var intent = picker.GetTakePhotoUI(new StoreCameraMediaOptions
{
Name = “test.jpg”,
Directory = “Xxx”
});
activity.StartActivityForResult(intent);
activity.StartActivityForResult(intent, 1);
…
protected override async void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
if (resultCode == Result.Canceled)
return;
var mediaFile = await data.GetMediaFileExtraAsync(Forms.Context);
}
MessageCenter
- luźna komunikacja oparta na wymianie wiadomości
- identyfikacja wiadomości
- grupowanie po typie
- string ID
MessagingCenter.Send<IPictureTaker, string>(this, “pictureTaken”, mediaFile.Path);
…
MessagingCenter.Subscribe<IPictureTaker, string>(this, “pictureTaken”,
(sender, arg) =>
{
});
Propercje bindable tylko do odczytu
static readonly BindablePropertyKey WordCountKey =
BindableProperty.CreateReadOnly("WordCount", // propertyName
typeof(int), // returnType
typeof(CountedLabel), // declaringType
0); // defaultValue
public static readonly BindableProperty WordCountProperty = WordCountKey.BindableProperty;
public int WordCount
{
private set { SetValue(WordCountKey, value); }
get { return (int)GetValue(WordCountProperty); }
}
Brak komentarzy:
Prześlij komentarz