C# İçindeki Yerel Görünümler
iOS, Android ve UWP'den yerel görünümlere C# kullanılarak oluşturulan sayfalardan Xamarin.Forms doğrudan başvurulabilir. Bu makalede, C# kullanılarak oluşturulan bir Xamarin.Forms düzene yerel görünümlerin nasıl ekleneceği ve bunların ölçüm API'si kullanımını düzeltmek için özel görünümlerin düzeninin nasıl geçersiz kılınacakları gösterilmektedir.
Genel bakış
Ayarlanmasına izin veren Content
veya koleksiyonu olan Children
tüm Xamarin.Forms denetimler platforma özgü görünümler ekleyebilir. Örneğin, bir iOS UILabel
doğrudan özelliğine ContentView.Content
veya koleksiyona StackLayout.Children
eklenebilir. Ancak, bu işlevin Paylaşılan Proje çözümlerinde Xamarin.Forms tanımların #if
kullanılmasını gerektirdiğini ve .NET Standart kitaplık çözümlerinde Xamarin.Forms kullanılamadığını unutmayın.
Aşağıdaki ekran görüntüleri, bir Xamarin.FormsStackLayout
öğesine eklenen platforma özgü görünümleri gösterir:
Düzene platforma özgü görünümler Xamarin.Forms ekleme özelliği her platformda iki uzantı yöntemiyle etkinleştirilir:
Add
– bir düzen koleksiyonuna platformaChildren
özgü bir görünüm ekler.ToView
– platforma özgü bir görünüm alır ve denetimin Xamarin.FormsView
özelliği olarak ayarlanabilenContent
bir görünüm olarak sarmalar.
Paylaşılan projede Xamarin.Forms bu yöntemlerin kullanılması için platforma özgü Xamarin.Forms uygun ad alanının içeri aktarılması gerekir:
- iOS – Xamarin.Forms. Platform.iOS
- Android – Xamarin.Forms. Platform.Android
- Evrensel Windows Platformu (UWP) – Xamarin.Forms. Platform.UWP
Her Platforma Platforma Özgü Görünümler Ekleme
Aşağıdaki bölümlerde, her platformdaki bir Xamarin.Forms düzene platforma özgü görünümlerin nasıl ekleneceği gösterilmektedir.
iOS
Aşağıdaki kod örneğinde ve 'ye StackLayout
nasıl ekleneceği UILabel
gösterilmektedirContentView
:
var uiLabel = new UILabel {
MinimumFontSize = 14f,
Lines = 0,
LineBreakMode = UILineBreakMode.WordWrap,
Text = originalText,
};
stackLayout.Children.Add (uiLabel);
contentView.Content = uiLabel.ToView();
Örnekte ve contentView
örneklerinin stackLayout
daha önce XAML veya C# içinde oluşturulduğu varsayılır.
Android
Aşağıdaki kod örneğinde ve 'ye StackLayout
nasıl ekleneceği TextView
gösterilmektedirContentView
:
var textView = new TextView (MainActivity.Instance) { Text = originalText, TextSize = 14 };
stackLayout.Children.Add (textView);
contentView.Content = textView.ToView();
Örnekte ve contentView
örneklerinin stackLayout
daha önce XAML veya C# içinde oluşturulduğu varsayılır.
Evrensel Windows Platformu
Aşağıdaki kod örneğinde ve 'ye StackLayout
nasıl ekleneceği TextBlock
gösterilmektedirContentView
:
var textBlock = new TextBlock
{
Text = originalText,
FontSize = 14,
FontFamily = new FontFamily("HelveticaNeue"),
TextWrapping = TextWrapping.Wrap
};
stackLayout.Children.Add(textBlock);
contentView.Content = textBlock.ToView();
Örnekte ve contentView
örneklerinin stackLayout
daha önce XAML veya C# içinde oluşturulduğu varsayılır.
Özel Görünümler için Platform Ölçümlerini Geçersiz Kılma
Her platformdaki özel görünümler genellikle yalnızca tasarlandığı düzen senaryosu için ölçüleri doğru şekilde uygular. Örneğin, özel bir görünüm, cihazın kullanılabilir genişliğinin yalnızca yarısını kaplar şekilde tasarlanmış olabilir. Ancak, diğer kullanıcılarla paylaşıldıktan sonra, cihazın tüm kullanılabilir genişliğini kaplarken özel görünüm gerekebilir. Bu nedenle, bir düzende Xamarin.Forms yeniden kullanılırken özel görünümler ölçüm uygulamasını geçersiz kılmak gerekebilir. Bu nedenle ve ToView
uzantısı yöntemleri, Add
ölçüm temsilcilerinin belirtilmesine izin veren geçersiz kılmalar sağlar ve bu da bir Xamarin.Forms düzene eklendiğinde özel görünüm düzenini geçersiz kılabilir.
Aşağıdaki bölümlerde, ölçüm API'sinin kullanımını düzeltmek için özel görünümlerin düzeninin nasıl geçersiz kılınacakları gösterilmektedir.
iOS
Aşağıdaki kod örneği, öğesinden UILabel
devralan sınıfını gösterirCustomControl
:
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);
}
}
Bu görünümün bir örneği, aşağıdaki kod örneğinde gösterildiği gibi öğesine StackLayout
eklenir:
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);
Ancak, CustomControl.SizeThatFits
geçersiz kılma her zaman 150 yüksekliği döndürdüğünden, görünüm aşağıdaki ekran görüntüsünde gösterildiği gibi üzerinde ve altında boş alanla görüntülenir:
Bu sorunun çözümü, aşağıdaki kod örneğinde gösterildiği gibi bir GetDesiredSizeDelegate
uygulama sağlamaktır:
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));
}
Bu yöntem, yöntemi tarafından CustomControl.SizeThatFits
sağlanan genişliği kullanır, ancak 150'nin yüksekliğini 70'lik bir yükseklikle değiştirmektedir. CustomControl
örneği öğesine FixSize
StackLayout
eklendiğinde, sınıfı tarafından CustomControl
sağlanan hatalı ölçümü düzeltmek için yöntemi olarak belirtilebilirGetDesiredSizeDelegate
:
stackLayout.Children.Add (customControl, FixSize);
Bu, aşağıdaki ekran görüntüsünde gösterildiği gibi, özel görünümün üzerinde ve altında boş alan olmadan doğru şekilde görüntülenmesine neden olur:
Android
Aşağıdaki kod örneği, öğesinden TextView
devralan sınıfını gösterirCustomControl
:
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);
}
}
Bu görünümün bir örneği, aşağıdaki kod örneğinde gösterildiği gibi öğesine StackLayout
eklenir:
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);
Ancak, CustomControl.OnMeasure
geçersiz kılma her zaman istenen genişliğin yarısını döndürdüğünden, görünüm aşağıdaki ekran görüntüsünde gösterildiği gibi cihazın kullanılabilir genişliğinin yalnızca yarısını kaplayarak görüntülenir:
Bu sorunun çözümü, aşağıdaki kod örneğinde gösterildiği gibi bir GetDesiredSizeDelegate
uygulama sağlamaktır:
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));
}
Bu yöntem, yöntemi tarafından CustomControl.OnMeasure
sağlanan genişliği kullanır, ancak iki ile çarpar. CustomControl
örneği öğesine FixSize
StackLayout
eklendiğinde, sınıfı tarafından CustomControl
sağlanan hatalı ölçümü düzeltmek için yöntemi olarak belirtilebilirGetDesiredSizeDelegate
:
stackLayout.Children.Add (customControl, FixSize);
Bu, aşağıdaki ekran görüntüsünde gösterildiği gibi özel görünümün doğru şekilde görüntülenmesine ve cihazın genişliğinin kaplanmasıyla sonuçlanır:
Evrensel Windows Platformu
Aşağıdaki kod örneği, öğesinden Panel
devralan sınıfını gösterirCustomControl
:
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);
}
}
Bu görünümün bir örneği, aşağıdaki kod örneğinde gösterildiği gibi öğesine StackLayout
eklenir:
var brokenControl = new CustomControl {
Text = "This control has incorrect sizing - it doesn't occupy the available width of the device."
};
stackLayout.Children.Add(brokenControl);
Ancak, CustomControl.ArrangeOverride
geçersiz kılma her zaman istenen genişliğin yarısını döndürdüğünden, görünüm aşağıdaki ekran görüntüsünde gösterildiği gibi cihazın kullanılabilir genişliğinin yarısına kırpılır:
Bu sorunun çözümü, aşağıdaki kod örneğinde gösterildiği gibi görünümü öğesine StackLayout
eklerken bir ArrangeOverrideDelegate
uygulama sağlamaktır:
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;
});
Bu yöntem, yöntemi tarafından CustomControl.ArrangeOverride
sağlanan genişliği kullanır, ancak iki ile çarpar. Bu, aşağıdaki ekran görüntüsünde gösterildiği gibi özel görünümün doğru şekilde görüntülenmesine ve cihazın genişliğinin kaplanmasıyla sonuçlanır:
Özet
Bu makalede, C# kullanılarak oluşturulan bir Xamarin.Forms düzene yerel görünümlerin nasıl ekleneceği ve bunların ölçüm API'si kullanımını düzeltmek için özel görünümlerin düzeninin nasıl geçersiz kılınacakları açıklanmıştır.