Nativní zobrazení v jazyce C#
Nativní zobrazení z iOSu, Androidu a UPW se dají přímo odkazovat ze Xamarin.Forms stránek vytvořených pomocí jazyka C#. Tento článek ukazuje, jak přidat nativní zobrazení do Xamarin.Forms rozložení vytvořeného pomocí jazyka C# a jak přepsat rozložení vlastních zobrazení, aby bylo možné opravit využití rozhraní API pro měření.
Přehled
Jakýkoli Xamarin.Forms ovládací prvek, který umožňuje Content
nastavit nebo který má Children
kolekci, může přidat zobrazení specifická pro platformu. Do vlastnosti nebo do StackLayout.Children
kolekce můžete například přidat ContentView.Content
přímo iOSUILabel
. Mějte však na paměti, že tato funkce vyžaduje použití #if
definic v Xamarin.Forms řešeních sdíleného projektu a není k dispozici v Xamarin.Forms řešeních knihoven .NET Standard.
Následující snímky obrazovky ukazují zobrazení specifická pro platformu Xamarin.FormsStackLayout
, která byla přidána do:
Možnost přidat zobrazení specifická pro platformu Xamarin.Forms do rozložení je povolená dvěma metodami rozšíření na každé platformě:
Add
– přidá zobrazení specifické pro platformuChildren
do kolekce rozložení.ToView
– vezme zobrazení specifické pro platformu a zabalí ho jako Xamarin.FormsView
vlastnostContent
ovládacího prvku.
Použití těchto metod ve sdíleném Xamarin.Forms projektu vyžaduje import příslušného oboru názvů specifického pro Xamarin.Forms platformu:
- iOS – Xamarin.Forms. Platform.iOS
- Android – Xamarin.Forms. Platform.Android
- Univerzální platforma Windows (UPW) – Xamarin.Forms. Platform.UWP
Přidání zobrazení specifických pro platformu na každé platformě
Následující části ukazují, jak přidat zobrazení specifická pro platformu Xamarin.Forms do rozložení na každé platformě.
iOS
Následující příklad kódu ukazuje, jak přidat UILabel
do a StackLayout
a ContentView
:
var uiLabel = new UILabel {
MinimumFontSize = 14f,
Lines = 0,
LineBreakMode = UILineBreakMode.WordWrap,
Text = originalText,
};
stackLayout.Children.Add (uiLabel);
contentView.Content = uiLabel.ToView();
V příkladu se předpokládá, že stackLayout
instance a contentView
instance byly dříve vytvořeny v jazyce XAML nebo C#.
Android
Následující příklad kódu ukazuje, jak přidat TextView
do a StackLayout
a ContentView
:
var textView = new TextView (MainActivity.Instance) { Text = originalText, TextSize = 14 };
stackLayout.Children.Add (textView);
contentView.Content = textView.ToView();
V příkladu se předpokládá, že stackLayout
instance a contentView
instance byly dříve vytvořeny v jazyce XAML nebo C#.
Univerzální platforma Windows
Následující příklad kódu ukazuje, jak přidat TextBlock
do a StackLayout
a ContentView
:
var textBlock = new TextBlock
{
Text = originalText,
FontSize = 14,
FontFamily = new FontFamily("HelveticaNeue"),
TextWrapping = TextWrapping.Wrap
};
stackLayout.Children.Add(textBlock);
contentView.Content = textBlock.ToView();
V příkladu se předpokládá, že stackLayout
instance a contentView
instance byly dříve vytvořeny v jazyce XAML nebo C#.
Přepsání měření platformy pro vlastní zobrazení
Vlastní zobrazení na jednotlivých platformách často implementují měření pouze pro scénář rozložení, pro který byly navrženy. Vlastní zobrazení bylo například navržené tak, aby zabíralo pouze polovinu dostupné šířky zařízení. Po sdílení s jinými uživateli se ale může vyžadovat vlastní zobrazení, aby zabírala plnou dostupnou šířku zařízení. Proto může být nutné přepsat vlastní implementaci měření zobrazení při opětovném Xamarin.Forms použití v rozložení. Z tohoto důvodu poskytují metody rozšíření ToView
přepsání, Add
která umožňují určit delegáty měření, což může po přidání do Xamarin.Forms rozložení přepsat vlastní rozložení zobrazení.
Následující části ukazují, jak přepsat rozložení vlastních zobrazení a opravit jejich využití rozhraní API pro měření.
iOS
Následující příklad kódu ukazuje CustomControl
třídu, která dědí z UILabel
:
public class CustomControl : UILabel
{
public override string Text {
get { return base.Text; }
set { base.Text = value.ToUpper (); }
}
public override CGSize SizeThatFits (CGSize size)
{
return new CGSize (size.Width, 150);
}
}
Instance tohoto zobrazení se přidá do objektu StackLayout
, jak je znázorněno v následujícím příkladu kódu:
var customControl = new CustomControl {
MinimumFontSize = 14,
Lines = 0,
LineBreakMode = UILineBreakMode.WordWrap,
Text = "This control has incorrect sizing - there's empty space above and below it."
};
stackLayout.Children.Add (customControl);
Vzhledem k tomu, že CustomControl.SizeThatFits
přepsání vždy vrací výšku 150, zobrazí se zobrazení s prázdným místem nad ním a pod ním, jak je znázorněno na následujícím snímku obrazovky:
Řešením tohoto problému je poskytnout GetDesiredSizeDelegate
implementaci, jak je znázorněno v následujícím příkladu kódu:
SizeRequest? FixSize (NativeViewWrapperRenderer renderer, double width, double height)
{
var uiView = renderer.Control;
if (uiView == null) {
return null;
}
var constraint = new CGSize (width, height);
// Let the CustomControl determine its size (which will be wrong)
var badRect = uiView.SizeThatFits (constraint);
// Use the width and substitute the height
return new SizeRequest (new Size (badRect.Width, 70));
}
Tato metoda používá šířku poskytnutou CustomControl.SizeThatFits
metodou, ale nahradí výšku 150 výškou 70. CustomControl
Při přidání instance do StackLayout
třídy FixSize
lze metodu určit jako GetDesiredSizeDelegate
opravu chybného měření poskytovaného CustomControl
třídou:
stackLayout.Children.Add (customControl, FixSize);
Výsledkem je správné zobrazení vlastního zobrazení bez prázdného místa nad ním a pod ním, jak je znázorněno na následujícím snímku obrazovky:
Android
Následující příklad kódu ukazuje CustomControl
třídu, která dědí z TextView
:
public class CustomControl : TextView
{
public CustomControl (Context context) : base (context)
{
}
protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
int width = MeasureSpec.GetSize (widthMeasureSpec);
// Force the width to half of what's been requested.
// This is deliberately wrong to demonstrate providing an override to fix it with.
int widthSpec = MeasureSpec.MakeMeasureSpec (width / 2, MeasureSpec.GetMode (widthMeasureSpec));
base.OnMeasure (widthSpec, heightMeasureSpec);
}
}
Instance tohoto zobrazení se přidá do objektu StackLayout
, jak je znázorněno v následujícím příkladu kódu:
var customControl = new CustomControl (MainActivity.Instance) {
Text = "This control has incorrect sizing - it doesn't occupy the available width of the device.",
TextSize = 14
};
stackLayout.Children.Add (customControl);
Vzhledem k tomu, že CustomControl.OnMeasure
přepsání vždy vrací polovinu požadované šířky, zobrazí se zobrazení zabírající pouze polovinu dostupné šířky zařízení, jak je znázorněno na následujícím snímku obrazovky:
Řešením tohoto problému je poskytnout GetDesiredSizeDelegate
implementaci, jak je znázorněno v následujícím příkladu kódu:
SizeRequest? FixSize (NativeViewWrapperRenderer renderer, int widthConstraint, int heightConstraint)
{
var nativeView = renderer.Control;
if ((widthConstraint == 0 && heightConstraint == 0) || nativeView == null) {
return null;
}
int width = Android.Views.View.MeasureSpec.GetSize (widthConstraint);
int widthSpec = Android.Views.View.MeasureSpec.MakeMeasureSpec (
width * 2, Android.Views.View.MeasureSpec.GetMode (widthConstraint));
nativeView.Measure (widthSpec, heightConstraint);
return new SizeRequest (new Size (nativeView.MeasuredWidth, nativeView.MeasuredHeight));
}
Tato metoda používá šířku poskytnutou metodou CustomControl.OnMeasure
, ale vynásobí ji dvěma. CustomControl
Při přidání instance do StackLayout
třídy FixSize
lze metodu určit jako GetDesiredSizeDelegate
opravu chybného měření poskytovaného CustomControl
třídou:
stackLayout.Children.Add (customControl, FixSize);
Výsledkem je správné zobrazení vlastního zobrazení, které zabírá šířku zařízení, jak je znázorněno na následujícím snímku obrazovky:
Univerzální platforma Windows
Následující příklad kódu ukazuje CustomControl
třídu, která dědí z Panel
:
public class CustomControl : Panel
{
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text", typeof(string), typeof(CustomControl), new PropertyMetadata(default(string), OnTextPropertyChanged));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value.ToUpper()); }
}
readonly TextBlock textBlock;
public CustomControl()
{
textBlock = new TextBlock
{
MinHeight = 0,
MaxHeight = double.PositiveInfinity,
MinWidth = 0,
MaxWidth = double.PositiveInfinity,
FontSize = 14,
TextWrapping = TextWrapping.Wrap,
VerticalAlignment = VerticalAlignment.Center
};
Children.Add(textBlock);
}
static void OnTextPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
((CustomControl)dependencyObject).textBlock.Text = (string)args.NewValue;
}
protected override Size ArrangeOverride(Size finalSize)
{
// This is deliberately wrong to demonstrate providing an override to fix it with.
textBlock.Arrange(new Rect(0, 0, finalSize.Width/2, finalSize.Height));
return finalSize;
}
protected override Size MeasureOverride(Size availableSize)
{
textBlock.Measure(availableSize);
return new Size(textBlock.DesiredSize.Width, textBlock.DesiredSize.Height);
}
}
Instance tohoto zobrazení se přidá do objektu StackLayout
, jak je znázorněno v následujícím příkladu kódu:
var brokenControl = new CustomControl {
Text = "This control has incorrect sizing - it doesn't occupy the available width of the device."
};
stackLayout.Children.Add(brokenControl);
Vzhledem k tomu, že CustomControl.ArrangeOverride
přepsání vždy vrací polovinu požadované šířky, bude zobrazení oříznuto na polovinu dostupné šířky zařízení, jak je znázorněno na následujícím snímku obrazovky:
Řešením tohoto problému je poskytnout ArrangeOverrideDelegate
implementaci při přidání zobrazení do objektu StackLayout
, jak je znázorněno v následujícím příkladu kódu:
stackLayout.Children.Add(fixedControl, arrangeOverrideDelegate: (renderer, finalSize) =>
{
if (finalSize.Width <= 0 || double.IsInfinity(finalSize.Width))
{
return null;
}
var frameworkElement = renderer.Control;
frameworkElement.Arrange(new Rect(0, 0, finalSize.Width * 2, finalSize.Height));
return finalSize;
});
Tato metoda používá šířku poskytnutou metodou CustomControl.ArrangeOverride
, ale vynásobí ji dvěma. Výsledkem je správné zobrazení vlastního zobrazení, které zabírá šířku zařízení, jak je znázorněno na následujícím snímku obrazovky:
Shrnutí
Tento článek vysvětluje, jak přidat nativní zobrazení do Xamarin.Forms rozložení vytvořeného pomocí jazyka C# a jak přepsat rozložení vlastních zobrazení, aby bylo možné opravit jejich využití rozhraní API pro měření.