如何借助Xamarin.Forms跨移動(dòng)平臺(tái)共享UI代碼

今天就跟大家聊聊有關(guān)如何借助Xamarin.Forms跨移動(dòng)平臺(tái)共享UI代碼,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

成都創(chuàng)新互聯(lián)公司主要從事做網(wǎng)站、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)沅江,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):13518219792

借助 Xamarin,您可以使用 C# 構(gòu)建美觀的本機(jī)移動(dòng)應(yīng)用和在平臺(tái)之間共享您的大部分代碼。傳統(tǒng)上,您必須對(duì)每個(gè)目標(biāo)平臺(tái)設(shè)計(jì)單獨(dú)的 UI。但是,借助 Xamarin.Forms,您可以構(gòu)建一個(gè)在所有平臺(tái)中本機(jī)呈現(xiàn)的 UI。

Xamarin.Forms 是跨平臺(tái) UI 抽象層??梢允褂盟谄脚_(tái)間共享 UI 和后端代碼,而同時(shí)仍提供完全本機(jī) UI 體驗(yàn)。因?yàn)樗鼈兪潜緳C(jī)的,所以您的控件和小組件將具有每個(gè)目標(biāo)平臺(tái)的外觀。

Xamarin.Forms 與 Model-View-ViewModel (MVVM) 設(shè)計(jì)模式完全兼容,因此可以在視圖模型類中將頁(yè)面元素綁定到屬性和命令。

如果您愿意以聲明方式設(shè)計(jì)您的頁(yè)面,則可以使用標(biāo)記語(yǔ)言 XAML,XAML 具有資源字典、動(dòng)態(tài)資源、數(shù)據(jù)綁定、命令、觸發(fā)器和行為等功能。

Xamarin.Forms 有一個(gè)小巧、易于使用的 API。如果您需要更深入地訪問(wèn)平臺(tái)的本機(jī) UI,可以創(chuàng)建自定義視圖和特定于平臺(tái)的呈現(xiàn)器。這盡管聽(tīng)起來(lái)很復(fù)雜,但它實(shí)際上只是一種可訪問(wèn)本機(jī) UI 的方法,并且 Xamarin 網(wǎng)站有充足示例來(lái)幫助您完成該任務(wù)。

您可以使用 Xamarin.Forms 附帶的任何現(xiàn)成頁(yè)面、布局和視圖開始操作。在您的應(yīng)用逐漸完善并且您發(fā)現(xiàn)新用例和設(shè)計(jì)機(jī)會(huì)時(shí),您可能馬上就需依賴 Xamarin.Forms 支持 XAML、MVVM、特定于自定義平臺(tái)的呈現(xiàn)器和各種其他功能(如動(dòng)畫和數(shù)據(jù)模板)。

我將使用特定示例概述 Xamarin 功能,演示如何在不同的目標(biāo)平臺(tái)之間共享大部分 UI 代碼,以及如何在必要時(shí)合并特定于平臺(tái)的代碼。

開始使用

首先,打開 Visual Studio 或 Xamarin Studio 中的 NuGet 包管理器,并檢查 Xamarin.Forms 是否為新版本。因?yàn)閮H僅在任一 IDE 中打開 Xamarin.Forms 解決方案,不會(huì)告知您新版本,所以檢查更新的 NuGet 包是否為確保獲得最新增強(qiáng)功能的唯一方法。

創(chuàng)建 Xamarin.Forms 解決方案確保您已獲得最新版本 Xamarin.Forms 后,創(chuàng)建一個(gè)空白應(yīng)用 (Xamarin.Forms Portable) 解決方案。

您的解決方案具有三個(gè)特定于平臺(tái)的項(xiàng)目和一個(gè)可移植類庫(kù) (PCL)。在 PCL 中創(chuàng)建您的頁(yè)面。首先創(chuàng)建一個(gè)基本的登錄頁(yè)面。

使用 C# 創(chuàng)建頁(yè)面向 PCL 項(xiàng)目中添加一個(gè)類。然后添加控件(在 Xamarin 中稱為“視圖”),如圖 1中所示。

圖 1 添加視圖(控件)

public class LogInPage : ContentPage
{
  public LogInPage()
  {
    Entry userEntry = new Entry { Placeholder = "Username" };
    Entry passEntry =
      new Entry { Placeholder = "Password", IsPassword = true };
    Button submit = new Button { };
    Content = new StackLayout
    {
      Padding = 20,
      VerticalOptions = LayoutOptions.Center,
      Children = { userEntry, passEntry, submit }
    };
  }
}

