uygulamasında Özel Düzen oluşturma Xamarin.Forms
Xamarin.Forms beş düzen sınıfı tanımlar: StackLayout, AbsoluteLayout, RelativeLayout, Grid ve FlexLayout ve her biri alt öğelerini farklı bir şekilde düzenler. Ancak, bazen sayfa içeriğini tarafından Xamarin.Formssağlanmayan bir düzen kullanarak düzenlemek gerekir. Bu makalede özel bir düzen sınıfının nasıl yazıldığını açıklar ve alt öğelerini sayfada yatay olarak yerleştiren ve ardından sonraki alt öğelerin görünümünü ek satırlara kaydıran, yönlendirmeye duyarlı wrapLayout sınıfını gösterir.
içinde Xamarin.Forms, tüm düzen sınıfları sınıfından Layout<T>
türetilir ve genel türü View
ile türetilen türlerini kısıtlar. Buna karşılık, Layout<T>
sınıf, alt öğeleri konumlandırmak ve boyutlandırmak için mekanizma sağlayan sınıfından türetilir Layout
.
Her görsel öğesi, istenen boyut olarak bilinen kendi tercih edilen boyutunu belirlemekle sorumludur. Page
, Layout
ve Layout<View>
türetilmiş türler, kendilerine göre çocuklarının veya çocuklarının konumunu ve boyutunu belirlemekle sorumludur. Bu nedenle, düzen, üst öğe alt öğelerinin boyutunun ne olması gerektiğini belirlediği ancak çocuğun istenen boyutunu barındırmaya çalışacağı bir üst-alt ilişki içerir.
Özel bir düzen oluşturmak için düzeni ve geçersizleştirme döngülerini ayrıntılı bir şekilde anlamak Xamarin.Forms gerekir. Bu döngüler artık ele alınacaktır.
Düzen
Düzen, görsel ağacının en üstünde bir sayfayla başlar ve sayfadaki tüm görsel öğeleri kapsayacak şekilde görsel ağacının tüm dallarında ilerler. Diğer öğelerin ebeveyni olan öğeler, çocuklarının kendilerine göre boyutlandırılmasından ve konumlandırılmasından sorumludur.
sınıfıVisualElement
, düzen işlemleri için bir öğeyi ölçen bir yöntem ve öğenin içinde işlenecek dikdörtgen alanı belirten bir Layout
yöntem tanımlarMeasure
. Bir uygulama başlatıldığında ve ilk sayfa görüntülendiğinde, ilk çağrılardan ve ardından çağrılardan Measure
oluşan bir düzen döngüsü nesne üzerinde Page
başlar:Layout
- Düzen döngüsü sırasında, her üst öğe alt öğelerinde yöntemini çağırmaktan
Measure
sorumludur. - Alt öğeler ölçüldükten sonra, her üst öğe alt öğelerinde yöntemini çağırmaktan
Layout
sorumludur.
Bu döngü, sayfadaki her görsel öğenin ve Layout
yöntemlerine Measure
çağrılar almasını sağlar. İşlem aşağıdaki diyagramda gösterilmiştir:
Not
Düzeni etkileyecek bir değişiklik olduğunda, düzen döngülerinin görsel ağacının bir alt kümesinde de gerçekleşebileceğini unutmayın. Buna, içinde gibi StackLayout
bir koleksiyona eklenen veya kaldırılan öğeler, öğenin özelliğinde IsVisible
yapılan bir değişiklik veya öğenin boyutundaki bir değişiklik dahildir.
veya Children
özelliği olan her Xamarin.Forms sınıfın Content
geçersiz kılınabilir LayoutChildren
bir yöntemi vardır. öğesinden Layout<View>
türetilen özel düzen sınıfları bu yöntemi geçersiz kılmalı ve istenen özel düzeni sağlamak için ve Layout
yöntemlerinin öğenin tüm alt öğelerinde çağrıldığından emin olmalıdırMeasure
.
Ayrıca, öğesinden Layout
türetilen veya Layout<View>
yöntemini geçersiz kılması OnMeasure
gereken her sınıf, bir düzen sınıfının alt öğelerinin yöntemlerine Measure
çağrılar yaparak olması gereken boyutu belirlediği yöntemdir.
Not
Öğeler boyutlarını kısıtlamalara göre belirler ve bu da öğenin üst öğesi içindeki bir öğe için ne kadar alan olduğunu gösterir. ve OnMeasure
yöntemlerine Measure
geçirilen kısıtlamalar 0 Double.PositiveInfinity
ile arasında değişebilir. Bir öğe, sonsuz olmayan bağımsız değişkenlerle yöntemine Measure
bir çağrı aldığında kısıtlanmış veya tamamen kısıtlanmış olur. Öğe belirli bir boyuta kısıtlanır. Bir öğe, yöntemine Measure
en az bir bağımsız değişkene eşit Double.PositiveInfinity
bir çağrı aldığında kısıtlanmamış veya kısmen kısıtlanmış olur; sonsuz kısıtlama otomatikleştirmeyi gösterir olarak düşünülebilir.
Örneğin
Geçersizleştirme, sayfadaki bir öğedeki değişikliğin yeni bir düzen döngüsünü tetiklediği işlemdir. Öğeler artık doğru boyuta veya konuma sahip olmadığında geçersiz kabul edilir. Örneğin, bir Button
değişikliğin FontSize
Button
özelliği artık doğru boyuta sahip olmayacağından geçersiz olduğu söylenir. Yeniden boyutlandırma, Button
sayfanın geri kalanında düzendeki değişikliklerin dalgalı bir etkisine sahip olabilir.
Genellikle öğenin bir özelliği öğenin yeni boyutuna InvalidateMeasure
neden olabilecek değiştiğinde, öğeler yöntemini çağırarak kendilerini geçersiz hale getirir. Bu yöntem, öğenin üst öğesinin MeasureInvalidated
yeni bir düzen döngüsünü tetikleyecek şekilde işlediği olayı tetikler.
sınıfı, Layout
özelliğine veya Children
koleksiyonuna MeasureInvalidated
Content
eklenen her alt öğede olay için bir işleyici ayarlar ve alt öğe kaldırıldığında işleyiciyi ayırır. Bu nedenle, görsel ağaçta alt öğeleri olan her öğe, alt öğelerinden birinin boyutu değiştiğinde uyarı alır. Aşağıdaki diyagramda, görsel ağaçtaki bir öğenin boyutundaki bir değişikliğin ağacı dalgalayan değişikliklere nasıl neden olabileceği gösterilmektedir:
Ancak sınıf, Layout
bir çocuğun boyutundaki değişikliğin sayfa düzeni üzerindeki etkisini kısıtlamaya çalışır. Düzen boyutu kısıtlanmışsa, alt boyut değişikliği görsel ağaçtaki üst düzenden daha yüksek bir şeyi etkilemez. Ancak, genellikle düzenin boyutundaki bir değişiklik, düzenin alt öğelerini nasıl düzenleyeceğini etkiler. Bu nedenle, düzenin boyutundaki herhangi bir değişiklik düzen için bir düzen döngüsü başlatır ve düzen ve LayoutChildren
yöntemlerine OnMeasure
çağrılar alır.
sınıfı, Layout
yöntemine InvalidateMeasure
benzer bir amaca sahip olan bir InvalidateLayout
yöntemi de tanımlar. Düzenin InvalidateLayout
alt öğelerini nasıl konumlandırdığını ve boyutlandırdığını etkileyen bir değişiklik yapıldığında yöntemi çağrılmalıdır. Örneğin, Layout
bir alt öğe bir düzene eklendiğinde veya bir düzenden kaldırıldığında sınıfı yöntemini çağırır InvalidateLayout
.
düzenin InvalidateLayout
alt öğelerinin yöntemlerinin yinelenen çağrılarını Measure
en aza indirmek için bir önbellek uygulamak için geçersiz kılınabilir. yöntemi geçersiz kılındığında InvalidateLayout
, alt öğeler düzene eklendiğinde veya düzenden kaldırıldığında bir bildirim sağlanır. Benzer şekilde, düzenin OnChildMeasureInvalidated
alt öğelerinden birinin boyutu değiştiğinde bildirim sağlamak için yöntemi geçersiz kılınabilir. Her iki yöntem geçersiz kılması için özel bir düzen önbelleği temizleyerek yanıt vermelidir. Daha fazla bilgi için bkz . Düzen Verilerini Hesaplama ve Önbelleğe Alma.
Özel Düzen Oluşturma
Özel düzen oluşturma işlemi aşağıdaki gibidir:
sınıfından türetilen
Layout<View>
bir sınıf oluşturun. Daha fazla bilgi için bkz . WrapLayout oluşturma.[isteğe bağlı] Düzen sınıfında ayarlanması gereken parametreler için bağlanabilir özellikler tarafından yedeklenen özellikler ekleyin. Daha fazla bilgi için bkz . Bağlanabilir Özellikler Tarafından Yedeklenen Özellikler Ekleme.
OnMeasure
Yöntemi düzendeki tüm alt öğelerde çağırmakMeasure
ve düzen için istenen boyutu döndürmek için yöntemini geçersiz kılın. Daha fazla bilgi için bkz . OnMeasure Yöntemini Geçersiz Kılma.Yöntemi, düzenin
LayoutChildren
Layout
tüm alt öğelerinde çağırmak için geçersiz kılın. Bir düzendeki her alt öğede yönteminin çağrılmamasıLayout
, çocuğun hiçbir zaman doğru boyut veya konum almamasına neden olur ve bu nedenle çocuk sayfada görünmez. Daha fazla bilgi için bkz . LayoutChildren Yöntemini Geçersiz Kılma.Not
ve geçersiz kılmalarında
OnMeasure
alt öğeleri numaralandırırken, özelliği olarakfalse
ayarlanmış olanIsVisible
tüm alt öğeleri atlayın.LayoutChildren
Bu, özel düzenin görünmez çocuklar için alan bırakmamasını sağlar.[isteğe bağlı] Alt öğeler düzene eklendiğinde veya düzenden kaldırıldığında bildirilecek yöntemi geçersiz kılın
InvalidateLayout
. Daha fazla bilgi için bkz . InvalidateLayout Yöntemini Geçersiz Kılma.[isteğe bağlı] Düzenin
OnChildMeasureInvalidated
alt öğelerinden birinin boyutu değiştiğinde bildirim almak için yöntemini geçersiz kılın. Daha fazla bilgi için bkz . OnChildMeasureInvalidated Yöntemini Geçersiz Kılma.
Not
Düzenin OnMeasure
boyutu alt öğeleri yerine üst öğe tarafından yönetiliyorsa geçersiz kılmanın çağrılmayacağını unutmayın. Ancak, kısıtlamalardan biri veya her ikisi de sonsuzsa veya düzen sınıfı varsayılan HorizontalOptions
olmayan veya VerticalOptions
özellik değerlerine sahipse geçersiz kılma çağrılır. Bu nedenle geçersiz kılma, LayoutChildren
yöntem çağrısı sırasında OnMeasure
elde edilen alt boyutları kullanamaz. Bunun yerine, LayoutChildren
yöntemini çağırmadan önce düzenin alt öğelerinde yöntemini çağırması Measure
Layout
gerekir. Alternatif olarak, geçersiz kılmada daha sonra Measure
çağrılmasını LayoutChildren
önlemek için geçersiz kılmada OnMeasure
elde edilen çocukların boyutu önbelleğe alınabilir, ancak düzen sınıfının boyutların yeniden ne zaman alınması gerektiğini bilmesi gerekir. Daha fazla bilgi için bkz . Düzen Verilerini Hesaplama ve Önbelleğe Alma.
Düzen sınıfı daha sonra bir öğesine Page
eklenerek ve düzene alt öğeler eklenerek kullanılabilir. Daha fazla bilgi için bkz . WrapLayout kullanma.
WrapLayout oluşturma
Örnek uygulama, alt öğelerini sayfada yatay olarak yerleştiren ve ardından sonraki alt öğelerin görünümünü ek satırlara kaydıran, yönlendirmeye duyarlı WrapLayout
bir sınıf gösterir.
sınıfıWrapLayout
, alt öğelerin en büyük boyutuna göre her alt öğe için hücre boyutu olarak bilinen aynı miktarda alan ayırır. Hücre boyutundan küçük çocuklar ve VerticalOptions
özellik değerlerine HorizontalOptions
göre hücre içinde konumlandırılabilir.
Sınıf WrapLayout
tanımı aşağıdaki kod örneğinde gösterilmiştir:
public class WrapLayout : Layout<View>
{
Dictionary<Size, LayoutData> layoutDataCache = new Dictionary<Size, LayoutData>();
...
}
Düzen Verilerini Hesaplama ve Önbelleğe Alma
Yapı, LayoutData
bir alt öğe koleksiyonu hakkındaki verileri bir dizi özellikte depolar:
VisibleChildCount
– düzende görünen alt öğe sayısı.CellSize
– düzenin boyutuna göre ayarlanmış tüm alt öğeleri en büyük boyut.Rows
– satır sayısı.Columns
– sütun sayısı.
Alanı layoutDataCache
, birden çok LayoutData
değeri depolamak için kullanılır. Uygulama başlatıldığında, geçerli yönlendirme için sözlükte iki LayoutData
nesne önbelleğe layoutDataCache
alınır: biri geçersiz kılmaya yönelik kısıtlama bağımsız değişkenleri OnMeasure
ve geçersiz kılmaya yönelik width
ve height
bağımsız değişkenleri için LayoutChildren
. Cihazı yatay yönlendirmeye döndürürken, OnMeasure
geçersiz kılma ve geçersiz kılma yeniden çağrılır ve LayoutChildren
bu da sözlükte başka iki LayoutData
nesnenin önbelleğe alınmasına neden olur. Ancak, cihazı dikey yönlendirmeye döndürürken, gerekli veriler zaten olduğundan layoutDataCache
başka hesaplama yapılması gerekmez.
Aşağıdaki kod örneği, belirli bir boyuta GetLayoutData
göre yapılandırılmış özellikleri LayoutData
hesaplayan yöntemini gösterir:
LayoutData GetLayoutData(double width, double height)
{
Size size = new Size(width, height);
// Check if cached information is available.
if (layoutDataCache.ContainsKey(size))
{
return layoutDataCache[size];
}
int visibleChildCount = 0;
Size maxChildSize = new Size();
int rows = 0;
int columns = 0;
LayoutData layoutData = new LayoutData();
// Enumerate through all the children.
foreach (View child in Children)
{
// Skip invisible children.
if (!child.IsVisible)
continue;
// Count the visible children.
visibleChildCount++;
// Get the child's requested size.
SizeRequest childSizeRequest = child.Measure(Double.PositiveInfinity, Double.PositiveInfinity);
// Accumulate the maximum child size.
maxChildSize.Width = Math.Max(maxChildSize.Width, childSizeRequest.Request.Width);
maxChildSize.Height = Math.Max(maxChildSize.Height, childSizeRequest.Request.Height);
}
if (visibleChildCount != 0)
{
// Calculate the number of rows and columns.
if (Double.IsPositiveInfinity(width))
{
columns = visibleChildCount;
rows = 1;
}
else
{
columns = (int)((width + ColumnSpacing) / (maxChildSize.Width + ColumnSpacing));
columns = Math.Max(1, columns);
rows = (visibleChildCount + columns - 1) / columns;
}
// Now maximize the cell size based on the layout size.
Size cellSize = new Size();
if (Double.IsPositiveInfinity(width))
cellSize.Width = maxChildSize.Width;
else
cellSize.Width = (width - ColumnSpacing * (columns - 1)) / columns;
if (Double.IsPositiveInfinity(height))
cellSize.Height = maxChildSize.Height;
else
cellSize.Height = (height - RowSpacing * (rows - 1)) / rows;
layoutData = new LayoutData(visibleChildCount, cellSize, rows, columns);
}
layoutDataCache.Add(size, layoutData);
return layoutData;
}
GetLayoutData
yöntemi aşağıdaki işlemleri gerçekleştirir:
- Hesaplanmış
LayoutData
bir değerin önbellekte olup olmadığını belirler ve varsa döndürür. - Aksi takdirde, tüm alt öğeleri numaralandırır, sonsuz genişlik ve boya sahip her alt öğede yöntemini çağırır
Measure
ve en büyük alt boyutu belirler. - En az bir görünür alt öğe olması koşuluyla, gerekli satır ve sütun sayısını hesaplar ve ardından alt öğeler için boyutlarına
WrapLayout
göre bir hücre boyutu hesaplar. Hücre boyutunun genellikle en büyük çocuk boyutundan biraz daha geniş olduğunu, ancak en geniş çocuk için yeterince geniş değilse veya en uzun çocuk için yeterince uzun değilseWrapLayout
daha küçük olabileceğini unutmayın. - Yeni
LayoutData
değeri önbellekte depolar.
Bağlanabilir Özellikler Tarafından Yedeklenen Özellikler Ekleme
WrapLayout
sınıfı, değerleri düzendeki satır ve sütunları ayırmak için kullanılan ve bağlanabilir özellikler tarafından yedeklenen ve özelliklerini tanımlar ColumnSpacing
RowSpacing
. Bağlanabilir özellikler aşağıdaki kod örneğinde gösterilmiştir:
public static readonly BindableProperty ColumnSpacingProperty = BindableProperty.Create(
"ColumnSpacing",
typeof(double),
typeof(WrapLayout),
5.0,
propertyChanged: (bindable, oldvalue, newvalue) =>
{
((WrapLayout)bindable).InvalidateLayout();
});
public static readonly BindableProperty RowSpacingProperty = BindableProperty.Create(
"RowSpacing",
typeof(double),
typeof(WrapLayout),
5.0,
propertyChanged: (bindable, oldvalue, newvalue) =>
{
((WrapLayout)bindable).InvalidateLayout();
});
Her bağlanabilir özelliğin özellik tarafından değiştirilen işleyicisi, üzerinde yeni bir düzen geçişi tetikleyen yöntem geçersiz kılmasını WrapLayout
çağırırInvalidateLayout
. Daha fazla bilgi için bkz . InvalidateLayout Yöntemini Geçersiz Kılma ve OnChildMeasureInvalidated Yöntemini Geçersiz Kılma.
OnMeasure Yöntemini Geçersiz Kılma
Geçersiz OnMeasure
kılma aşağıdaki kod örneğinde gösterilmiştir:
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
LayoutData layoutData = GetLayoutData(widthConstraint, heightConstraint);
if (layoutData.VisibleChildCount == 0)
{
return new SizeRequest();
}
Size totalSize = new Size(layoutData.CellSize.Width * layoutData.Columns + ColumnSpacing * (layoutData.Columns - 1),
layoutData.CellSize.Height * layoutData.Rows + RowSpacing * (layoutData.Rows - 1));
return new SizeRequest(totalSize);
}
Geçersiz kılma yöntemini çağırır GetLayoutData
ve döndürülen verilerden bir SizeRequest
nesne oluştururken ve ColumnSpacing
özellik değerlerini de dikkate RowSpacing
alır. Yöntemi hakkında GetLayoutData
daha fazla bilgi için bkz . Hesaplama ve Önbellek Düzeni Verileri.
Önemli
Measure
ve OnMeasure
yöntemleri, özelliği olarak ayarlanmış Double.PositiveInfinity
bir SizeRequest
değer döndürerek hiçbir zaman sonsuz boyut istememelidir. Ancak, için OnMeasure
kısıtlama bağımsız değişkenlerinden en az biri olabilir Double.PositiveInfinity
.
LayoutChildren Yöntemini Geçersiz Kılma
Geçersiz LayoutChildren
kılma aşağıdaki kod örneğinde gösterilmiştir:
protected override void LayoutChildren(double x, double y, double width, double height)
{
LayoutData layoutData = GetLayoutData(width, height);
if (layoutData.VisibleChildCount == 0)
{
return;
}
double xChild = x;
double yChild = y;
int row = 0;
int column = 0;
foreach (View child in Children)
{
if (!child.IsVisible)
{
continue;
}
LayoutChildIntoBoundingRegion(child, new Rectangle(new Point(xChild, yChild), layoutData.CellSize));
if (++column == layoutData.Columns)
{
column = 0;
row++;
xChild = x;
yChild += RowSpacing + layoutData.CellSize.Height;
}
else
{
xChild += ColumnSpacing + layoutData.CellSize.Width;
}
}
}
Geçersiz kılma yöntemine GetLayoutData
yapılan bir çağrıyla başlar ve sonra tüm alt öğeleri her alt öğe hücresinde boyutlandırmak ve konumlandırmak için numaralandırır. Bu, bir alt öğeyi ve VerticalOptions
özellik değerlerine LayoutChildIntoBoundingRegion
göre HorizontalOptions
dikdörtgen içinde konumlandırmak için kullanılan yöntemini çağırarak elde edilir. Bu, çocuğun Layout
yöntemine çağrı yapmaya eşdeğerdir.
Not
yöntemine geçirilen dikdörtgenin LayoutChildIntoBoundingRegion
, çocuğun bulunabileceği alanın tamamını içerdiğini unutmayın.
Yöntemi hakkında GetLayoutData
daha fazla bilgi için bkz . Hesaplama ve Önbellek Düzeni Verileri.
InvalidateLayout Yöntemini Geçersiz Kılma
Geçersiz InvalidateLayout
kılma, aşağıdaki kod örneğinde gösterildiği gibi alt öğeler düzene eklendiğinde veya düzenden kaldırıldığında ya da özelliklerden WrapLayout
biri değeri değiştirdiğinde çağrılır:
protected override void InvalidateLayout()
{
base.InvalidateLayout();
layoutInfoCache.Clear();
}
Geçersiz kılma, düzeni geçersiz kılar ve önbelleğe alınan tüm düzen bilgilerini atar.
Not
Bir düzene bir alt öğe eklendiğinde veya bir düzenden kaldırıldığında sınıfın yöntemini çağırmasını durdurmak Layout
için ve ShouldInvalidateOnChildRemoved
yöntemlerini geçersiz kılın ShouldInvalidateOnChildAdded
ve döndürürfalse
.InvalidateLayout
Düzen sınıfı daha sonra alt öğeler eklendiğinde veya kaldırıldığında özel bir işlem uygulayabilir.
OnChildMeasureInvalidated Yöntemini Geçersiz Kılma
Düzenin OnChildMeasureInvalidated
alt öğelerinden birinin boyutu değiştiğinde geçersiz kılma çağrılır ve aşağıdaki kod örneğinde gösterilir:
protected override void OnChildMeasureInvalidated()
{
base.OnChildMeasureInvalidated();
layoutInfoCache.Clear();
}
Geçersiz kılma alt düzeni geçersiz kılar ve önbelleğe alınan tüm düzen bilgilerini atar.
WrapLayout kullanma
Sınıfı WrapLayout
, aşağıdaki XAML kod örneğinde gösterildiği gibi türetilmiş bir Page
türe yerleştirilerek kullanılabilir:
<ContentPage ... xmlns:local="clr-namespace:ImageWrapLayout">
<ScrollView Margin="0,20,0,20">
<local:WrapLayout x:Name="wrapLayout" />
</ScrollView>
</ContentPage>
Eşdeğer C# kodu aşağıda gösterilmiştir:
public class ImageWrapLayoutPageCS : ContentPage
{
WrapLayout wrapLayout;
public ImageWrapLayoutPageCS()
{
wrapLayout = new WrapLayout();
Content = new ScrollView
{
Margin = new Thickness(0, 20, 0, 20),
Content = wrapLayout
};
}
...
}
Daha sonra alt öğelere gerektiği gibi eklenebilir WrapLayout
. Aşağıdaki kod örneği öğesine eklenen WrapLayout
öğeleri gösterirImage
:
protected override async void OnAppearing()
{
base.OnAppearing();
var images = await GetImageListAsync();
if (images != null)
{
foreach (var photo in images.Photos)
{
var image = new Image
{
Source = ImageSource.FromUri(new Uri(photo))
};
wrapLayout.Children.Add(image);
}
}
}
async Task<ImageList> GetImageListAsync()
{
try
{
string requestUri = "https://raw.githubusercontent.com/xamarin/docs-archive/master/Images/stock/small/stock.json";
string result = await _client.GetStringAsync(requestUri);
return JsonConvert.DeserializeObject<ImageList>(result);
}
catch (Exception ex)
{
Debug.WriteLine($"\tERROR: {ex.Message}");
}
return null;
}
öğesini içeren sayfa göründüğünde WrapLayout
, örnek uygulama fotoğraf listesini içeren uzak bir JSON dosyasına zaman uyumsuz olarak erişir, her fotoğraf için bir Image
öğe oluşturur ve bunu WrapLayout
öğesine ekler. Bu, aşağıdaki ekran görüntülerinde gösterilen görünüme neden olur:
Aşağıdaki ekran görüntüleri, yatay yönlendirmeye döndürüldükten sonrasını gösterir WrapLayout
:
Her satırdaki sütun sayısı fotoğraf boyutuna, ekran genişliğine ve cihazdan bağımsız birim başına piksel sayısına bağlıdır. Image
Öğeler fotoğrafları zaman uyumsuz olarak yükler ve bu nedenle WrapLayout
her Image
öğe yüklenen fotoğrafa göre yeni bir boyut aldığından sınıfı yöntemine sık sık çağrılar LayoutChildren
alır.