搞懂Xamarin.Forms佈局,看這篇應該就夠了吧

  Xamarin.Forms 佈局介紹

  什麼是佈局?能夠簡單的理解爲,咱們經過將佈局元素有效的組織起來,讓屏幕變成咱們想要的樣子!
html

  咱們經過畫圖的方式來描述一下Xamarin.Forms的佈局。git

    小節錨點:github

      佈局控件之StackLayout性能優化

      Xamarin.Forms 中能夠C#代碼進行佈局less

      Xamarin.Forms 的佈局方向函數

      邊距和填充工具

      八種佈局選項佈局

      佈局控件之Grid性能

      佈局控件之AbsoluteLayout學習

      佈局控件之ScrollView

      佈局控件之RelativeLayout

      佈局控件之FlexLayout

      佈局壓縮LayoutCompression

  佈局控件之StackLayout

  Xamarin.Forms 經常使用的有 6 種佈局控件,咱們先選一個最基礎最經常使用的佈局控件 StackLayout 來說解佈局。後面的內容再依次介紹其餘佈局控件。StackLayout 中文翻譯又叫「堆棧佈局」,意指在Xamarin.Forms中使用XAML代碼或者是C#代碼,經過一維排列的方式來完成佈局。

  咱們能夠從圖上看到 StackLayout 是從上到下依次排列的,StackLayout 並不複雜,它只是簡單的線性方式排列。若是想建立更復雜的佈局,咱們可使用 StackLayout 嵌套的方式來完成佈局。

  咱們先來演練一個簡單的 StackLayout :

 

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Layout"
             x:Class="Layout.MainPage">


    <StackLayout>
        <StackLayout BackgroundColor="#A8A8A8">
            <Label Text="佈局1"/>
        </StackLayout>
        <StackLayout BackgroundColor="#A8A8A8">
            <Label Text="佈局2"/>
        </StackLayout>
        <StackLayout BackgroundColor="#A8A8A8">
            <Label Text="佈局3"/>
        </StackLayout>
        <StackLayout BackgroundColor="#A8A8A8">
            <Label Text="佈局4"/>
        </StackLayout>
        <StackLayout BackgroundColor="#A8A8A8">
            <Label Text="佈局5"/>
        </StackLayout>
    </StackLayout>

</ContentPage>

  能夠看到咱們使用 XAML代碼實現了一個簡單的佈局,咱們將五個StackLayout 嵌套到一個 StackLayout,對每一個內嵌的StackLayout設置背景顏色爲 #A8A8A8,StackLayout 中再放入一個文本。代碼寫完直接運行就變成了圖上的樣子。由於本人沒有使用Mac電腦,沒法打包IOS應用,因此暫時只放 Android 的圖。

 

  Xamarin.Forms 中能夠C#代碼進行佈局

  實際上在Xamarin.Forms中不止能夠經過XAML代碼的方式來佈局,咱們還可使用C#代碼來完成佈局。

  剛剛演示了XAML方式寫一個簡單的StackLayout佈局,本輪演示一個C#代碼佈局。

 

 

 C# 代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CSharpLayout : ContentPage
    {
        public CSharpLayout ()
        {
            InitializeComponent ();

            //最外面的StackLayout
            var stackLayout = new StackLayout();

            //嵌套StackLayout_1
            var stackLayout_1 = new StackLayout() { BackgroundColor = Color.FromHex("#A8A8A8") };
            stackLayout_1.Children.Add(new Label() { Text = "C#編寫佈局1" });
            stackLayout.Children.Add(stackLayout_1);

            //嵌套StackLayout_2
            var stackLayout_2 = new StackLayout() { BackgroundColor = Color.FromHex("#A8A8A8") };
            stackLayout_2.Children.Add(new Label() { Text = "C#編寫佈局2" });
            stackLayout.Children.Add(stackLayout_2);

            //嵌套StackLayout_3
            var stackLayout_3 = new StackLayout() { BackgroundColor = Color.FromHex("#A8A8A8") };
            stackLayout_3.Children.Add(new Label() { Text = "C#編寫佈局3" });
            stackLayout.Children.Add(stackLayout_3);

            //嵌套StackLayout_4
            var stackLayout_4 = new StackLayout() { BackgroundColor = Color.FromHex("#A8A8A8") };
            stackLayout_4.Children.Add(new Label() { Text = "C#編寫佈局4" });
            stackLayout.Children.Add(stackLayout_4);

            //嵌套StackLayout_5
            var stackLayout_5 = new StackLayout() { BackgroundColor = Color.FromHex("#A8A8A8") };
            stackLayout_5.Children.Add(new Label() { Text = "C#編寫佈局5" });
            stackLayout.Children.Add(stackLayout_5);

            //將StackLayout放入Content
            Content = stackLayout;
        }
    }
}

  咱們能夠看到,前面用XAML實現的佈局,咱們用C#代碼一樣能夠實現。只是使用C#代碼咱們可能會寫更多的代碼而已。從單純佈局來講,微軟官方推薦咱們使用 XAML 方式佈局。那 C# 方式在什麼場景下使用呢?我認爲咱們在實現動態數據綁定效果,或者是頁面控件動態生成時,咱們可使用C#代碼完成。若是你搞過Web開發,就能夠理解爲寫XAML等於直接寫HTML,寫C#代碼等於用Javascript來生成HTML。

  總的來講,XAML方式佈局更簡潔,易讀寫,C#代碼佈局更靈活更動態。

 

  Xamarin.Forms 的佈局方向

   在Xamarin.Forms中目前支持兩種佈局方向:

    Horizontal(水平佈局):從左到右佈局

    Vertical(垂直佈局): 從上到下佈局

 

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.LayoutOrientation">
    <ContentPage.Content>
        <StackLayout>

            <StackLayout Orientation="Horizontal" BackgroundColor="#A8A8A8">
                <Label Text="水平"/>
                <Label Text="水平"/>
                <Label Text="水平"/>
            </StackLayout>

            <StackLayout Orientation="Vertical" BackgroundColor="#A8A8A8">
                <Label Text="垂直"/>
                <Label Text="垂直"/>
                <Label Text="垂直"/>
            </StackLayout>

            <StackLayout BackgroundColor="#A8A8A8">
                <Label Text="默認"/>
                <Label Text="默認"/>
                <Label Text="默認"/>
            </StackLayout>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

 