若要在應(yīng)用啟動(dòng)時(shí)顯示頁(yè)面,打開 MyApp 類并將其中一個(gè)實(shí)例分配給 MainPage 屬性:

public class MyApp : Application
{
  public MyApp()
  {
    MainPage = new LogInPage();
  }
}

這是討論應(yīng)用程序類的好時(shí)機(jī)。從 v1.3.0 開始,所有 Xamarin.Forms 應(yīng)用將都包含此類。它是 Xamarin.Forms 應(yīng)用的入口點(diǎn),除此之外,它還提供了生命周期事件以及所有可序列化數(shù)據(jù)的永久數(shù)據(jù)存儲(chǔ)區(qū)(屬性字典)。如果需要從應(yīng)用任意位置訪問(wèn)此類的實(shí)例,您可以使用靜態(tài) Application.Current 屬性。

在前面的示例中,我已刪除應(yīng)用程序類內(nèi)部的默認(rèn)代碼,并用一行代碼代替,從而使 LogInPage 顯示您何時(shí)運(yùn)行應(yīng)用。它顯示應(yīng)用何時(shí)運(yùn)行,因?yàn)榇舜a將頁(yè)面 (LogInPage) 分配給了應(yīng)用程序類的 MainPage 屬性。您必須在應(yīng)用程序類的構(gòu)造函數(shù)中對(duì)其進(jìn)行設(shè)置。

您還可以重寫此類中的三個(gè)方法:

  • OnStart 方法,第一次啟動(dòng)應(yīng)用時(shí)調(diào)用。

  • OnSleep 方法,當(dāng)應(yīng)用要進(jìn)入后臺(tái)狀態(tài)時(shí)調(diào)用。

  • OnResume 方法,當(dāng)從后臺(tái)狀態(tài)返回應(yīng)用時(shí)調(diào)用。

一般情況下,頁(yè)面不是非常有趣,直到您將他們與某種形式的數(shù)據(jù)或行為連接,因此我將介紹如何執(zhí)行該操作。

將頁(yè)面綁定到數(shù)據(jù)如果您使用 MVVM 設(shè)計(jì)模式,則可以創(chuàng)建一個(gè)(如圖 2中所示)實(shí)現(xiàn) INotifyPropertyChanged 接口的類。

圖 2 實(shí)現(xiàn) INotifyPropertyChanged 接口

public class LoginViewModel : INotifyPropertyChanged
{
  private string usrnmTxt;
  private string passWrd;
  public string UsernameText
  {
    get { return usrnmTxt; }
    set
    {
      if (usrnmTxt == value)
        return;
      usrnmTxt = value;
      OnPropertyChanged("UsernameText");
    }
  }
  public string PassWordText
  {
    get { return passWrd; }
    set
    {
      if (passWrd == value)
        return;
      passWrd = value;
      OnPropertyChanged("PassWrd");
    }
  }
  public event PropertyChangedEventHandler PropertyChanged;
  private void OnPropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

您可以將登錄頁(yè)面的視圖綁定到該類的屬性(如圖 3中所示)。

圖 3 將視圖綁定到類屬性

public LogInPage()
{
  Entry userEntry = new Entry { Placeholder = "Username" };
  userEntry.SetBinding(Entry.TextProperty, "UsernameText");
  Entry passEntry =
    new Entry { Placeholder = "Password", IsPassword = true };
  passEntry.SetBinding(Entry.TextProperty, "PasswordText");
  Button submit = new Button { Text = "Submit" };
  Content = new StackLayout
    {
      Padding = 20,
      VerticalOptions = LayoutOptions.Center,
      Children = { userEntry, passEntry, submit }
    };
  BindingContext = new LoginViewModel();
}

若要閱讀有關(guān)如何綁定到 Xamarin.Forms 應(yīng)用中數(shù)據(jù)的詳細(xì)信息,請(qǐng)參閱 Xamarin 站點(diǎn) bit.ly/1uMoIUX 上的“從數(shù)據(jù)綁定到 MVVM”。

使用 XAML 創(chuàng)建頁(yè)面對(duì)于較小的應(yīng)用,使用 C# 創(chuàng)建 UI 是完全合理的方法。但是,隨著應(yīng)用大小的增長(zhǎng),您可能會(huì)發(fā)現(xiàn)自己鍵入了大量的重復(fù)代碼。您可以通過(guò)使用 XAML 避免該問(wèn)題,,而不是通過(guò) C# 代碼。

將窗體 XAML 頁(yè)面項(xiàng)添加到您的 PCL 項(xiàng)目。然后將標(biāo)記添加到頁(yè)面,如圖 4中所示。

圖 4 將標(biāo)記添加到窗體 XAML 頁(yè)面

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  x:Class="Jason3.LogInPage"
  xmlns:local="clr-namespace:XamarinForms;assembly=XamarinForms"> 
    <StackLayout VerticalOptions="Center">
      <StackLayout.BindingContext>
        <local:LoginViewModel />
      </StackLayout.BindingContext>
      <Entry Text="{Binding UsernameText}" Placeholder="Username" />
      <Entry Text="{Binding PasswordText}"
        Placeholder="Password" IsPassword="true" />
      <Button Text="Login" Command="{Binding LoginCommand}" />
    </StackLayout>
</ContentPage>

如果您編寫過(guò) Windows Presentation Foundation (WPF) 應(yīng)用,那么會(huì)對(duì)圖 4中的 XAML 感到很熟悉。但是,這些標(biāo)記是不同的,因?yàn)樗鼈冎傅氖?Xamarin.Forms 類型。此外,根元素引用 Xamarin.Forms.Element 類的子類。Xamarin.Forms 應(yīng)用中的所有 XAML 文件必須都這樣做。

