天天看點

第十四章:絕對布局(四)使用比例坐标

使用比例坐标

在AbsoluteLayout中使用比例定位可能很棘手。 有時您需要補償考慮到大小的内部計算。 例如,您可能更喜歡指定坐标,以便X值為1表示子項的左邊緣位于AbsoluteLayout的右邊緣,您需要将其轉換為AbsoluteLayout了解的坐标。

在下面的讨論中,一個不考慮大小的坐标 - 一個坐标,其中1表示子項位于AbsoluteLay的右邊緣或底邊之外? - 被稱為小數坐标。本節的目标是開發将小數坐标轉換為可與AbsoluteLayout一起使用的比例坐标的規則。此配置檔案要求您知道子視圖的大小。

假設您将名為child的視圖放在名為absoluteLayout的AbsoluteLayout中,并為名為layoutBounds的子項設定布局邊界矩形。讓我們将此分析限制為水準坐标和大小。垂直坐标和尺寸的過程相同。

這個孩子必須先以某種方式獲得寬度。子節點可以計算自己的寬度,或者可以通過LayoutBounds附加屬性為與裝置無關的單元配置設定寬度。但是我們假設設定了AbsoluteLayoutFlags.WidthProportional标志,這意味着寬度是根據布局邊界的寬度字段和AbsoluteLay的寬度來計算的:

child.Width = layoutBounds.Width * absoluteLayout.Width           

如果還設定了AbsoluteLayoutFlags.XProportional标志,那麼AbsoluteLayout内部通過考慮子項的大小來計算子項相對于自身的坐标:

relativeChildCorrdinate.X = (absoluteLayout.Width - child.Width) * layoutBounds.X           

例如,如果AbsoluteLayout的寬度為400,而子節點的寬度為100,而layoutBounds.X為0.5,則relativeChildCoordinate.X計算為150.這意味着子節點的左邊緣為150 來自父級左邊緣的像素。 這會導緻子項在AbsoluteLayout中水準居中。

也可以計算小數子坐标:

fractionalChildCoordinate.X = relativeChildCoordinate.X / absoluteLayout.Width           

這與比例坐标不同,因為小數子坐标為1意味着孩子的左邊緣恰好位于AbsoluteLayout的右邊緣之外,是以子項位于AbsoluteLayout的表面之外。 要繼續該示例,小數子坐标為150除以400或0.375。 子視圖的左側位于(0.375 * 400)或距離AbsoluteLayout左邊緣150個機關。

讓我們重新排列公式的術語,計算要為layoutBounds.X求解的相對子坐标:

layoutBounds.X = relativeChildCoordinate.X / (absoluteLayout.WIdth - child.Width)           

讓我們将該比率的頂部和底部除以AbsoluteLayout的寬度:

layoutBounds.X = fractionalChildCoordinate.X / (1 - child.Width / absoluteLayout.Width)           

如果你也使用比例寬度,那麼分母中的那個比例是layoutBounds.Width:

layoutBounds.X = fractionalChildCoordinate.X / ( 1 - layoutBounds.Width)           

這通常是一個非常友善的公式,因為它允許您從小數子坐标轉換為比例坐标,以便在布局邊界矩形中使用。

在ChessboardProportional示例中,當col等于7時,fractionalChildCoordi?nate.X為7除以列數(8)或7/8。 分母是1減1/8(正方形的比例寬度),或者再次是7/8。 比例為1。

讓我們看一個公式在代碼中應用于小數坐标的示例。 Propor tionalCoordinateCalc程式嘗試使用粉紅色AbsoluteLayout上的八個藍色BoxView元素重制這個簡單的圖形:

第十四章:絕對布局(四)使用比例坐标

整個數字有2:1的比例。 您可以将該圖視為包含四個水準矩形和四個垂直矩形。 頂部和底部的水準藍色矩形對具有0.1個分數機關的高度(相對于AbsoluteLayout的高度),并且從頂部和底部以及彼此之間間隔0.1個機關。 垂直的藍色矩形看起來間隔和尺寸相似,但由于縱橫比為2:1,垂直矩形的寬度為0.05個機關,并且從左側和右側以及彼此之間間隔0.05個機關。

AbsoluteLayout在XAML檔案中定義并居中,并以粉紅色着色:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ProportionalCoordinateCalc.ProportionalCoordinateCalcPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="5, 25, 5, 5"
                    Android="5"
                    WinPhone="5" />
    </ContentPage.Padding>
    <ContentView SizeChanged="OnContentViewSizeChanged">
        <AbsoluteLayout x:Name="absoluteLayout"
                        BackgroundColor="Pink"
                        HorizontalOptions="Center"
                        VerticalOptions="Center" />
    </ContentView>
</ContentPage>           

代碼隐藏檔案定義了一個Rectangle結構數組,其中包含八個BoxView元素中每個元素的小數坐标。 在foreach循環中,程式應用上面顯示的最終公式的略微變化。 而不是分母等于1減去布局的值?Bounds.Width(或layoutBounds.Height),它使用小數界限的寬度(或高度),它是相同的值。

public partial class ProportionalCoordinateCalcPage : ContentPage
{
    public ProportionalCoordinateCalcPage()
    {
        InitializeComponent();
        Rectangle[] fractionalRects = 
        {
            new Rectangle(0.05, 0.1, 0.90, 0.1), // outer top
            new Rectangle(0.05, 0.8, 0.90, 0.1), // outer bottom
            new Rectangle(0.05, 0.1, 0.05, 0.8), // outer left
            new Rectangle(0.90, 0.1, 0.05, 0.8), // outer right
            new Rectangle(0.15, 0.3, 0.70, 0.1), // inner top
            new Rectangle(0.15, 0.6, 0.70, 0.1), // inner bottom
            new Rectangle(0.15, 0.3, 0.05, 0.4), // inner left
            new Rectangle(0.80, 0.3, 0.05, 0.4), // inner right
        };
        foreach (Rectangle fractionalRect in fractionalRects)
        {
            Rectangle layoutBounds = new Rectangle
            {
                // Proportional coordinate calculations.
                X = fractionalRect.X / (1 - fractionalRect.Width),
                Y = fractionalRect.Y / (1 - fractionalRect.Height),
                Width = fractionalRect.Width,
                Height = fractionalRect.Height
            };
            absoluteLayout.Children.Add(
                new BoxView
                {
                    Color = Color.Blue
                },
                layoutBounds,
                AbsoluteLayoutFlags.All);
        }
    }
    void OnContentViewSizeChanged(object sender, EventArgs args)
    {
        ContentView contentView = (ContentView)sender;
        // Figure has an aspect ratio of 2:1.
        double height = Math.Min(contentView.Width / 2, contentView.Height);
        absoluteLayout.WidthRequest = 2 * height;
        absoluteLayout.HeightRequest = height;
    }
}           

SizeChanged處理程式隻是修複了寬高比。

這是結果:

第十四章:絕對布局(四)使用比例坐标

而且,當然,您可以将手機側向轉動,并在橫向模式下看到更大的數字,您必須通過側向翻書來檢視:

第十四章:絕對布局(四)使用比例坐标

繼續閱讀