C# 代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CSharpLayoutOrientation : ContentPage
    {
        public CSharpLayoutOrientation ()
        {
            InitializeComponent ();

            var stackLayout = new StackLayout();

            //設置以水平方式佈局
            var stackLayout_1 = new StackLayout()
            {
                Orientation = StackOrientation.Horizontal,
                BackgroundColor = Color.FromHex("#A8A8A8")
            };
            stackLayout_1.Children.Add(new Label() { Text = "水平" });
            stackLayout_1.Children.Add(new Label() { Text = "水平" });
            stackLayout_1.Children.Add(new Label() { Text = "水平" });

            //設置以垂直方式佈局
            var stackLayout_2 = new StackLayout()
            {
                Orientation = StackOrientation.Vertical,
                BackgroundColor = Color.FromHex("#A8A8A8")
            };
            stackLayout_2.Children.Add(new Label() { Text = "垂直" });
            stackLayout_2.Children.Add(new Label() { Text = "垂直" });
            stackLayout_2.Children.Add(new Label() { Text = "垂直" });

            //默認的方式佈局
            var stackLayout_3 = new StackLayout()
            {
                BackgroundColor = Color.FromHex("#A8A8A8")
            };
            stackLayout_3.Children.Add(new Label() { Text = "默認" });
            stackLayout_3.Children.Add(new Label() { Text = "默認" });
            stackLayout_3.Children.Add(new Label() { Text = "默認" });


            stackLayout.Children.Add(stackLayout_1);
            stackLayout.Children.Add(stackLayout_2);
            stackLayout.Children.Add(stackLayout_3);

            Content = stackLayout;
        }
    }
}

 

  咱們能夠看到,我用水平,垂直,默認三種方式來展示了佈局方向。

  設置 StackLayout 的 Orientation 屬性爲 Horizontal 表示,系統將會以水平方式來佈局。

  設置 StackLayout 的 Orientation 屬性爲 Vertical 表示,系統將會以垂直方式來佈局。

  默認 StackLayout 的 Orientation 屬性爲 Horizontal。

 

  邊距和填充

  咱們在使用佈局的時候,能夠經過邊距、填充屬性來控制佈局行爲。

    Margin:表示一個元素與它相鄰的元素之間的距離。

    Padding:表示一個元素與它的子元素之間的距離。

 

 

 

 

  Margin 和 Padding 都有四個方位的值,分別是 上下左右。

  特別要注意的是,Margin 的值是有累加性的。好比:咱們把兩個相鄰元素的Margin值分別設置爲 Margin 。

  下面咱們用代碼來預覽一下:

  

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.MarginPadding">
    <ContentPage.Content>

        <StackLayout BackgroundColor="#A8A8A8">

            <StackLayout BackgroundColor="#f9d33c" Margin="60,60,60,60" Padding="30,30,30,30">
                <StackLayout BackgroundColor="#91e2f4" WidthRequest="200" HeightRequest="100">
                    <Label Text="Child"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Margin="60,60,60,60" Padding="30,30,30,30">
                <StackLayout BackgroundColor="#91e2f4" WidthRequest="200" HeightRequest="100">
                    <Label Text="Child"/>
                </StackLayout>
            </StackLayout>

        </StackLayout>

    </ContentPage.Content>
</ContentPage>

C# 代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CSharpMarginPadding : ContentPage
    {
        public CSharpMarginPadding()
        {
            InitializeComponent();

            var stackLayout = new StackLayout() {
                BackgroundColor = Color.FromHex("#A8A8A8")
            };

            var stackLayout_1 = new StackLayout()
            {
                BackgroundColor = Color.FromHex("#f9d33c"),
                Margin = new Thickness(60, 60, 60, 60),
                Padding = new Thickness(30, 30, 30, 30)
            };
            var stackLayout_1_1 = new StackLayout()
            {
                BackgroundColor = Color.FromHex("#91e2f4"),
                WidthRequest = 200,
                HeightRequest = 100
            };
            stackLayout_1_1.Children.Add(new Label() { Text = "Child" });
            stackLayout_1.Children.Add(stackLayout_1_1);
            stackLayout.Children.Add(stackLayout_1);


            var stackLayout_2 = new StackLayout()
            {
                BackgroundColor = Color.FromHex("#f9d33c"),
                Margin = new Thickness(60, 60, 60, 60),
                Padding = new Thickness(30, 30, 30, 30)
            };
            var stackLayout_2_1 = new StackLayout()
            {
                BackgroundColor = Color.FromHex("#91e2f4"),
                WidthRequest = 200,
                HeightRequest = 100
            };
            stackLayout_2_1.Children.Add(new Label() { Text = "Child" });
            stackLayout_2.Children.Add(stackLayout_2_1);
            stackLayout.Children.Add(stackLayout_2);


            Content = stackLayout;

        }
    }
}

咱們能夠看到 Margin 和 Padding 分別展示的效果。而兩個相鄰元素分別設置 Margin Bottom = 60 ,Margin Top = 60 ,讓兩個元素中間的間距爲 120。

咱們再進一步,咱們來看看 Margin 和 Padding 是什麼類型。

 

 

 

從圖片上,咱們能夠看到,Margin 是屬於 Xamarin.Forms.View 的一個屬性,類型爲 Xamarin.Forms.Thickness

 


 

 

從圖片上,咱們能夠看到,Padding 是屬於 Xamarin.Forms.Layout 的一個屬性,類型爲 Xamarin.Forms.Thickness

小結:Xamarin.Forms.Thickness 是一個結構體,咱們能夠經過該結構體設置元素的上下左右的間距。

 

  八種佈局選項

  Xamarin.Forms 中全部的 View 都具備類型爲 Xamarin.Forms.LayoutOptions 的 HorizontalOptions 和 VerticalOptions 兩個屬性。

  那麼哪些控件是屬於 Xamarin.Forms.View 類型的呢?諸如經常使用的佈局控件 StackLayout,AbsoluteLayout,RelativeLayout ,Grid,FlexLayout,ScrollView 等控件都是直接或間接繼承自 Xamarin.Forms.View 的。

  總之, Xamarin.Forms.LayoutOptions 在 Xamarin.Forms 佈局工做中是很是重要的!

 

  Xamarin.Forms.LayoutOptions 說明:

    HorizontalOptions:

      Start:在父元素中以 水平方向靠左 排列

      Center:在父元素中以 水平方向居中 排列

      End:在父元素中以 水平方向靠右 排列

      Fill:在父元素中以 填充方式 排列

      StartAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向靠左 排列

      CenterAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向居中 排列

      EndAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向靠右 排列

      FillAndExpand:在父元素中以 填充方式 排列

    VerticalOptions :

      Start:在父元素中以 垂直方向靠上 排列

      Center:在父元素中以 垂直方向居中 排列

      End:在父元素中以 垂直方向靠下 排列

      Fill:在父元素中以 填充方式 排列

      StartAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向靠上 排列

      CenterAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向居中 排列

      EndAndExpand:在父元素中 將父元素剩餘部分填充後 以 水平方向靠下 排列

      FillAndExpand:在父元素中以 填充方式 排列

 

  接下來咱們用代碼和圖片預覽的方式分別來講明一下:

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.LayoutOptions">
    <ContentPage.Content>
        <StackLayout BackgroundColor="#A8A8A8">

            
            <StackLayout BackgroundColor="#f9d33c">
                <!--Start_1在水平選項最左側位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Start">
                    <Label Text="Start_1"/>
                </StackLayout>

                <!--Center_1在水平選項中間位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Center">
                    <Label Text="Center_1"/>
                </StackLayout>

                <!--End_1在水平選項中最右側位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="End">
                    <Label Text="End_1"/>
                </StackLayout>

                <!--Fill_1佔滿了整個水平選項-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Fill">
                    <Label Text="Fill_1"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--Start_A在水平選項最左側位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Start">
                    <Label Text="Start_A"/>
                </StackLayout>

                <!--Center_A依次排列-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Center">
                    <Label Text="Center_A"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--Start_2在水平選項最左側位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Start">
                    <Label Text="Start_2"/>
                </StackLayout>

                <!--EndAndExpand_2填充剩餘區域後靠最右側顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="EndAndExpand">
                    <Label Text="EndAndExpand_2"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--Start_3在水平選項最左側位置-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="Start">
                    <Label Text="Start_3"/>
                </StackLayout>

                <!--CenterAndExpand_3填充剩餘區域後再居中顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="CenterAndExpand">
                    <Label Text="CenterAndExpand_3"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--StartAndExpand_4填充剩餘區域後,在最左側顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="StartAndExpand">
                    <Label Text="StartAndExpand_4"/>
                </StackLayout>

                <!--CenterAndExpand_4填充剩餘區域後,再居中顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="CenterAndExpand">
                    <Label Text="CenterAndExpand_4"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--CenterAndExpand_5_1填充剩餘區域後,再居中顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="CenterAndExpand">
                    <Label Text="CenterAndExpand_5_1"/>
                </StackLayout>

                <!--CenterAndExpand_5_2填充剩餘區域後,再居中顯示-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="CenterAndExpand">
                    <Label Text="CenterAndExpand_5_2"/>
                </StackLayout>
            </StackLayout>

            <StackLayout BackgroundColor="#f9d33c" Orientation="Horizontal">
                <!--FillAndExpand_6填充整個剩餘部分-->
                <StackLayout BackgroundColor="#91e2f4" HorizontalOptions="FillAndExpand">
                    <Label Text="FillAndExpand_6"/>
                </StackLayout>
            </StackLayout>
            
            <StackLayout BackgroundColor="#f9d33c" VerticalOptions="FillAndExpand">
                <!--VerticalOptions=CenterAndExpand垂直方向填充居中顯示-->
                <StackLayout BackgroundColor="#91e2f4" VerticalOptions="CenterAndExpand">
                    <Label Text="VerticalOptions=CenterAndExpand"/>
                </StackLayout>
                <!--VerticalOptions=EndAndExpand垂直方向填充靠下顯示-->
                <StackLayout BackgroundColor="#91e2f4" VerticalOptions="EndAndExpand">
                    <Label Text="VerticalOptions=EndAndExpand"/>
                </StackLayout>
            </StackLayout>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

  能夠看到:

    1. 在默認的佈局方向(默認爲垂直方向)中,加入 Start_1,Center_1,End_1,Fill_1。分別表現出 Start_1在水平選項最左側位置,Center_1在水平選項中間位置,End_1在水平選項中最右側位置,而Fill_1佔滿了整個水平選項。

    2. 在佈局方式爲水平方向的佈局中,加入 Start_A,Center_A。表現出 Start_A,Center_A 依次從左到右排列。

    3. 在佈局方式爲水平方向的佈局中,加入 Start_2,EndAndExpand_2。表現出,Start_2 在佈局最左側,而 EndAndExpand_2 將佈局剩餘部分填滿後靠最右側顯示。

    4. 在佈局方式爲水平方向的佈局中,加入 Start_3,CenterAndExpand_3。表現出,Start_3 在佈局最左側,而 CenterAndExpand_3 將佈局剩餘部分填滿後居中顯示顯示。

    5. 在佈局方式爲水平方向的佈局中,加入 StartAndExpand_4,CenterAndExpand_4。表現出,StartAndExpand_4 將佈局餘部分填滿後在佈局最左側顯示,而 CenterAndExpand_4 將佈局剩餘部分填滿後居中顯示。

    6. 在佈局方式爲水平方向的佈局中,加入 CenterAndExpand_5_1,CenterAndExpand_5_2。表現出,CenterAndExpand_5_1 和 CenterAndExpand_5_2 都將佈局剩餘部分填滿後居中顯示。

    7. 在佈局方式爲水平方向的佈局中,加入 FillAndExpand_6。表現出,FillAndExpand_6 都將佈局剩餘部分填滿後填充顯示(Fill後已經沒有剩餘部分了)。

    8. 在佈局方式爲垂直方向的佈局中,加入 VerticalOptions=CenterAndExpand 。表現出,VerticalOptions=CenterAndExpand垂直方向填充居中顯示。

    9. 在佈局方式爲垂直方向的佈局中,加入 VerticalOptions=EndAndExpand。表現出,VerticalOptions=EndAndExpand垂直方向填充靠下顯示。

 

  佈局控件之Grid

  Grid 中文翻譯又叫「網格佈局」,意指在Xamarin.Forms中使用XAML代碼或者是C#代碼,經過網格的方式來完成佈局。能夠理解爲 Excel 中 N行N列的方式來佈局。

 

  咱們能夠看到Grid佈局,是以行和列,以單元格的方式進行佈局。行和列的索引只從0開始,讓咱們先來演練一個簡單的 Grid :

 

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.Grid">
    <ContentPage.Content>
        <!--定義網格行間隙爲2,列間隙爲2-->
        <Grid RowSpacing="2" ColumnSpacing="2" BackgroundColor="#A8A8A8">
            
            <!--定義一個5行,4列的表格-->
            <Grid.RowDefinitions>
                <!--設置行高爲100-->
                <RowDefinition Height="100"></RowDefinition>
                <!--減去行高100後,按照1/10高度(此網格定義了10)計算-->
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="2*"></RowDefinition>
                <!--減去行高100後,按照3/10高度(此網格定義了10)計算-->
                <RowDefinition Height="3*"></RowDefinition>
                <!--減去行高100後,按照4/10高度(此網格定義了10)計算-->
                <RowDefinition Height="4*"></RowDefinition>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <!--按照1/5寬度(此網格定義了5)計算-->
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <!--按照2/5寬度(此網格定義了5)計算-->
                <ColumnDefinition Width="2*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>

            <!--設置元素在網格的第0行0列-->
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="0" Grid.Column="0">
                <Label Text="第0行0列"/>
            </StackLayout>
            <!--設置元素在網格的第0行1列,跨2列-->
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2">
                <Label Text="第0行1列,跨2列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="0" Grid.Column="3">
                <Label Text="第0行3列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="1" Grid.Column="0">
                <Label Text="第1行0列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3">
                <Label Text="第1行1列,跨3列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="2" Grid.Column="0">
                <Label Text="第2行0列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="2" Grid.Column="1">
                <Label Text="第2行1列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="2" Grid.Column="2">
                <Label Text="第2行2列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="2" Grid.Column="3">
                <Label Text="第2行3列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="3" Grid.Column="0">
                <Label Text="第3行0列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="3" Grid.Column="1">
                <Label Text="第3行1列"/>
            </StackLayout>
            <!--設置元素在網格的第3行2列,跨2行-->
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="3" Grid.Column="2" Grid.RowSpan="2">
                <Label Text="第3行2列,跨2行"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="3" Grid.Column="3">
                <Label Text="第3行3列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="4" Grid.Column="0">
                <Label Text="第4行0列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="4" Grid.Column="1">
                <Label Text="第4行1列"/>
            </StackLayout>
            <StackLayout BackgroundColor="#91e2f4" Grid.Row="4" Grid.Column="3">
                <Label Text="第4行3列"/>
            </StackLayout>
        </Grid>
    </ContentPage.Content>
