当列表中的项目很少时,如何将ListView项目与屏幕底部对齐?
我想要一个Xamarin.Forms列表视图,它从下到上显示它的元素,这样当项目很少时,元素就会显示在列表视图的底部。请参见图中的说明。这是否可以在不必手动设置ListView的HeightRequest的情况下实现?(如果需要手动设置HeightRequest,那么当我使用当列表中的项目很少时,如何将ListView项目与屏幕底部对齐?,listview,xamarin.forms,Listview,Xamarin.forms,我想要一个Xamarin.Forms列表视图,它从下到上显示它的元素,这样当项目很少时,元素就会显示在列表视图的底部。请参见图中的说明。这是否可以在不必手动设置ListView的HeightRequest的情况下实现?(如果需要手动设置HeightRequest,那么当我使用hasLows=true时,如何计算ListView子元素的高度?) 下面是我希望它的外观(左边的项目很少,右边的项目很多) 以下是ListView在项目较少时的正常工作方式供参考: 我会选择一个网格,其中两行定义为“*”
hasLows=true
时,如何计算ListView子元素的高度?)
下面是我希望它的外观(左边的项目很少,右边的项目很多)
以下是ListView在项目较少时的正常工作方式供参考:
我会选择一个网格,其中两行定义为“*”或您想要的像素高度,底部定义为“自动”,listview垂直选项设置为“结束”。如果
listview
不是强制性的,并且您只需要一个具有模板支持的可重复控件,您可以使用。由于它使用StackLayout
作为面板,因此它只能扩展到所需的高度。所以,你不需要计算它的高度请注意ItemsControl
具有非常基本的虚拟化行为(回收)-因此,如果您有很多项目,则必须修改该控件以支持虚拟化。
其次,您可以扩展网格
,根据底部内容大小自动将第二个行定义
设置为自动
或星型
。i、 e.默认情况下,将其保持为自动
,但如果内容大小大于视口高度的50%,则将行定义
重置为星型
。例如,您可以创建自定义的拆分网格,如下所示:
public class SplitterGrid : Grid
{
public SplitterGrid()
{
RowDefinitions = new RowDefinitionCollection()
{
new RowDefinition { Height = GridLength.Star },
new RowDefinition { Height = GridLength.Auto }
};
}
void Content2_SizeChanged(object sender, EventArgs e)
{
if (Height == 0 && Width == 0)
return;
Content2.SizeChanged -= Content2_SizeChanged;
if (Content2.Height > Height / 2)
RowDefinitions[1].Height = GridLength.Star;
else
RowDefinitions[1].Height = GridLength.Auto;
}
public static readonly BindableProperty Content1Property =
BindableProperty.Create(
"Content1", typeof(View), typeof(SplitterGrid),
defaultValue: null, propertyChanged: OnContent1Changed);
public View Content1
{
get { return (View)GetValue(Content1Property); }
set { SetValue(Content1Property, value); }
}
private static void OnContent1Changed(BindableObject bindable, object oldValue, object newValue)
{
((SplitterGrid)bindable).OnContent1ChangedImpl((View)oldValue, (View)newValue);
}
void OnContent1ChangedImpl(View oldValue, View newValue)
{
if (oldValue == null)
Children.Add(Content1);
}
public static readonly BindableProperty Content2Property =
BindableProperty.Create(
"Content2", typeof(View), typeof(SplitterGrid),
defaultValue: null, propertyChanged: OnContent2Changed);
public View Content2
{
get { return (View)GetValue(Content2Property); }
set { SetValue(Content2Property, value); }
}
private static void OnContent2Changed(BindableObject bindable, object oldValue, object newValue)
{
((SplitterGrid)bindable).OnContent2ChangedImpl((View)oldValue, (View)newValue);
}
void OnContent2ChangedImpl(View oldValue, View newValue)
{
if (oldValue == null)
{
Children.Add(Content2);
Content2.SizeChanged += Content2_SizeChanged;
Grid.SetRow(Content2, 1);
}
else
Content2.SizeChanged -= Content2_SizeChanged;
}
}
并且,使用情况如下所示:
<local:SplitterGrid Margin="0,20,0,0">
<local:SplitterGrid.Content1>
<ContentView Padding="10" BackgroundColor="#E4E4E4">
<Label Text="This page contains about 3 items." />
</ContentView>
</local:SplitterGrid.Content1>
<local:SplitterGrid.Content2>
<ScrollView VerticalOptions="End">
<local:ItemsControl>
<local:ItemsControl.ItemTemplate>
<DataTemplate>
<Label FontAttributes="Bold" FontSize="40" Text="{Binding .}" />
</DataTemplate>
</local:ItemsControl.ItemTemplate>
<local:ItemsControl.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item 1</x:String>
<x:String>Item 2</x:String>
<x:String>Item 3</x:String>
</x:Array>
</local:ItemsControl.ItemsSource>
</local:ItemsControl>
</ScrollView>
</local:SplitterGrid.Content2>
</local:SplitterGrid>
项目1
项目2
项目3
不幸的是,这似乎不起作用。在
Auto
行中,ListView的扩展似乎优先于*
行的扩展。结果和我开始时差不多。谢谢,ItemsControl运行得非常好(除了a)。我相信,这应该很容易修复;通过在ItemsSource change listener中添加clear方法(如果新的集合计数小于以前),是的,我链接到一个修复它的PR。