您好,自定義渲染器!
HelloRenderers程式主要示範編寫簡單渲染器所需的開銷。 該程式定義了一個名為HelloView的新View衍生,旨在顯示一個簡單的固定文本字元串。 這是HelloRenderers可移植類庫項目中的完整HelloView.cs檔案:
using Xamarin.Forms;
namespace HelloRenderers
{
public class HelloView : View
{
}
}
而已! 但請注意,該類被定義為public。 即使您可能認為此類僅在PCL中引用,但事實并非如此。 它必須對平台元件可見。
HelloRenderers PCL非常簡單,甚至不會打擾頁面類。 相反,它執行個體化并在App.cs檔案中顯示以頁面為中心的HelloView對象:
namespace HelloRenderers
{
public class App : Application
{
public App()
{
MainPage = new ContentPage
{
Content = new HelloView
{
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center
}
};
}
__
}
}
沒有任何其他代碼,這個程式運作正常,但你實際上不會在螢幕上看到HelloView對象,因為它隻是一個空白的透明視圖。 我們需要的是HelloView的一些平台渲染器。
當Xamarin.Forms應用程式啟動時,Xamarin.Forms使用.NET反射搜尋構成應用程式的各種程式集,查找名為ExportRenderer的程式集屬性。 ExportRenderer屬性訓示是否存在可以為Xamarin.Forms元素提供支援的自定義渲染器。
HelloRenderers.iOS項目包含以下HelloViewRenderer.cs檔案,完整顯示。 請注意using指令下的ExportRenderer屬性。 因為這是一個程式集屬性,是以它必須在名稱空間聲明之外。 這個特殊的ExportRenderer屬性基本上表示“HelloViewRenderer類型的渲染器支援HelloView類”:
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using UIKit;
using HelloRenderers;
using HelloRenderers.iOS;
[assembly: ExportRenderer(typeof(HelloView), typeof(HelloViewRenderer))]
namespace HelloRenderers.iOS
{
public class HelloViewRenderer : ViewRenderer<HelloView, UILabel>
{
protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
{
base.OnElementChanged(args);
if (Control == null)
{
UILabel label = new UILabel
{
Text = "Hello from iOS!",
Font = UIFont.SystemFontOfSize(24)
};
SetNativeControl(label);
}
}
}
}
HelloViewRenderer類的定義遵循ExportRenderer屬性。這堂課必須公開。它派生自通用的ViewRenderer類。這兩個通用參數名為TView,它是Xamarin.Forms類,TNativeView是這個特殊情況下的類,是iOS的原生類。
在iOS中,顯示文本的類是UIKit名稱空間中的UILabel,這就是這裡使用的内容。 ViewRenderer的兩個泛型參數基本上說“一個HelloView對象實際上被渲染為iOS UILabel對象”。
ViewRenderer派生的一個基本工作是覆寫OnElementChanged方法。建立HelloView對象時調用此方法,其作用是建立用于呈現HelloView對象的本機控件。
OnElementChanged覆寫首先檢查該類是否繼承自ViewRenderer的Control屬性。此Control屬性由ViewRenderer定義為TNativeView類型,是以在HelloViewRenderer中它的類型為UILabel。第一次調用OnElementChanged時,此Control屬性将為null。必須建立UILabel對象。這就是該方法的作用,為其配置設定一些文本和字型大小。然後将該UILabel方法傳遞給SetNativeControl方法。此後,Control屬性将是此UILabel對象。
檔案頂部的using指令分為三組:
- ExportRenderer屬性需要Xamarin.Forms命名空間的using指令,而ViewRenderer類需要Xamarin.Forms.Platform.iOS。
- UILabel需要iOS UIKIt名稱空間。
- 僅對于ExportRenderer屬性中的HelloView和HelloViewRenderer引用,需要HelloRenderers和HelloRenderers.iOS的using指令,因為該屬性必須位于HelloRenderer.iOS命名空間塊之外。
最後兩個使用指令特别煩人,因為它們隻需要一個目的。 如果您願意,可以通過完全限定ExportRenderer屬性中的類名來删除這兩個使用指令。
這在以下渲染器中完成。 這是HelloRenderers.Droid項目中的完整HelloViewRenderer.cs檔案。 用于顯示文本的Android小部件是Android.Widget命名空間中的TextView:
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.Util;
using Android.Widget;
[assembly: ExportRenderer(typeof(HelloRenderers.HelloView),
typeof(HelloRenderers.Droid.HelloViewRenderer))]
namespace HelloRenderers.Droid
{
public class HelloViewRenderer : ViewRenderer<HelloView, TextView>
{
protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
{
base.OnElementChanged(args);
if (Control == null)
{
SetNativeControl(new TextView(Context)
{
Text = "Hello from Android!"
});
Control.SetTextSize(ComplexUnitType.Sp, 24);
}
}
}
}
此HelloViewRenderer類派生自Android版本的ViewRenderer。 ViewRenderer的泛型參數表明Android TextView小部件支援HelloView類。
再次,在第一次調用OnElementChanged時,Control屬性将為null。該方法必須建立本機Android TextView小部件并調用SetNativeControl。為了節省一點空間,新執行個體化的TextView對象直接傳遞給SetNativeControl方法。請注意,TextView構造函數需要Android Context對象。這是OnElementChanged的屬性。
在調用SetNativeControl之後,ViewRenderer定義的Control屬性是本機Android小部件,在本例中是TextView對象。該方法使用此Control屬性在TextView對象上調用SetTextSize。在Android中,文本大小可以通過多種方式進行縮放。 ComplexUnitType.Sp枚舉成員表示“縮放像素”,它與Xamarin.Forms處理Android中Label的字型大小的方式相容。
這是HelloRenderers.UWP項目中的HelloViewRenderer的UWP版本:
using Xamarin.Forms.Platform.UWP;
using Windows.UI.Xaml.Controls;
[assembly: ExportRenderer (typeof(HelloRenderers.HelloView),
typeof(HelloRenderers.UWP.HelloViewRenderer))]
namespace HelloRenderers.UWP
{
public class HelloViewRenderer : ViewRenderer<HelloView, TextBlock>
{
protected override void OnElementChanged(ElementChangedEventArgs<HelloView> args)
{
base.OnElementChanged(args);
if (Control == null)
{
SetNativeControl(new TextBlock
{
Text = "Hello from the UWP!",
FontSize = 24,
});
}
}
}
}
在所有Windows平台中,HelloView對象由Windows.UI.Xaml.Controls命名空間中的Windows運作時TextBlock呈現。
HelloRenderers.Windows和HelloRenderers.WinPhone項目中的HelloViewRenderer類大緻相同,除了名稱空間和用于設定TextBlock的Text屬性的文本。
這是在三個标準平台上運作的程式:

注意如何通過使用HelloView對象上設定的正常HorizontalOptions和VerticalOptions屬性來正确居中文本。 但是,您無法在HelloView上設定HorizontalTextAlignment和VerticalTextAlignment屬性。 這些屬性由Label定義,而不是由HelloView定義。
要将HelloView轉換為用于顯示文本的完整視圖,您需要開始向HelloView類添加屬性。 讓我們來看看如何使用不同的示例将屬性添加到渲染器。