Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Widoki natywne z systemów iOS, Android i UWP można odwoływać się bezpośrednio ze Xamarin.Forms stron utworzonych przy użyciu języka C#. W tym artykule pokazano, jak dodać widoki natywne do układu utworzonego Xamarin.Forms przy użyciu języka C#, oraz jak zastąpić układ widoków niestandardowych w celu poprawienia użycia interfejsu API pomiaru.
Omówienie
Każda Xamarin.Forms kontrolka, która umożliwia Content ustawienie lub kolekcja Children , może dodawać widoki specyficzne dla platformy. Na przykład system iOS UILabel można bezpośrednio dodać do ContentView.Content właściwości lub do kolekcji StackLayout.Children . Należy jednak pamiętać, że ta funkcja wymaga użycia funkcji definiowanych #if w Xamarin.Forms rozwiązaniach projektów udostępnionych i nie jest dostępna z Xamarin.Forms rozwiązań biblioteki .NET Standard.
Na poniższych zrzutach ekranu przedstawiono widoki specyficzne dla platformy, które zostały dodane do elementu Xamarin.FormsStackLayout:
Możliwość dodawania widoków specyficznych dla platformy do Xamarin.Forms układu jest włączona przez dwie metody rozszerzenia na każdej platformie:
Add— dodaje widok specyficzny dla platformy doChildrenkolekcji układu.ToView— przyjmuje widok specyficzny dla platformy i opakowuje go jako Xamarin.FormsViewwłaściwość kontrolki, którą można ustawić jakoContentwłaściwość kontrolki.
Użycie tych metod w udostępnionym Xamarin.Forms projekcie wymaga zaimportowania odpowiedniej przestrzeni nazw specyficznej dla Xamarin.Forms platformy:
- iOS — Xamarin.Forms. Platform.iOS
- Android — Xamarin.Forms. Platform.Android
- platforma uniwersalna systemu Windows (UWP) — Xamarin.Forms. Platform.UWP
Dodawanie widoków specyficznych dla platformy na każdej platformie
W poniższych sekcjach pokazano, jak dodać widoki specyficzne dla platformy do Xamarin.Forms układu na każdej platformie.
iOS
W poniższym przykładzie kodu pokazano, jak dodać element UILabel do elementu StackLayout i ContentView:
var uiLabel = new UILabel {
MinimumFontSize = 14f,
Lines = 0,
LineBreakMode = UILineBreakMode.WordWrap,
Text = originalText,
};
stackLayout.Children.Add (uiLabel);
contentView.Content = uiLabel.ToView();
W przykładzie przyjęto założenie, że stackLayout wystąpienia i contentView zostały wcześniej utworzone w języku XAML lub C#.
Android
W poniższym przykładzie kodu pokazano, jak dodać element TextView do elementu StackLayout i ContentView:
var textView = new TextView (MainActivity.Instance) { Text = originalText, TextSize = 14 };
stackLayout.Children.Add (textView);
contentView.Content = textView.ToView();
W przykładzie przyjęto założenie, że stackLayout wystąpienia i contentView zostały wcześniej utworzone w języku XAML lub C#.
Platforma uniwersalna systemu Windows
W poniższym przykładzie kodu pokazano, jak dodać element TextBlock do elementu StackLayout i ContentView:
var textBlock = new TextBlock
{
Text = originalText,
FontSize = 14,
FontFamily = new FontFamily("HelveticaNeue"),
TextWrapping = TextWrapping.Wrap
};
stackLayout.Children.Add(textBlock);
contentView.Content = textBlock.ToView();
W przykładzie przyjęto założenie, że stackLayout wystąpienia i contentView zostały wcześniej utworzone w języku XAML lub C#.
Zastępowanie miar platformy dla widoków niestandardowych
Widoki niestandardowe na każdej platformie często prawidłowo implementują pomiar dla scenariusza układu, dla którego zostały zaprojektowane. Na przykład widok niestandardowy może być zaprojektowany tak, aby zajmował tylko połowę dostępnej szerokości urządzenia. Jednak po udostępnieniu innym użytkownikom widok niestandardowy może być wymagany do zajmowania pełnej dostępnej szerokości urządzenia. W związku z tym może być konieczne zastąpienie implementacji pomiarów widoków niestandardowych podczas ponownego Xamarin.Forms użycia w układzie. Z tego powodu metody i ToView zapewniają przesłonięcia, Add które umożliwiają określenie delegatów pomiaru, co może zastąpić układ widoku niestandardowego Xamarin.Forms po dodaniu go do układu.
W poniższych sekcjach pokazano, jak zastąpić układ widoków niestandardowych, aby poprawić użycie interfejsu API pomiaru.
iOS
Poniższy przykład kodu przedstawia klasę CustomControl , która dziedziczy z UILabelklasy :
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);
}
}
Wystąpienie tego widoku jest dodawane do StackLayoutobiektu , jak pokazano w poniższym przykładzie kodu:
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);
Jednak ponieważ CustomControl.SizeThatFits przesłonięcia zawsze zwraca wysokość 150, widok będzie wyświetlany z pustym miejscem powyżej i poniżej, jak pokazano na poniższym zrzucie ekranu:

