MAUI新生6.2-布局类控件难点:FlexLayout、BindableLayout、StateContainer

一、FlexLayout弹性布局

1、FlexLayout弹性布局,和前端的Flex弹性布局,几乎一样。FlexLayout是容器,可以定义Direction/主轴方向、Wrap/子元素在主轴方向上是否换行/列、JustityContent/AlignItems/AlignContent子元素整体对齐方式。同时,在子元素上可以通过附加属性,定义子元素的个体行为,如Order,定义子元素排列顺序;Basis/Grow/Shrink,定义子元素主轴方向的尺寸形为;AlighSeft,定义子元素在交叉轴方向的对齐行为。

 

 2、使用FlexLayout布局时的经验

  • 确定子元素排列的主轴方向Direction,Row-由左至右水平排列(默认值),Column-由上至下垂直排列,或者RowReverse-由右至左水平排列、ColumnReverse-由下至上垂直排列
  • 确定子元素在主轴方向上是否换行Wrap,NoWrap-不换行(默认值)、Wrap-换行、Reverse-反方向换行
  • 确定子元素整体在主轴和交叉轴上的对齐方式,JustifyContent-主轴方向上的对齐方式、AlignItems-NoWap时交叉轴方向上的对齐方式、AlignContent-Wap时交叉轴方向上的对齐方式
  • 确定子元素个体在主轴和交叉轴上的排列顺序、缩放和对齐行为,Order-排列顺序、Basis/Grow/Shrink-NoWap时主轴方向上的尺寸和缩放、AlignSeft-NoWap时交叉轴方向上的对齐
  • 如下图所示:

 

3、使用FlexLayout完成圣杯布局 

<ContentPage
    x:Class="MauiApp12.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    BackgroundColor="{DynamicResource PageBackgroundColor}">

    <!--  外层FlexLayout,主轴为Column,自上而下垂直排列,分为三行,不换行  -->
    <!--  JustifyContent主轴-垂直方向的对齐方式为Start,AlignItems交叉轴-水平方向对齐方式为Stretch/自动扩展  -->
    <FlexLayout
        AlignItems="Stretch"
        Direction="Column"
        JustifyContent="Start"
        Wrap="NoWrap">
        <Label
            BackgroundColor="Red"
            HorizontalTextAlignment="Center"
            Text="Header" />
        <!--内层FlexLayout,作为外层FlexLayout的子元素,附加属性FlexLayout.Grow为1,在交叉轴-水平方向上填满剩余空间-->
        <!--内层FlexLayout,主轴方向为Row,自左向右水平排列,不换行-->
        <FlexLayout
            Direction="Row"
            FlexLayout.Grow="1"
            Wrap="NoWrap">
            <!--内层FlexLayout的子元素,BoxView设置附加属性FlexLayout.Basis,主轴方向的基础尺寸为50-->
            <BoxView FlexLayout.Basis="50" Color="Yellow" />
            <!--内层FlexLayout的子元素,Lable设置附加属性FlexLayout.Grow,主轴方向上扩展填满剩余空间-->
            <Label
                BackgroundColor="Green"
                FlexLayout.Grow="1"
                Text="Content" />
            <BoxView FlexLayout.Basis="50" Color="Yellow" />
        </FlexLayout>
        <Label
            BackgroundColor="Gray"
            HorizontalTextAlignment="Center"
            Text="Footer" />
    </FlexLayout>
</ContentPage>

 

  

 

 

二、绑定布局BindableLayout,以附加属性的形式,在宿主布局容器内,实现一个集合展示。实现的功能,与ListView或CollectionView类似,在条目数较少、无滚动、无选择按钮情况时,可以使用BindableLayout。

1、定义一个ViewModel,作为数据源 

//直接New一个Employee集合
//ImageSource为Resources/Images目录下的图像
public partial class MainPageViewModel: ObservableObject
{
    [ObservableProperty]
    private List<Employee> employees = new List<Employee>
    {
        new Employee{Name = "HeLiu",ImageSource="he_liu.png"},
        new Employee{Name = "HaiShang",ImageSource="hai_shang.png"},
        new Employee{Name = "LuoRi",ImageSource="luo_ri.png"},
        new Employee{Name = "GongYuan",ImageSource="gong_yuan.png"},
    };
}

  