若要了解有關(guān)使用 XAML 在 Xamarin.Forms 應(yīng)用中創(chuàng)建頁(yè)面的詳細(xì)信息,請(qǐng)參閱 Xamarin 網(wǎng)站 bit.ly/1xAKvRN 上的“適用于 Xamarin.Forms 的 XAML”。

設(shè)計(jì)特定平臺(tái)

與其他本機(jī)移動(dòng)平臺(tái)相比,Xamarin.Forms 具有相對(duì)較少的 API。這樣您可以更輕松地設(shè)計(jì)頁(yè)面,但有時(shí) Xamarin.Forms 不按您想要的方式在一個(gè)或多個(gè)平臺(tái)目標(biāo)上呈現(xiàn)視圖。

如果遇到此障礙,只需創(chuàng)建自定義視圖,這只是一個(gè)可用于 Xamarin.Forms 的任何視圖的子類。

若要使視圖顯示在頁(yè)面上,請(qǐng)擴(kuò)展視圖呈現(xiàn)器。在更高級(jí)的情況下,您甚至可以從頭創(chuàng)建自定義呈現(xiàn)器。自定義呈現(xiàn)器代碼是特定于平臺(tái)的,因此您不能共享此代碼。但這種方法值這個(gè)價(jià)格,因?yàn)樗梢砸氡緳C(jī)功能和應(yīng)用可用性。

創(chuàng)建自定義視圖首先,創(chuàng)建 Xamarin.Forms 中提供的任一視圖的子類。下面是兩個(gè)自定義視圖的代碼:

public class MyEntry : Entry {}
public class RoundedBoxView : BoxView {}

擴(kuò)展現(xiàn)有的呈現(xiàn)器圖 5擴(kuò)展可以呈現(xiàn) iOS 平臺(tái)的條目視圖的呈現(xiàn)器。您應(yīng)將此類放在 iOS 平臺(tái)項(xiàng)目中。此呈現(xiàn)器設(shè)置底層本機(jī)文本字段的顏色和樣式。

圖 5 擴(kuò)展現(xiàn)有的呈現(xiàn)器

[assembly: ExportRenderer (typeof (MyEntry), typeof (MyEntryRenderer))]
namespace CustomRenderer.iOS
{
  public class MyEntryRenderer : EntryRenderer
  {
    protected override void OnElementChanged
      (ElementChangedEventArgs<Entry> e)
    {
      base.OnElementChanged (e);
      if (e.OldElement == null) {
        var nativeTextField = (UITextField)Control;
        nativeTextField.BackgroundColor = UIColor.Gray;
        nativeTextField.BorderStyle = UITextBorderStyle.Line;
      }
    }
  }
}

