第十四章:絕對佈局(三)

wangccsy發表於2018-08-30

比例尺寸和定位

如您所見,ChessboardDynamic程式根據AbsoluteLayout本身的大小重新定位BoxView子項並調整其大小。 換句話說,每個孩子的大小和位置與容器的大小成比例。 有趣的是,AbsoluteLayout通常就是這種情況,如果AbsoluteLayout自動適應這種情況可能會很好。
它確實!
AbsoluteLayout定義了第二個附加的可繫結屬性,名為LayoutFlagsProperty,還有兩個靜態方法,名為SetLayoutFlags和GetLayoutFlags。 設定此附加的可繫結屬性允許您指定與AbsoluteLayout的大小成比例的子位置座標或大小(或兩者)。 在佈置孩子時,AbsoluteLayout會對這些孩子進行擴充套件
適當的座標和大小。
您可以選擇此功能如何與AbsoluteLayoutFlags列舉的一個或多個成員一起使用:

  • None (equal to 0)
  • XProportional (1)
  • YProportional (2)
  • PositionProportional (3)
  • WidthProportional (4)
  • HeightProportional (8)
  • SizeProportional (12)
  • All (xFFFFFFFF)

您可以使用兩個靜態方法在AbsoluteLayout的子項上設定比例位置和大小:

AbsoluteLayout.SetLayoutBounds(view, rect);
AbsoluteLayout.SetLayoutFlags(view, AbsoluteLayoutFlags.All);

或者,您可以在接受AbsoluteLayoutFlags列舉成員的Children集合上使用Add方法的一個版本:

absoluteLayout.Children.Add(view, rect, AbsoluteLayoutFlags.All);

例如,如果使用SizeProportional標誌並將子項的寬度設定為0.25,將高度設定為0.10,則子項將是AbsoluteLayout寬度的四分之一和高度的十分之一。很容易。
PositionProportional標誌是類似的,但它考慮到孩子的大小:位置(0,0)將孩子放在左上角,位置(1,1)將孩子放在較低的位置 – 右上角和(0.5,0.5)的位置使孩子在AbsoluteLayout中居中。考慮到孩子的大小對於某些任務來說是很好的 – 例如將孩子置於AbsoluteLayout中心或者將其顯示在右邊或底邊 – 但對其他任務來說有點尷尬。
這是ChessboardProportional。定位和大小調整的大部分工作已經移回建構函式。 SizeChanged處理程式現在僅通過將AbsoluteLayout的WidthRequest和HeightRequest屬性設定為ContentView的寬度和高度的最小值來維持整體寬高比。刪除SizeChanged處理,棋盤擴充套件到頁面大小而不是填充。

public class ChessboardProportionalPage : ContentPage
{
    AbsoluteLayout absoluteLayout;
    public ChessboardProportionalPage()
    {
        absoluteLayout = new AbsoluteLayout
        {
            BackgroundColor = Color.FromRgb(240, 220, 130),
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
        for (int row = 0; row < 8; row++)
        {
            for (int col = 0; col < 8; col++)
            {
                // Skip every other square.
                if (((row ^ col) & 1) == 0)
                    continue;
                BoxView boxView = new BoxView
                {
                    Color = Color.FromRgb(0, 64, 0)
                };
                Rectangle rect = new Rectangle(col / 7.0, // x
                                               row / 7.0, // y
                                               1 / 8.0, // width
                                               1 / 8.0); // height
                absoluteLayout.Children.Add(boxView, rect, AbsoluteLayoutFlags.All);
            }
        }
        ContentView contentView = new ContentView
        {
            Content = absoluteLayout
        };
        contentView.SizeChanged += OnContentViewSizeChanged;
        this.Padding = new Thickness(5, Device.OnPlatform(25, 5, 5), 5, 5);
         this.Content = contentView;
    }
    void OnContentViewSizeChanged(object sender, EventArgs args)
    {
        ContentView contentView = (ContentView)sender;
        double boardSize = Math.Min(contentView.Width, contentView.Height);
        absoluteLayout.WidthRequest = boardSize;
        absoluteLayout.HeightRequest = boardSize;
    }
}

螢幕看起來與ChessboardDynamic程式相同。
每個BoxView都使用以下程式碼新增到AbsoluteLayout。 所有分母都是浮點值,因此除法的結果將轉換為double:

Rectangle rect = new Rectangle(col / 7.0, // x
                               row / 7.0, // y
                               1 / 8.0, // width
                               1 / 8.0); // height
absoluteLayout.Children.Add(boxView, rect, AbsoluteLayoutFlags.All);

寬度和高度始終等於AbsoluteLayout的寬度和高度的八分之一。 這很清楚。 但是對於相對x和y座標,row和col變數除以7(而不是8)。 for迴圈中的row和col變數的範圍是0到7.行和col值0對應於left或top,但row和col值7必須對映到x和y座標1以將子項定位到 右邊或底邊。
如果您認為可能需要一些可靠的規則來獲得比例座標,請繼續閱讀。


相關文章