2、使用BindableLayout 

<ContentPage
    x:Class="MauiApp12.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:vm="clr-namespace:MauiApp12.ViewModels">

    <!--直接创建ViewModel对象,并设置为页面的BindingContext-->
    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>
    
    <!--BindableLayout.ItemsSource,数据源-->
    <!--BindableLayout.ItemTemplate,数据模板-->
    <!--BindableLayout.EmptyView,无数据时显示的文字提示-->
    <!--BindableLayout.EmptyView,还支持定义复杂的外观-->
    <!--BindableLayout.ItemTemplateSelector,相当于迭代中的if,详见数据模板的DataTemplateSelector-->
    <StackLayout
        BindableLayout.EmptyView="无数据"
        BindableLayout.ItemsSource="{Binding Employees}"
        Orientation="Horizontal">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <Image
                    Aspect="AspectFill"
                    HeightRequest="44"
                    Source="{Binding ImageSource}"
                    WidthRequest="44" />
            </DataTemplate>
        </BindableLayout.ItemTemplate>
        <!--<BindableLayout.EmptyView>
            <Label Text="数据为空时显示的外观"/>
        </BindableLayout.EmptyView>-->
    </StackLayout>
</ContentPage>

 

 

  

 

三、状态容器StateContainer,以附加属性的形式,在宿主布局容器内,根据不同的状态条件,显示不同的外观。

1、安装Nuget包,Community.Toolkit.Maui,并在入口文件MauiProgram.cs文件中设置【builder.UseMauiApp<App>().UseMauiCommunityToolkit()】

2、定义一个ViewModel,作为数据源

public partial class MainPageViewModel: ObservableObject
{
    [ObservableProperty]
    private string myCurrentState;

    [RelayCommand]
    private void ChangeMyCurrentStateLoading()
    {
        MyCurrentState = "Loading";
    }

    [RelayCommand]
    private void ChangeMyCurrentStateSuccess()
    {
        MyCurrentState = "Success";
    }

    [RelayCommand]
    private void ChangeMyCurrentStateEmpty()
    {
        MyCurrentState = "";
    }
}

 

3、使用StateContainer

<ContentPage
    ......
    xmlns:tk="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
    xmlns:vm="clr-namespace:MauiApp12.ViewModels">

    <!--  直接创建ViewModel对象,并设置为页面的BindingContext  -->
    <ContentPage.BindingContext>
        <vm:MainPageViewModel />
    </ContentPage.BindingContext>

    <VerticalStackLayout>
        <!--tk:StateContainer.CurrentState的值和tk:StateView.StateKey匹配-->
        <VerticalStackLayout tk:StateContainer.CurrentState="{Binding MyCurrentState}">
            <tk:StateContainer.StateViews>
                <!--tk:StateContainer.CurrentState的值为Loading时,显示如下内容-->
                <VerticalStackLayout tk:StateView.StateKey="Loading">
                    <ActivityIndicator IsRunning="True" />
                    <Label Text="加载中..." />
                </VerticalStackLayout>
                <!--tk:StateContainer.CurrentState的值为Success时,显示如下内容-->
                <Label tk:StateView.StateKey="Success" Text="Success!" />
            </tk:StateContainer.StateViews>
            <!--tk:StateContainer.CurrentState的值为Null或空字符串时默认显示的内容-->
            <Label Text="默认内容" />
        </VerticalStackLayout>

<!--按钮更改MyCurrentState值--> <Button Command="{Binding ChangeMyCurrentStateLoadingCommand}" Text="Loading" /> <Button Command="{Binding ChangeMyCurrentStateSuccessCommand}" Text="Success" /> <Button Command="{Binding ChangeMyCurrentStateEmptyCommand}" Text="Empty" /> </VerticalStackLayout> </ContentPage>

 

posted @ 2022-12-24 21:31  functionMC  阅读(1037)  评论(0编辑  收藏  举报