您可以在呈現(xiàn)器上執(zhí)行幾乎任何操作,因?yàn)槟谝帽緳C(jī) API。如果您想要查看包含此代碼段的示例,請(qǐng)參閱 bit.ly/1xTIjmR 上的“Xamarin.Forms 自定義呈現(xiàn)器”。

從頭開始創(chuàng)建呈現(xiàn)器可以創(chuàng)建不擴(kuò)展任何其他呈現(xiàn)器的全新呈現(xiàn)器。創(chuàng)建呈現(xiàn)器會(huì)需要您做更多的工作,但是這有益于執(zhí)行以下任一操作:

  • 替換視圖的呈現(xiàn)器。

  • 將新的視圖類型添加到您的解決方案。

  • 將本機(jī)控件或本機(jī)頁(yè)面添加到您的解決方案。

例如,如果您想要將本機(jī) UIView 控件添加到 iOS 版本應(yīng)用的頁(yè)面中,則應(yīng)將自定義呈現(xiàn)器添加到您的 iOS 項(xiàng)目,如圖 6中所示。

圖 6 將本機(jī) UIView 控件添加到配備自定義呈現(xiàn)器的 iOS 應(yīng)用

[assembly: ExportRendererAttribute(typeof(RoundedBoxView),
  typeof(RoundedBoxViewRenderer))]
namespace RBVRenderer.iOS
{
  public class RoundedBoxViewRenderer :
    ViewRenderer<RoundedBoxView,UIView>
  {
    protected override void OnElementChanged(
      ElementChangedEventArgs<RoundedBoxView> e)
    {
      base.OnElementChanged(e);
      var rbvOld = e.OldElement;
      if (rbvOld != null)
      {
        // Unhook any events from e.OldElement here.
      }
      var rbv = e.NewElement;
      if (rbv != null)
      {
        var shadowView = new UIView();
        // Set properties on the UIView here.
        SetNativeControl(shadowView);
        // Hook up any events from e.NewElement here.
      }
    }
  }
}

此呈現(xiàn)器中顯示的通用模式,可確保您可以在虛擬化布局(如列表視圖)中使用此模式,稍后我將對(duì)此進(jìn)行討論。

如果您想要查看包含此代碼段的示例,請(qǐng)參閱 bit.ly/xf-customrenderer。

將屬性添加到自定義視圖您可以將屬性添加到自定義視圖,但要確保這些屬性可綁定,以便您可以將屬性綁定到視圖模型中的屬性或其他類型的數(shù)據(jù)。下面是一個(gè) RoundedBoxView 自定義視圖中可綁定的屬性:

public class RoundedBoxView : BoxView
{
  public static readonly BindableProperty CornerRadiusProperty =
    BindableProperty.Create<RoundedBoxView, double>(p => p.CornerRadius, 0);
  public double CornerRadius
  {
    get { return (double)base.GetValue(CornerRadiusProperty);}
    set { base.SetValue(CornerRadiusProperty, value);}
  }
}

若要將新屬性連接到您的呈現(xiàn)器,請(qǐng)重寫呈現(xiàn)器的 OnElementPropertyChanged 方法,并添加在屬性更改時(shí)運(yùn)行的代碼:

protected override void OnElementPropertyChanged(object sender,    
  System.ComponentModel.PropertyChangedEventArgs e)
{
  base.OnElementPropertyChanged(sender, e);
  if (e.PropertyName ==
    RoundedBoxView.CornerRadiusProperty.PropertyName)
      childView.Layer.CornerRadius = (float)this.Element.CornerRadius;
}

若要了解有關(guān)創(chuàng)建自定義視圖和自定義呈現(xiàn)器的詳細(xì)信息,請(qǐng)參閱 bit.ly/11pSFhL 上的“自定義每個(gè)平臺(tái)的控件”。

頁(yè)面、布局和視圖:Xamarin.Forms 的構(gòu)建基塊

我已經(jīng)展示了幾個(gè)元素,但還有更多。這是介紹這些元素的好時(shí)機(jī)。

Xamarin.Forms 應(yīng)用包含頁(yè)面、布局和視圖。一個(gè)頁(yè)面包含一個(gè)或多個(gè)布局,一個(gè)布局包含一個(gè)或多個(gè)視圖。在 Xamarin 中使用術(shù)語(yǔ)視圖來(lái)描述您調(diào)用控件的習(xí)慣??偟膩?lái)說(shuō),Xamarin.Forms 框架包含五種頁(yè)面類型、七種布局類型和 24 種視圖類型。通過(guò) xamarin.com/forms,您可以獲得更多信息。稍后,我將介紹一些重要的頁(yè)面類型,但首先我將花一點(diǎn)時(shí)間回顧一些您可以在應(yīng)用中使用的布局。Xamarin.Forms 包含四種主要布局:

  • StackLayout:StackLayout 在單個(gè)垂直或水平行中定位子元素。您可以嵌套 StackLayouts 來(lái)創(chuàng)建復(fù)雜的可視層次結(jié)構(gòu)。通過(guò)使用每個(gè)子視圖的 VerticalOptions 和 Horizontal&shy;Options 屬性,可以控制視圖在 StackLayout 中的排列方式。

  • 網(wǎng)格:網(wǎng)格將視圖排列入行和列。此布局類似于使用 WPF 和 Silverlight 獲得的布局,但您不可以在行和列之間添加間距。通過(guò)使用網(wǎng)格的 RowSpacing 和 ColumnSpacing 屬性來(lái)做到這一點(diǎn)。

  • RelativeLayout:通過(guò)使用相對(duì)于其他視圖的約束,RelativeLayout 可以定位視圖。

  • AbsoluteLayout:AbsoluteLayout 可以通過(guò)兩種方式定位子視圖:絕對(duì)位置定位或相對(duì)于父級(jí)按比例定位。這有助于創(chuàng)建拆分并疊加層次結(jié)構(gòu)。圖 7顯示了一個(gè)示例。

圖 7 使用 AbsoluteLayout

void AbsoluteLayoutView()
{
  var layout = new AbsoluteLayout();
  var leftHalfOfLayoutChild = new BoxView { Color = Color.Red };
  var centerAutomaticallySizedChild =
    new BoxView { Color = Color.Green };
  var absolutelyPositionedChild = new BoxView { Color = Color.Blue };
  layout.Children.Add(leftHalfOfLayoutChild,
    new Rectangle(0, 0, 0.5, 1),
    AbsoluteLayoutFlags.All);
  layout.Children.Add(centerAutomaticallySizedChild,
    new Rectangle(
    0.5, 0.5, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize),
    AbsoluteLayoutFlags.PositionProportional);
  layout.Children.Add(
    absolutelyPositionedChild, new Rectangle(10, 20, 30, 40));
}

請(qǐng)注意,所有布局都為您提供了名為 Children 的屬性。該屬性可用于訪問(wèn)其他成員。例如,可以使用網(wǎng)格布局的 Children 屬性來(lái)添加和刪除行和列,以及指定行和列間距。

在滾動(dòng)列表中顯示數(shù)據(jù)

通過(guò)使用列表視圖窗體(名為 ListView),可以在滾動(dòng)列表中顯示數(shù)據(jù)。此視圖性能良好,因?yàn)榱斜碇忻總€(gè)單元格的呈現(xiàn)器均被虛擬化。由于每個(gè)單元格均被虛擬化,因此通過(guò)使用與前面類似的模式,正確處理為單元格或列表創(chuàng)建的任何自定義呈現(xiàn)器的 OnElementChanged 事件是非常重要的。

首先,定義某一單元格,如圖 8中所示。ListView 的所有數(shù)據(jù)模板都必須都使用單元格作為根元素。

圖 8 定義 ListView 單元格

public class MyCell : ViewCell
{
  public MyCell()
  {
    var nameLabel = new Label();
    nameLabel.SetBinding(Label.TextProperty, "Name");
    var descLabel = new Label();
    descLabel.SetBinding(Label.TextProperty, "Description");
    View = new StackLayout
    {
      VerticalOptions = LayoutOptions.Center,
      Children = { nameLabel, descLabel }
    };
  }
}

接下來(lái),定義數(shù)據(jù)源,并對(duì)新的數(shù)據(jù)模板設(shè)置 ListView 的 ItemTemplate 屬性。數(shù)據(jù)模板基于前面創(chuàng)建的 MyCell 類:

var items = new[] {
  new { Name = "Flower", Description = "A lovely pot of flowers." },
  new { Name = "Tuna", Description = "A can of tuna!" },
  // ... Add more items
};
var listView = new ListView
{
  ItemsSource = items,
  ItemTemplate = new DataTemplate(typeof(MyCell))
};

