sobota, 28 lutego 2015

Kulisy Xamarina - odc. 8: Xamarin.Forms cz.4

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: