.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
相关产品推荐
相关产品推荐