您可以借助以下標(biāo)記在 XAML 中執(zhí)行此操作:

<ListView ItemsSource="{Binding Items}">
  <ListView.ItemTemplate>
    <ViewCell>
      <StackLayout VerticalOptions="center">
      <Label Text="{Binding Name}" />
      <Label Text="{Binding Description}" />
      </StackLayout>
    </ViewCell>
  </ListView.ItemTemplate>
</ListView>

在頁(yè)面之間導(dǎo)航

大多數(shù)應(yīng)用包含多個(gè)頁(yè)面,因此您需要使用戶能夠從一個(gè)頁(yè)面導(dǎo)航到另一個(gè)頁(yè)面。以下頁(yè)面具有適用于頁(yè)面導(dǎo)航的內(nèi)置支持,并支持全屏模式頁(yè)面演示文稿:

  • TabbedPage

  • MasterDetailPage

  • NavigationPage

  • CarouselPage

您可以將頁(yè)面作為子級(jí)添加到這四個(gè)頁(yè)面的任何一個(gè),并免費(fèi)獲得導(dǎo)航。

Tabbed PageTabbedPage 橫跨屏幕頂部顯示選項(xiàng)卡的數(shù)組。假設(shè) PCL 項(xiàng)目包含名為 LogInPage、DirectoryPage 和 AboutPage 的頁(yè)面,則可以使用以下代碼將這些頁(yè)面全部添加到 TabbedPage:

var tabbedPage = new TabbedPage
{
  Children =
  {
    new LoginPage { Title = "Login", Icon = "login.png" },
    new DirectoryPage { Title = "Directory", Icon = "directory.png" },
    new AboutPage { Title = "About", Icon = "about.png" }
  }
};

在這種情況下,設(shè)置每個(gè)頁(yè)面的標(biāo)題和圖標(biāo)屬性是非常重要的,這可以使某些內(nèi)容顯示在頁(yè)面選項(xiàng)卡上。并非所有平臺(tái)都呈現(xiàn)圖標(biāo)。這取決于平臺(tái)的選項(xiàng)卡設(shè)計(jì)。

如果您在移動(dòng)設(shè)備上打開此頁(yè)面,第一個(gè)選項(xiàng)卡將顯示為選中狀態(tài)。但是,可以通過(guò)設(shè)置 TabbedPage 頁(yè)面的 CurrentPage 屬性更改此狀態(tài)。

NavigationPageNavigationPage 管理大量頁(yè)面的導(dǎo)航和 UX。此頁(yè)為您提供了最常見(jiàn)的移動(dòng)應(yīng)用導(dǎo)航模式類型。下面是如何向它添加您的頁(yè)面:

var loginPage = new LoginPage();
var navigationPage = new NavigationPage(loginPage);
loginPage.LoginSuccessful += async (o, e) => await
  navigationPage.PushAsync(new DirectoryPage());

請(qǐng)注意,PushAsync 方法用于導(dǎo)航用戶到特定頁(yè)面(在本例中為 DirectoryPage)。在 NavigationPage 中,可以將頁(yè)面“推送”到堆棧,然后在用戶向后導(dǎo)航到先前頁(yè)面時(shí)將其“彈出”。

NavigationPage 的 PushAsync 和 PopAsync 方法是異步的,因此您的代碼應(yīng)等待它們,而不是運(yùn)行任務(wù)時(shí)推送或彈出任何新頁(yè)面。推送或彈出的動(dòng)畫完成后,返回每種方法的任務(wù)。

為方便起見(jiàn),所有 Xamarin.Forms 視圖、布局和頁(yè)面都包含導(dǎo)航屬性。此屬性是一個(gè)代理接口,包含 NavigationPage 實(shí)例的 PushAsync 和 PopAsync 方法。該屬性可用于導(dǎo)航到頁(yè)面而不是直接調(diào)用 NavigationPage 實(shí)例的 PushAsync 和 PopAsync 方法。NavigationProperty 還可用于獲取 PushModalAsync 和 PopModalAsync 方法。這有助于將整個(gè)屏幕的內(nèi)容替換為新的模式頁(yè)面。視圖的父堆棧中不一定必須有一個(gè) NavigationPage 來(lái)使用視圖的導(dǎo)航屬性,但無(wú)模式 PushAsync/PopAsync 操作可能會(huì)失敗。

