You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Maui如何根据显示区域动态调整页面布局?

问题

我需要实现一个页面,包含三个区域(每个区域是由Label和内嵌CollectionView的Frame组成的VerticalStackLayout),底部固定两个Button。每个区域会根据绑定的条件决定是否显示,要求所有可见区域(1个、任意2个或3个)自动填充上方的可用视图空间。

当前使用的XAML结构如下:

<Grid
    ColumnDefinitions="*,*"
    RowDefinitions="*,60">
    <VerticalStackLayout Grid.Row="0" Grid.ColumSpan="2">
        <VerticalStackLayout IsVisible="{Binding ConditionA}">
            <Label Text="States" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout IsVisible="{Binding ConditionB}">
            <Label Test="Topics" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout IsVisible="{Binding ConditionC}">
            <Label Text="Activities" />
            <Frame HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
    </VerticalStackLayout>
    <Button Grid.Row="1" Grid.Column="0" />
    <Button Grid.Row="1" Grid.Column="1" />
</Grid>

现在遇到的问题是:如果不给Frame设置HeightRequest,CollectionView会自动扩展至超出页面底部;但通过代码手动管理HeightRequest的方式不够优雅,希望能通过XAML元素实现自动根据可用空间分配布局,达到以下理想效果:

  • 三个区域都可见时,均分上方可用空间
  • 两个区域可见时,各占上方可用空间的一半
  • 单个区域可见时,占满上方全部可用空间
最终实现代码

XAML部分

<Grid
    ColumnDefinitions="*,*">
    <Grid.RowDefinitions>
        <RowDefinition x:Name="MainArea" Height="*" />
        <RowDefinition x:Name="ButtonArea" Height="60" />
    </Grid.RowDefinitions>
    <VerticalStackLayout Grid.Row="0" Grid.ColumSpan="2">
        <VerticalStackLayout x:Name="StatesFilter" IsVisible="{Binding ConditionA}">
            <Label Text="List A" />
            <Frame x:Name="StatesFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout x:Name="TopicsFilter" IsVisible="{Binding ConditionB}">
            <Label Test="List B" />
            <Frame x:Name="TopicsFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
        <VerticalStackLayout x:Name="ActivitiesFilter" IsVisible="{Binding ConditionC}">
            <Label Text="List C" />
            <Frame x:Name="ActivitiesFrame" HeightRequest="150">
                <CollectionView />
            </Frame>
        </VerticalStackLayout>
    </VerticalStackLayout>
    <Button Grid.Row="1" Grid.Column="0" />
    <Button Grid.Row="1" Grid.Column="1" />
</Grid>

代码后置部分

protected override void OnSizeAllocated(double width, double height)
{
    base.OnSizeAllocated(width, height);

    // 此方法会调用两次,第一次参数为-1,-1,第二次返回实际宽高
    if (Height > 0)
    {
        AdjustRegionHeight(height);
    }
}

private void AdjustRegionHeight(double pageHeight)
{
    double frameHeight;
    double bottomSpace = 44; 

    int cnt = 0;
    cnt += (StatesFilter.IsVisible) ? 1 : 0;
    cnt += (TopicsFilter.IsVisible) ? 1 : 0;
    cnt += (ActivitiesFilter.IsVisible) ? 1 : 0;

    double fullHeight = pageHeight - ButtonArea.Height.Value;
    frameHeight = (fullHeight / cnt) - bottomSpace;

    StatesFrame.HeightRequest = (StatesFilter.IsVisible) ? frameHeight : 0;
    TopicsFrame.HeightRequest = (TopicsFilter.IsVisible) ? frameHeight : 0;
    ActivitiesFrame.HeightRequest = (ActivitiesFilter.IsVisible) ? frameHeight : 0;
}

内容的提问来源于stack exchange,提问作者AdvApp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:05:44