</ContentPage>

C# 代碼:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CSharpGrid : ContentPage
    {
        public CSharpGrid ()
        {
            InitializeComponent ();

            //定義網格行間隙爲2,列間隙爲2
            var grid = new Xamarin.Forms.Grid()
            {
                RowSpacing = 2,
                ColumnSpacing = 2,
                BackgroundColor = Color.FromHex("#A8A8A8")
            };

            /*
             * 定義一個5行,4列的表格
             */

            //設置行高爲100
            grid.RowDefinitions.Add(new RowDefinition() { Height = 100 });
            //減去行高100後,按照1/10高度(此網格定義了10)計算
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
            //減去行高100後,按照2/10高度(此網格定義了10)計算
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) });
            //減去行高100後,按照3/10高度(此網格定義了10)計算
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(3, GridUnitType.Star) });
            //減去行高100後,按照4/10高度(此網格定義了10)計算
            grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(4, GridUnitType.Star) });

            //按照1/5寬度(此網格定義了5)計算
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
            //按照2/5寬度(此網格定義了5)計算
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2, GridUnitType.Star) });
            grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });

            //設置元素在網格的第0行0列
            var s_0_0 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_0_0.Children.Add(new Label() { Text = "第0行0列" });
            grid.Children.Add(s_0_0);
            Xamarin.Forms.Grid.SetRow(s_0_0, 0);
            Xamarin.Forms.Grid.SetColumn(s_0_0, 0);


            //設置元素在網格的第0行1列,跨2列
            var s_0_1 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_0_1.Children.Add(new Label() { Text = "第0行1列,跨2列" });
            grid.Children.Add(s_0_1);
            Xamarin.Forms.Grid.SetRow(s_0_1, 0);
            Xamarin.Forms.Grid.SetColumn(s_0_1, 1);
            Xamarin.Forms.Grid.SetColumnSpan(s_0_1, 2);

            var s_0_3 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_0_3.Children.Add(new Label() { Text = "第0行3列" });
            grid.Children.Add(s_0_3);
            Xamarin.Forms.Grid.SetRow(s_0_3, 0);
            Xamarin.Forms.Grid.SetColumn(s_0_3, 3);

            var s_1_0 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_1_0.Children.Add(new Label() { Text = "第1行0列" });
            grid.Children.Add(s_1_0);
            Xamarin.Forms.Grid.SetRow(s_1_0, 1);
            Xamarin.Forms.Grid.SetColumn(s_1_0, 0);

            var s_1_1 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_1_1.Children.Add(new Label() { Text = "第1行1列,跨3列" });
            grid.Children.Add(s_1_1);
            Xamarin.Forms.Grid.SetRow(s_1_1, 1);
            Xamarin.Forms.Grid.SetColumn(s_1_1, 1);
            Xamarin.Forms.Grid.SetColumnSpan(s_1_1, 3);

            var s_2_0 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_2_0.Children.Add(new Label() { Text = "第2行0列" });
            grid.Children.Add(s_2_0);
            Xamarin.Forms.Grid.SetRow(s_2_0, 2);
            Xamarin.Forms.Grid.SetColumn(s_2_0, 0);

            var s_2_1 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_2_1.Children.Add(new Label() { Text = "第2行1列" });
            grid.Children.Add(s_2_1);
            Xamarin.Forms.Grid.SetRow(s_2_1, 2);
            Xamarin.Forms.Grid.SetColumn(s_2_1, 1);

            var s_2_2 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_2_2.Children.Add(new Label() { Text = "第2行2列" });
            grid.Children.Add(s_2_2);
            Xamarin.Forms.Grid.SetRow(s_2_2, 2);
            Xamarin.Forms.Grid.SetColumn(s_2_2, 2);

            var s_2_3 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_2_3.Children.Add(new Label() { Text = "第2行2列" });
            grid.Children.Add(s_2_3);
            Xamarin.Forms.Grid.SetRow(s_2_3, 2);
            Xamarin.Forms.Grid.SetColumn(s_2_3, 3);

            var s_3_0 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_3_0.Children.Add(new Label() { Text = "第3行0列" });
            grid.Children.Add(s_3_0);
            Xamarin.Forms.Grid.SetRow(s_3_0, 3);
            Xamarin.Forms.Grid.SetColumn(s_3_0, 0);

            var s_3_1 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_3_1.Children.Add(new Label() { Text = "第3行1列" });
            grid.Children.Add(s_3_1);
            Xamarin.Forms.Grid.SetRow(s_3_1, 3);
            Xamarin.Forms.Grid.SetColumn(s_3_1, 1);

            //第3行2列,跨2行
            var s_3_2 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_3_2.Children.Add(new Label() { Text = "第3行2列,跨2行" });
            grid.Children.Add(s_3_2);
            Xamarin.Forms.Grid.SetRow(s_3_2, 3);
            Xamarin.Forms.Grid.SetColumn(s_3_2, 2);
            Xamarin.Forms.Grid.SetRowSpan(s_3_2, 2);

            var s_3_3 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_3_3.Children.Add(new Label() { Text = "第3行3列" });
            grid.Children.Add(s_3_3);
            Xamarin.Forms.Grid.SetRow(s_3_3, 3);
            Xamarin.Forms.Grid.SetColumn(s_3_3, 3);


            var s_4_0 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_4_0.Children.Add(new Label() { Text = "第4行0列" });
            grid.Children.Add(s_4_0);
            Xamarin.Forms.Grid.SetRow(s_4_0, 4);
            Xamarin.Forms.Grid.SetColumn(s_4_0, 0);

            var s_4_1 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_4_1.Children.Add(new Label() { Text = "第4行1列" });
            grid.Children.Add(s_4_1);
            Xamarin.Forms.Grid.SetRow(s_4_1, 4);
            Xamarin.Forms.Grid.SetColumn(s_4_1, 1);

            var s_4_3 = new StackLayout() { BackgroundColor = Color.FromHex("#91e2f4") };
            s_4_3.Children.Add(new Label() { Text = "第4行3列" });
            grid.Children.Add(s_4_3);
            Xamarin.Forms.Grid.SetRow(s_4_3, 4);
            Xamarin.Forms.Grid.SetColumn(s_4_3, 3);

            
            Content = grid;
        }
    }
}

 