關(guān)于設(shè)計(jì)模式的注釋通常,將 NavigationPages 作為子級(jí)添加到 TabbedPages,將 TabbedPages 作為子級(jí)添加到 MasterDetailPages。某些類型的模式可能會(huì)導(dǎo)致意外的 UX。例如,大多數(shù)平臺(tái)建議您不要將 TabbedPage 添加為 NavigationPage 的子級(jí)。

對(duì)頁(yè)面中的視圖進(jìn)行動(dòng)畫處理

有兩種方法對(duì)頁(yè)面上的視圖設(shè)置動(dòng)畫效果,來(lái)創(chuàng)建更具吸引力的用戶體驗(yàn)。選擇 Xamarin.Forms 附帶的內(nèi)置動(dòng)畫,或通過(guò)使用動(dòng)畫 API 自己構(gòu)建。

例如,您可以通過(guò)調(diào)用一個(gè)視圖的 FadeTo 動(dòng)畫創(chuàng)建淡化效果。FadeTo 動(dòng)畫內(nèi)置于視圖中,因此簡(jiǎn)單易用:

async Task SpinAndFadeView(View view)
{
  await view.FadeTo(20, length: 200, easing: Easing.CubicInOut);
}

可以通過(guò)使用 await 關(guān)鍵字一起鏈接一系列的動(dòng)畫。在前一個(gè)完成后,將執(zhí)行每個(gè)動(dòng)畫。例如,可以在將視圖淡化為焦點(diǎn)之前對(duì)其進(jìn)行旋轉(zhuǎn):

async Task SpinAndFadeView(View view)
{
  await view.RotateTo(180);
  await view.FadeTo(20, length: 200, easing: Easing.CubicInOut);
}

如果在實(shí)現(xiàn)所需效果時(shí)遇到問(wèn)題,可以使用完整的動(dòng)畫 API。在下面的代碼中,通過(guò)旋轉(zhuǎn)視圖淡化一半:

void SpinAndFadeView(View view)
{
  var animation = new Animation();
  animation.Add(0, 1, new Animation(
    d => view.Rotation = d, 0, 180, Easing.CubicInOut));
  animation.Add(0.5, 1, new Animation(
    d => view.Opacity = d, 1, 0, Easing.Linear));
  animation.Commit(view, "FadeAndRotate", length: 250);
}

此示例將每個(gè)動(dòng)畫組合成單個(gè)動(dòng)畫實(shí)例,然后使用 Commit 方法運(yùn)行整個(gè)動(dòng)畫序列。因?yàn)榇藙?dòng)畫不能局限于特定視圖,所以您可以將此動(dòng)畫應(yīng)用于任何視圖。

Xamarin.Forms 是構(gòu)建跨平臺(tái)本機(jī)移動(dòng)應(yīng)用的令人激動(dòng)的新方法。使用它可以構(gòu)建跨 iOS、Android 和 Windows Phone 本機(jī)呈現(xiàn)的 UI。您可以在平臺(tái)之間共享幾乎所有代碼。

Xamarin Inc. 構(gòu)建 Xamarin 和 Xamarin.Forms,使 C# 開發(fā)人員幾乎能夠迅速跳轉(zhuǎn)到移動(dòng)開發(fā)。如果您已經(jīng)為 Windows 運(yùn)行時(shí)、WPF 或 Silverlight 進(jìn)行開發(fā),您會(huì)發(fā)現(xiàn) Xamarin.Forms 是跨平臺(tái)本機(jī)移動(dòng)開發(fā)領(lǐng)域的便捷橋梁。您可以立即安裝 Xamarin 并立即開始使用 C#,以構(gòu)建在 iOS、Android 和 Windows Phone 設(shè)備上運(yùn)行的美觀本機(jī)應(yīng)用。

看完上述內(nèi)容,你們對(duì)如何借助Xamarin.Forms跨移動(dòng)平臺(tái)共享UI代碼有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。

網(wǎng)站名稱:如何借助Xamarin.Forms跨移動(dòng)平臺(tái)共享UI代碼
網(wǎng)址分享:http://muchs.cn/article4/pdjdie.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、品牌網(wǎng)站建設(shè)、虛擬主機(jī)用戶體驗(yàn)、品牌網(wǎng)站設(shè)計(jì)、微信小程序

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司