Rozwiązaniem tego problemu jest zapewnienie GetDesiredSizeDelegate implementacji, jak pokazano w poniższym przykładzie kodu:
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));
}
Ta metoda używa szerokości podanej CustomControl.SizeThatFits przez metodę, ale zastępuje wysokość 150 na wysokość 70. CustomControl Po dodaniu wystąpienia do StackLayoutFixSize klasy można określić metodę w GetDesiredSizeDelegate celu naprawienia nieprawidłowej miary dostarczonej przez klasęCustomControl:
stackLayout.Children.Add (customControl, FixSize);
Spowoduje to poprawne wyświetlenie widoku niestandardowego bez pustego miejsca powyżej i poniżej niego, jak pokazano na poniższym zrzucie ekranu:

Android
Poniższy przykład kodu przedstawia klasę CustomControl , która dziedziczy z TextViewklasy :
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);
}
}
Wystąpienie tego widoku jest dodawane do StackLayoutobiektu , jak pokazano w poniższym przykładzie kodu:
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);
Jednak ze względu na to CustomControl.OnMeasure , że przesłonięcia zawsze zwraca połowę żądanej szerokości, widok będzie wyświetlany zająć tylko połowę dostępnej szerokości urządzenia, jak pokazano na poniższym zrzucie ekranu:

Rozwiązaniem tego problemu jest zapewnienie GetDesiredSizeDelegate implementacji, jak pokazano w poniższym przykładzie kodu:
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));
}
Ta metoda używa szerokości podanej przez metodę CustomControl.OnMeasure , ale mnoży ją przez dwa. CustomControl Po dodaniu wystąpienia do StackLayoutFixSize klasy można określić metodę w GetDesiredSizeDelegate celu naprawienia nieprawidłowej miary dostarczonej przez klasęCustomControl:
stackLayout.Children.Add (customControl, FixSize);
Spowoduje to poprawne wyświetlenie widoku niestandardowego, zajmowanie szerokości urządzenia, jak pokazano na poniższym zrzucie ekranu:

Platforma uniwersalna systemu Windows
Poniższy przykład kodu przedstawia klasę CustomControl , która dziedziczy z Panelklasy :
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);
}
}
Wystąpienie tego widoku jest dodawane do StackLayoutobiektu , jak pokazano w poniższym przykładzie kodu:
var brokenControl = new CustomControl {
Text = "This control has incorrect sizing - it doesn't occupy the available width of the device."
};
stackLayout.Children.Add(brokenControl);
Jednak ponieważ CustomControl.ArrangeOverride przesłonięcia zawsze zwraca połowę żądanej szerokości, widok zostanie obcięty do połowy dostępnej szerokości urządzenia, jak pokazano na poniższym zrzucie ekranu:

Rozwiązaniem tego problemu jest zapewnienie ArrangeOverrideDelegate implementacji podczas dodawania widoku do StackLayoutelementu , jak pokazano w poniższym przykładzie kodu:
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;
});
Ta metoda używa szerokości podanej przez metodę CustomControl.ArrangeOverride , ale mnoży ją przez dwa. Spowoduje to poprawne wyświetlenie widoku niestandardowego, zajmowanie szerokości urządzenia, jak pokazano na poniższym zrzucie ekranu:

Podsumowanie
W tym artykule wyjaśniono, jak dodać widoki natywne do układu utworzonego Xamarin.Forms przy użyciu języka C#, oraz jak zastąpić układ widoków niestandardowych w celu poprawienia użycia interfejsu API pomiaru.
