2017-10-12 28 views
0

任何人都知道爲什麼下面的代碼不會在我的Forms應用程序中執行OnMeasure()?基本上,我試圖迫使AbsoluteLayout具有相同的高度/寬度顯示爲一個廣場:在OnMeasure通話如何在我的AbsoluteLayout上強制正方形佈局?

public class AbsoluteSquareLayout : AbsoluteLayout 
{ 
    protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) 
    { 
     var size = Math.Min(widthConstraint, heightConstraint); 
     return base.OnMeasure(size, size); 
    } 
} 

回答

1

重寫尺寸的限制並不能保證最終大小 - 從父母最終Layout通佈局將覆蓋此值。 XF文章here對此進行了詳細的討論。

爲了能夠實現方形佈局 - 您將不得不更新父佈局以考慮這些約束,並確保它在佈局傳遞中傳遞。

例如,您可以擴展AbsoluteLayout以動態計算兒童的大小限制。此自定義佈局默認將所有兒童視爲正方形。爲了覆蓋特定孩子的這種行爲 - 您可以將附加屬性SquareLayout.IsSquare設置爲false

public class SquareLayout : AbsoluteLayout 
{ 

    public static readonly BindableProperty IsSquareProperty = 
      BindableProperty.CreateAttached("IsSquare", 
              typeof(bool), 
              typeof(SquareLayout), 
              defaultValue: true, 
              defaultBindingMode: BindingMode.OneWay); 

    public static bool GetIsSquare(BindableObject view) 
    { 
     return (bool)view.GetValue(IsSquareProperty); 
    } 

    public static void SetIsSquare(BindableObject view, bool value) 
    { 
     view.SetValue(IsSquareProperty, value); 
    } 

    Dictionary<View, Rectangle> _boundsCache = new Dictionary<View, Rectangle>(); 
    protected override void LayoutChildren(double x, double y, double width, double height) 
    { 
     foreach(var child in Children) 
     { 
      var isSquare = GetIsSquare(child); 
      if(isSquare) 
      { 
       Rectangle bounds; 
       if (!_boundsCache.ContainsKey(child)) 
        _boundsCache[child] = bounds = GetLayoutBounds(child); 
       else 
        bounds = _boundsCache[child]; 

       var absFlags = GetLayoutFlags(child); 

       var widthIsProportional = (absFlags & AbsoluteLayoutFlags.WidthProportional) != 0; 
       var heightIsProportional = (absFlags & AbsoluteLayoutFlags.HeightProportional) != 0; 

       var childWidth = widthIsProportional ? bounds.Width * width : bounds.Width; 
       var childHeight = heightIsProportional ? bounds.Height * height : bounds.Height; 

       var size = Math.Min(childWidth, childHeight); 

       SetLayoutBounds(
        child, 
        new Rectangle(
         bounds.X, 
         bounds.Y, 
         (widthIsProportional ? (size/width) : size), 
         (heightIsProportional ? (size/height) : size) 
        ) 
       ); 
      } 
     } 

     base.LayoutChildren(x, y, width, height); 
    } 
} 

使用範例:

<local:SquareLayout> 
    <AbsoluteLayout BackgroundColor="Green" 
        AbsoluteLayout.LayoutBounds=".1,.1,1,1" 
        AbsoluteLayout.LayoutFlags="All" /> 

    <AbsoluteLayout BackgroundColor="Blue" 
        AbsoluteLayout.LayoutBounds=".5,.5,.2,.1" 
        AbsoluteLayout.LayoutFlags="All" /> 

    <AbsoluteLayout BackgroundColor="Red" 
        AbsoluteLayout.LayoutBounds=".9,.9,200,200" 
        AbsoluteLayout.LayoutFlags="PositionProportional" /> 

    <AbsoluteLayout BackgroundColor="Yellow" 
        AbsoluteLayout.LayoutBounds="10,20,.3,.3" 
        AbsoluteLayout.LayoutFlags="SizeProportional" /> 

    <AbsoluteLayout BackgroundColor="Silver" 
        local:SquareLayout.IsSquare="false" 
        AbsoluteLayout.LayoutBounds=".9,.9,1,.1" 
        AbsoluteLayout.LayoutFlags="All" /> 
</local:SquareLayout> 

enter image description here enter image description here

+0

哇很好的解釋!感謝您的理解:) – Maximus

相關問題