如何在不设置HeightRequest的情况下消除Xamarin.Forms双ListView间空白?
解决Xamarin.Forms中两个ListView之间的空白问题
嘿,我完全懂你的困扰——单个订单的ListView和商品明细ListView之间莫名出现了大片空白,还不想用硬编码的HeightRequest怕在不同设备上变形。其实这问题的核心很简单:你用ListView来展示单条数据了,ListView本来是给列表批量数据设计的,哪怕只有一项,它的内部布局逻辑也会预留出滚动区域的额外空间(比如默认的内边距、空行占位),这就是空白的源头。
下面给你两个解决思路,优先推荐第一个:
方案1:把单个订单的ListView换成静态布局(最靠谱)
既然SingleOrderList只展示一条订单信息,完全没必要用ListView!直接把原来ViewCell里的内容抽出来,用Frame+StackLayout就能完美展示,既消除了ListView带来的额外空间,还能简化布局代码:
修改后的完整布局代码:
<ContentPage.Content> <StackLayout BackgroundColor="Transparent" Spacing="0" Opacity="1" HorizontalOptions="FillAndExpand" Margin="4,0,4,0" VerticalOptions="StartAndExpand"> <Label Text="Main Order" TextColor="White" HeightRequest="30" HorizontalOptions="Center" VerticalOptions="Center" FontSize="Title" FontAttributes="Bold" /> <!-- 直接用Frame展示单个订单,替代原来的ListView --> <Frame x:Name="OrderFrame" CornerRadius="20" BackgroundColor="White" Margin="4,0,4,0" Padding="27"> <StackLayout BackgroundColor="Transparent" Orientation="Vertical" Spacing="0"> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="ID:" FontAttributes="Bold" FontSize="Large" /> <Span Text="{ Binding id }" FontAttributes="Bold" FontSize="Large" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Mail:" /> <Span Text="{ Binding billing.email }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Date:" /> <Span Text="{ Binding date_created }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Status:" /> <Span Text="{ Binding status }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="{ Binding total, StringFormat='Total R:{0,5:#,0.00}' }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> </StackLayout> </Frame> <Label Text="ITEMS" TextColor="White" HeightRequest="30" HorizontalOptions="Center" VerticalOptions="Center" FontSize="Title" FontAttributes="Bold" /> <ListView BackgroundColor="Transparent" x:Name="Lineorders" HasUnevenRows="True" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" SeparatorVisibility="Default"> <!-- 商品明细ListView代码保持不变 --> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ViewCell.View> <Frame CornerRadius="20" BackgroundColor="White" Margin="10" Padding="20"> <StackLayout Spacing="0" BackgroundColor="Transparent" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Product:" FontAttributes="Bold" FontSize="Large" /> <Span Text="{ Binding name }" FontAttributes="Bold" FontSize="Large" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Price:" /> <Span Text="{ Binding price,StringFormat={}{0:0.####################}}" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Sku:" /> <Span Text="{ Binding sku }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="{ Binding total , StringFormat='Total R:{0,5:#,0.00}' }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> <Label HorizontalTextAlignment="Center" TextColor="Black"> <Label.FormattedText> <FormattedString> <Span Text="Quantity:" /> <Span Text="{ Binding quantity }" FontAttributes="Bold" FontSize="Medium" /> </FormattedString> </Label.FormattedText> </Label> </StackLayout> </Frame> </ViewCell.View> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage.Content>
然后在后台代码里,把原来绑定给SingleOrderList的单个订单对象,直接赋值给OrderFrame的BindingContext就行:
// 假设yourSingleOrder是你的订单数据对象 OrderFrame.BindingContext = yourSingleOrder;
方案2:如果必须保留ListView(不推荐)
要是你因为某些业务需求必须用ListView展示单条数据,可以试试这些设置让它贴合内容:
- 确保
SingleOrderList的VerticalOptions="Start"(你已经设置了) - 添加
CachingStrategy="RecycleElement"优化布局渲染 - 在后台代码里动态计算内容高度(不用硬编码):
// 在订单数据绑定完成后执行 SingleOrderList.PropertyChanged += (sender, e) => { if (e.PropertyName == nameof(ListView.ItemsSource) && SingleOrderList.ItemsSource != null) { // 等布局渲染完成后再计算高度 Device.BeginInvokeOnMainThread(async () => { await Task.Delay(100); // 给UI渲染留一点时间 var totalHeight = SingleOrderList.TotalRowHeight; // 加上内边距和外边距的垂直高度 SingleOrderList.HeightRequest = totalHeight + SingleOrderList.Padding.VerticalThickness + SingleOrderList.Margin.VerticalThickness; }); } };
不过这个方法有点依赖UI渲染时机,在不同设备上可能会有小问题,还是方案1更稳妥。
为什么会出现这个空白呢?简单说就是ListView的“本职工作”是展示列表,哪怕只有一项,它也会默认预留出滚动区域的空间,不会自动收缩到刚好包裹内容的高度。而用静态布局的话,控件会完全贴合内容大小,自然就没空白了。
内容的提问来源于stack exchange,提问作者Azurry
相关产品推荐
相关产品推荐