能夠看到:

  1. RowSpacing 能設置網格 行間隙,ColumnSpacing 能設置網格 列間隙

  2. Grid 中定義行的方式爲 Grid.RowDefinitions,具體定義行爲 RowDefinition 。當設置 RowDefinition.Height 爲一個數字時,該行高度爲該數字,當設置 RowDefinition.Height 爲 N*時,該行高度爲 (總高度-指定數字高度) / 總星數 * N。 

  3. Grid 中定義列的方式爲 Grid.ColumnDefinitions,具體定義行爲 ColumnDefinition 。當設置 ColumnDefinition.WIdth 爲一個數字時,該行寬度爲該數字,當設置 ColumnDefinition.Width 爲 N*時,該行寬度爲 (總寬度-指定數字寬度) / 總星數 * N。 

  4. 咱們能夠經過設置 Height 或 Width 爲 * 時 ,將 Height 或 Width 均等分佈局。

  5. 在元素上指定 Grid.Row 或 Grid.Column 時,能將元素對應到網格的具體位置。

  6. 在元素上指定 Grid.ColumnSpan 或 Grid.RowSpan 時,能設置元素的是否跨行或跨列,跨列數。

 

  佈局控件之AbsoluteLayout

  AbsoluteLayout 中文翻譯又叫「絕對佈局」,意指在Xamarin.Forms中咱們經過 AbsoluteLayout 能在視圖上直接指定 元素的座標(X,Y)和高寬,並繪製成矩形的形狀進行佈局。

  

  AbsoluteLayout  並不複雜,它是直接經過在視圖上給定起始位置佈局。若是這句話不太容易理解,咱們立刻用代碼預覽效果來理解一下:

 

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.AbsoluteLayout">
    <ContentPage.Content>

        <AbsoluteLayout>

            <!--LayoutBounds X,Y,Width,Height 爲比例(最大1)-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="0,0,0.3,0.1" 
                         AbsoluteLayout.LayoutFlags="All">
                <Label Text="0,0,0.3,0.1,All"/>
            </StackLayout>

            <!--LayoutBounds X,Y,Width,Height 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="100,100,150,25" 
                         AbsoluteLayout.LayoutFlags="None">
                <Label Text="100,100,150,25,None"/>
            </StackLayout>

            <!--LayoutBounds Width 爲比例,X,Y,Height 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="100,130,0.7,30" 
                         AbsoluteLayout.LayoutFlags="WidthProportional">
                <Label Text="100,130,0.7,30,WidthProportional"/>
            </StackLayout>

            <!--LayoutBounds Height爲比例,X,Y,Width 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="20,180,260,0.05" 
                         AbsoluteLayout.LayoutFlags="HeightProportional">
                <Label Text="20,180,260,0.05,HeightProportional"/>
            </StackLayout>

            <!--LayoutBounds X 爲比例,Y,Width,Height 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="0.6,250,330,30" 
                         AbsoluteLayout.LayoutFlags="XProportional">
                <Label Text="0.6,250,330,30,XProportional"/>
            </StackLayout>

            <!--LayoutBounds Y 爲比例,X,Width,Height 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="0,0.45,260,30" 
                         AbsoluteLayout.LayoutFlags="YProportional">
                <Label Text="0,0.45,260,30,YProportional"/>
            </StackLayout>

            <!--LayoutBounds X,Y 爲比例,Width,Height 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="0.01,0.5,260,30" 
                         AbsoluteLayout.LayoutFlags="PositionProportional">
                <Label Text="0.01,0.5,260,30,PositionProportional"/>
            </StackLayout>

            <!--LayoutBounds Width,Height 爲比例,X,Y 爲絕對值-->
            <StackLayout BackgroundColor="#f9d33c" 
                         AbsoluteLayout.LayoutBounds="10,400,0.5,0.05" 
                         AbsoluteLayout.LayoutFlags="SizeProportional">
                <Label Text="10,400,0.5,0.05,SizeProportional"/>
            </StackLayout>

            <!--AbsoluteLayout能夠重疊,先Render的被後Render的元素覆蓋-->
            <StackLayout BackgroundColor="Red" 
                         AbsoluteLayout.LayoutBounds="10,450,0.5,0.05" 
                         AbsoluteLayout.LayoutFlags="SizeProportional">
                <Label Text="AbsoluteLayout能夠重疊"/>
            </StackLayout>
            <StackLayout BackgroundColor="Blue" 
                         AbsoluteLayout.LayoutBounds="10,460,0.5,0.05" 
                         AbsoluteLayout.LayoutFlags="SizeProportional">
                <Label Text="AbsoluteLayout能夠重疊"/>
            </StackLayout>

        </AbsoluteLayout>
        
    </ContentPage.Content>
</ContentPage>

 C# 代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CSharpAbsoluteLayout : ContentPage
    {
        public CSharpAbsoluteLayout ()
        {
            InitializeComponent ();

            var absoluteLayout = new Xamarin.Forms.AbsoluteLayout();

            //LayoutBounds X,Y,Width,Height 爲比例(最大1)
            var stackLayout_1 = new Xamarin.Forms.StackLayout();
            stackLayout_1.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_1.Children.Add(new Label() { Text = "0,0,0.3,0.1,All" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_1, new Rectangle(0, 0, 0.3, 0.1));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_1, AbsoluteLayoutFlags.All);
            absoluteLayout.Children.Add(stackLayout_1);

            //LayoutBounds X,Y,Width,Height 爲絕對值
            var stackLayout_2 = new Xamarin.Forms.StackLayout();
            stackLayout_2.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_2.Children.Add(new Label() { Text = "100,100,150,25,None" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_2, new Rectangle(100, 100, 150, 25));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_2, AbsoluteLayoutFlags.None);
            absoluteLayout.Children.Add(stackLayout_2);

            //LayoutBounds Width 爲比例,X,Y,Height 爲絕對值
            var stackLayout_3 = new Xamarin.Forms.StackLayout();
            stackLayout_3.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_3.Children.Add(new Label() { Text = "100,130,0.7,30,WidthProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_3, new Rectangle(100, 130, 0.7, 30));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_3, AbsoluteLayoutFlags.WidthProportional);
            absoluteLayout.Children.Add(stackLayout_3);

            //LayoutBounds Height爲比例,X,Y,Width 爲絕對值
            var stackLayout_4 = new Xamarin.Forms.StackLayout();
            stackLayout_4.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_4.Children.Add(new Label() { Text = "20,180,260,0.05,HeightProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_4, new Rectangle(20, 180, 260, 0.05));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_4, AbsoluteLayoutFlags.HeightProportional);
            absoluteLayout.Children.Add(stackLayout_4);

            //LayoutBounds X 爲比例,Y,Width,Height 爲絕對值
            var stackLayout_5 = new Xamarin.Forms.StackLayout();
            stackLayout_5.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_5.Children.Add(new Label() { Text = "0.6,250,330,30,XProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_5, new Rectangle(0.6, 250, 330, 30));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_5, AbsoluteLayoutFlags.XProportional);
            absoluteLayout.Children.Add(stackLayout_5);

            //LayoutBounds Y 爲比例,X,Width,Height 爲絕對值
            var stackLayout_6 = new Xamarin.Forms.StackLayout();
            stackLayout_6.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_6.Children.Add(new Label() { Text = "0,0.45,260,30,YProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_6, new Rectangle(0, 0.45, 260, 30));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_6, AbsoluteLayoutFlags.YProportional);
            absoluteLayout.Children.Add(stackLayout_6);

            //LayoutBounds X,Y 爲比例,Width,Height 爲絕對值
            var stackLayout_7 = new Xamarin.Forms.StackLayout();
            stackLayout_7.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_7.Children.Add(new Label() { Text = "0.01,0.5,260,30,PositionProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_7, new Rectangle(0.01, 0.5, 260, 30));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_7, AbsoluteLayoutFlags.PositionProportional);
            absoluteLayout.Children.Add(stackLayout_7);

            //LayoutBounds Width,Height 爲比例,X,Y 爲絕對值
            var stackLayout_8 = new Xamarin.Forms.StackLayout();
            stackLayout_8.BackgroundColor = Color.FromHex("#f9d33c");
            stackLayout_8.Children.Add(new Label() { Text = "10,400,0.5,0.05,SizeProportional" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_8, new Rectangle(10, 400, 0.5, 0.05));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_8, AbsoluteLayoutFlags.SizeProportional);
            absoluteLayout.Children.Add(stackLayout_8);

            //AbsoluteLayout能夠重疊,先Render的被後Render的元素覆蓋
            var stackLayout_9 = new Xamarin.Forms.StackLayout();
            stackLayout_9.BackgroundColor = Color.Red;
            stackLayout_9.Children.Add(new Label() { Text = "AbsoluteLayout能夠重疊" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_9, new Rectangle(10, 450, 0.5, 0.05));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_9, AbsoluteLayoutFlags.SizeProportional);
            absoluteLayout.Children.Add(stackLayout_9);

            var stackLayout_10 = new Xamarin.Forms.StackLayout();
            stackLayout_10.BackgroundColor = Color.Blue;
            stackLayout_10.Children.Add(new Label() { Text = "AbsoluteLayout能夠重疊" });
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(stackLayout_10, new Rectangle(10, 460, 0.5, 0.05));
            Xamarin.Forms.AbsoluteLayout.SetLayoutFlags(stackLayout_10, AbsoluteLayoutFlags.SizeProportional);
            absoluteLayout.Children.Add(stackLayout_10);

            Content = absoluteLayout;

        }
    }
}

 

  絕對佈局有兩個關鍵屬性,分別是 AbsoluteLayout.LayoutBounds 和 AbsoluteLayout.LayoutFlags 。

  AbsoluteLayout.LayoutBounds 返回的類型爲 Xamarin.Forms.Rectangle ,那 Rectangle 是什麼呢?翻譯過來就是 「矩形」,意思是,咱們要佈局一個什麼樣的矩形。F12轉到代碼定義上看 Rectangle 4個重要的屬性。

 

  Rectangle 4個重要的屬性:

    X:繪製矩形的起始位置X座標。(屏幕最左上角爲 X = 0 , Y = 0)

    Y:繪製矩形的起始位置Y座標。

    Width:須要繪製的矩形的寬度。

    Height:須要繪製的矩形的高度。

 

  來看看代碼上 AbsoluteLayout.LayoutBounds="10,450,0.5,0.05"  是什麼意思呢? 10爲X的值,450爲Y的值,0.5爲Width的值,0.05爲Height的值。構造函數爲:

public Rectangle(double x, double y, double width, double height);

 

  AbsoluteLayout.LayoutFlags 定義了 AbsoluteLayout.LayoutBounds 如何來解析,解析的方式分爲 比例解析(比例最大爲1)絕對值解析。 

  AbsoluteLayout.LayoutFlags 是一個枚舉,枚舉的值分別是:

    All:X,Y,Width,Height 都經過比例進行解析。

    None:X,Y,Width,Height 都經過絕對值進行解析。

    WidthProportional:Width 經過比例進行解析;X,Y,Height 經過絕對值解析。

    HeightProportional:Height 經過比例進行解析;X,Y,Width 經過絕對值解析。

    XProportional:X 經過比例進行解析;Y,Width,Height 經過絕對值解析。

    YProportional:Y 經過比例進行解析;X,Width,Height 經過絕對值解析。

    PositionProportional:X,Y 經過比例進行解析;Width,Height 經過絕對值解析。

    SizeProportionalWidth,Height 經過比例進行解析;X,Y 經過絕對值解析。

  AbsoluteLayout能夠重疊,先Render的被後Render的元素覆蓋,咱們能夠經過Blue元素,覆蓋Red元素觀察到。

 

  佈局控件之ScrollView

   ScrollView 中文翻譯又叫「滾動視圖」,意指在Xamarin.Forms中咱們經過 ScrollView 能建立滾動到屏幕外的視圖,很差理解不要緊,往下看就對了。

  咱們能夠從圖上看到 ScrollView 顏色範圍超出了屏幕,相似於咱們用App某個頁面,一屏顯示不完,須要上下滑動或左右滑動觀看。

  咱們先來演練一個簡單的 ScrollView :

 

XAML 代碼:

 

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.ScrollView">
    <ContentPage.Content>

        <ScrollView x:Name="scrollView" Orientation="Vertical" VerticalScrollBarVisibility="Never">
            <StackLayout>
                <StackLayout BackgroundColor="Red" HeightRequest="500"></StackLayout>
                <StackLayout BackgroundColor="Yellow" HeightRequest="500"></StackLayout>
                <StackLayout BackgroundColor="Blue" HeightRequest="500"></StackLayout>
                <StackLayout BackgroundColor="Green" HeightRequest="500">
                    <Button x:Name="button" Text="回到頂部(X,Y)" Clicked="Button_Clicked" VerticalOptions="EndAndExpand"/>
                </StackLayout>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>

 

C# 代碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Layout
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ScrollView : ContentPage
    {
        public ScrollView ()
        {
            InitializeComponent ();

            scrollView.Scrolled += (object sender, ScrolledEventArgs e) =>
            {
                button.Text = string.Format("回到頂部({0},{1})", e.ScrollX, e.ScrollY);
            };

        }

        private void Button_Clicked(object sender, EventArgs e)
        {
            scrollView.ScrollToAsync(0, 0, true);
        }
    }
}

 

  從代碼運行起來後能夠看到,咱們定義了一個 ScrollView 在 ScrollView 中加入了 Red,Yellow,Blue,Green的總高度超出屏幕外的佈局。經過手勢往下拖動,咱們能夠看到 「回到頂部」 按鈕的Text文本在不斷的跟隨當前滑動的位置變化。當咱們點擊 「回到頂部」 按鈕,滾動視圖又回到了頂部位置。。

  接下來,咱們來詳細瞭解一下 ScrollView 的使用方式。

 

屬性

ScrollY:獲取當前 ScrollView 滾動位置的座標 Y 值。

ScrollX:獲取當前 ScrollView 滾動位置的座標 X 值。

Orientation:設置 ScrollView 滾動的方向。Orientation 的類型爲枚舉 Xamarin.Forms.ScrollOrientation;值 Vertical 表示只以垂直方式滾動,不容許以水平方式滾動。值 Horizontal 表示只以水平方式滾動,不容許以垂直方式滾動。值 Both 表示能夠經過垂直和水平方式滾動。

VerticalScrollBarVisibility:設置 ScrollView 在垂直方向的滾動條是否可見。VerticalScrollBarVisibility 的類型爲枚舉 Xamarin.Forms.ScrollBarVisibility;值 Default 表示垂直滾動條是否顯示,須要根據平臺自己默認的設置而定;值 Always 表示垂直滾動條老是顯示。值 Never 表示垂直滾動條老是不顯示。

HorizontalScrollBarVisibility:設置 ScrollView 在水平方向的滾動條是否可見。HorizontalScrollBarVisibility 的類型一樣也是 Xamarin.Forms.ScrollBarVisibility。

 

方法

ScrollToAsync:將 ScrollView 直接定位到一個(x,y)的位置或定位到一個元素的位置。 

ScrollToAsync(Element element, ScrollToPosition position, bool animated);
ScrollToAsync(double x, double y, bool animated);

 

事件

Scrolled:滾動完成後引起的事件。該事件會傳入一個類型爲 Xamarin.Forms.ScrolledEventArgs 的參數。經過該參數咱們能夠獲得 當前滾動正處於的 X,Y位置。

scrollView.Scrolled += (object sender, ScrolledEventArgs e) =>
{
        button.Text = string.Format("回到頂部({0},{1})", e.ScrollX, e.ScrollY);
};

 

小節:我的認爲 ScrollView 在真實項目中會常常用到,好比 ScrollView  能實現 輪播圖,實現產品預覽圖等。

 

  佈局控件之RelativeLayout

  RelativeLayout 中文翻譯又叫「相對佈局」,意指在Xamarin.Forms中咱們經過界面中的某個元素爲基準,設置另一個元素的位置和大小。經過這種佈局方式能夠實現動態佈局,使得設計的界面能夠在不一樣分辨率的屏幕中有更好的顯示效果。

 

 

 從圖上能夠看到,RelativeLayout 是以頁面中某個元素爲基準,來設置另一個元素。由於 RelativeLayout 用的比較少,因此下面只簡單瞭解一下。

 

 

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.RelativeLayout">
    <ContentPage.Content>
        <StackLayout>

            <RelativeLayout>
                
                <BoxView Color="Red" x:Name="redBox"
        RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
            Property=Height,Factor=.15,Constant=0}"
        RelativeLayout.WidthConstraint="{ConstraintExpression
            Type=RelativeToParent,Property=Width,Factor=1,Constant=0}"
        RelativeLayout.HeightConstraint="{ConstraintExpression
            Type=RelativeToParent,Property=Height,Factor=.8,Constant=0}" />
                
                <BoxView Color="Blue"
        RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView,
            ElementName=redBox,Property=Y,Factor=1,Constant=20}"
        RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView,
            ElementName=redBox,Property=X,Factor=1,Constant=20}"
        RelativeLayout.WidthConstraint="{ConstraintExpression
            Type=RelativeToParent,Property=Width,Factor=.5,Constant=0}"
        RelativeLayout.HeightConstraint="{ConstraintExpression
            Type=RelativeToParent,Property=Height,Factor=.5,Constant=0}" />
                
            </RelativeLayout>

        </StackLayout>
    </ContentPage.Content>
</ContentPage>

 

  佈局控件之FlexLayout

  FlexLayout 中文翻譯又叫「彈性佈局」,FlexLayout 佈局 是Xamarin.Forms 版本 3.0 中新增功能,基於 CSS靈活佈局思想。由於它包括許多靈活的選項來排列子級在佈局,所以稱爲 Flex 佈局或 彈性佈局。

FlexLayout 很是靈活,讓咱們直接運行一個示例來講明:

XAML 代碼:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Layout.FlexLayout">
    <ContentPage.Content>

        <FlexLayout Direction="Column" JustifyContent="Start" AlignItems="Start" >

            <StackLayout FlexLayout.Grow="1" BackgroundColor="Red" FlexLayout.Order="1"/>
            <StackLayout FlexLayout.Grow="2" BackgroundColor="Green" FlexLayout.Order="2"/>
            <StackLayout FlexLayout.Grow="3" BackgroundColor="Blue" FlexLayout.Order="3"/>

            <Label BackgroundColor="Blue" FlexLayout.AlignSelf="Stretch" FlexLayout.Order="4">底部狀態欄</Label>

            <Label BackgroundColor="Green" FlexLayout.Basis="150" Text="歡迎使用Xamarin Forms"/>
            <Label FlexLayout.Basis="150" Text="歡迎來到hexu6788"/>
            <Button Text="點擊按鈕" FlexLayout.AlignSelf="Center" />
        </FlexLayout>
        
    </ContentPage.Content>
</ContentPage>

FlexLayout 佈局中包含了如下重要的概念。

屬性

Direction:指定 FlexLayout 佈局的方向。類型爲 Xamarin.Forms.FlexDirection,枚舉 FlexDirection 包含4個值;

  Row 指示子元素將以區域設置的默認行佈局方向分佈;

  RowReverse 指示子元素將以區域設置默認行佈局方向的反方向分佈;

  Column 指示子元素將以區域設置的默認列布局方向分佈;

  ColumnReverse 指示子元素將以區域設置默認列布局方向的反方向分佈;

AlignItems:指定 FlexLayout 佈局每一項的對齊方式。類型爲 Xamarin.Forms.FlexAlignItems,枚舉 FlexAlignItems 包含4個值;

  Start 指示子元素將向父級的首端對齊;

  Center 指示子元素將在父級內居中顯示;

  End 指示子元素將向父級的末端對齊;

  Stretch 指示子元素將從父級的首端拉伸至末端;

JustifyContent:指定 FlexLayout 佈局軸的對齊方式。跟 AlignItems 類似,AlignItems 指橫軸,而 JustifyContent 指縱軸。JustifyContent 的 類型爲 Xamarin.Forms.FlexJustify,枚舉 FlexJustify 包含6個值;

  Start 指示子元素將向該行首端對齊;

  Center 指示子元素將彙集到父級中心;

  End 指示子元素將向該行末端對齊;

  SpaceBetween 指示子元素之間的間距相等,行的兩端沒有空格,以此形式在行中填充元素和空間;

  SpaceEvenly 指示子元素之間的間隔和首尾兩個子元素與其最接近的父級邊緣之間的間距相同;

  SpaceAround指示子元素在開頭和結尾處將以一個空格單位隔開,而且各元素之間間隔兩個單位,以此形式在行中填充元素和空間;

FlexLayout.AlignSelf:經過設置子元素的 FlexLayout.AlignSelf 屬性,能夠重寫父元素的 AlignItems 設置。FlexLayout.AlignSelf 有5種選項;

  Start 指示該元素將向父級的首端對齊;

  Center 指示該元素將在父級內居中顯示;

  End 指示該元素將向父級的末端對齊;

  Stretch 指示該元素將從父級的首端拉伸至末端;

  Auto 指示該元素會採用供其父級使用的 FlexAlignItems 值提供的對齊方式;

FlexLayout.Order:此屬性是一個整數,其默認值爲 0。 此屬性可用於更改在佈局順序。

FlexLayout.Grow此屬性的類型是 float 和默認值爲 0。若是該軸還有剩餘空間時,會將設置爲正值的元素進行剩餘空間分配。分配空間的比例則按照設置Grow的比例來,相似於 Grid 中的星型規範按比例分配空間。

FlexLayout.Base:此屬性的類型是 float 型。 此屬性定義一個絕對基本長度的值,FlexLayout.Base 支持百分比,寫法如 Base = "80%",在 FlexLayout 自動 Render 的時候不受影響,好比 FlexLayout 方向爲 Column 時 Base = 150 定義了一個高度爲150的元素。

  佈局壓縮LayoutCompression

  再擴展一個概念,LayoutCompression(佈局壓縮)。佈局壓縮功能從可視化樹中刪除指定的佈局,以試圖提高頁面呈現性能。

  爲何須要佈局壓縮呢?由於在咱們寫 Xamarin.Forms 代碼的時候,也許佈局有不少重複的地方,也許還會有不少簡寫可是不影響功能的寫法。所以,微乳提出了性能優化方式,佈局壓縮。

<StackLayout>
  <StackLayout ...>
    
<Button ... />     <Image ... />     <Image ... />     <BoxView ... />     <Label ... /> </StackLayout>
  <Label ... /> </StackLayout>

經過 Xamarin Inspector 工具, 在 Android 上,嵌套的視圖層次結構包含 17 層視圖:

 

  在 XAML 中,能夠在元素上設置 CompressedLayout.IsHeadless 屬性設置爲 true 來啓用佈局壓縮 ,也能夠經過 C# 代碼來設置 佈局壓縮:

<StackLayout CompressedLayout.IsHeadless="true">
  ...
</StackLayout> 
CompressedLayout.SetIsHeadless(元素, true);

  經過壓縮之後,嵌套的視圖層次結構變成 14 層視圖。與原始的嵌套的視圖17 層相比有 17%的減小。 雖然減小很少,但這個性能對整個頁面的性能影響也很大。設置過屬性的元素不適合佈局壓縮,由於某些元素設置了 背景色,或者手勢事件等。壓縮了後這個節點就沒有了,會影響軟件功能。

  結束語

實際上 Xamarin.Forms 還有其餘的佈局控件,由於文章已經很長了,全部就準備放到後面再寫了。我的博客已經幾年沒寫了,如今有點閒因此又繼續寫博客。

本次寫這篇文章,我本身學到了不少東西,但願 Xamarin 在中國有更多的人用起來,感謝博客園提供平臺,感謝各位大神提供支持。

以上全部示例代碼都在 https://github.com/hexu6788/XamarinForms-Samples/tree/master/Code/XamarinLayout/Layout/Layout

 

 

 

參考資料:

[1] Xamarin官方英文文檔  來源:https://docs.microsoft.com/en-us/xamarin/

 

若是你以爲本篇文章對您有幫助的話,感謝您的【推薦】。

若是你對 .NET 或 Xamarin 有興趣的話能夠關注我,我會按期的在博客分享個人學習心得。

本文地址:http://www.cnblogs.com/hexu6788/p/9916038.html

做者博客:何旭

歡迎轉載,請在明顯位置給出出處及連接

相關文章
相關標籤/搜索