当列表中的项目很少时,如何将ListView项目对齐到屏幕底部?

时间:2017-08-24 11:59:32

标签: listview xamarin.forms

我希望有一个Xamarin.Forms ListView从下到上开始显示其元素,以便当项目很少时,元素显示在ListView的底部。请参阅图像以获取解释。这可以不用手动设置ListView的HeightRequest吗? (如果需要手动设置HeightRequest,当我使用HasUnevenRows=true时如何计算ListView的子元素的高度?)

这就是我想要的样子(左边几个项目,右边有很多项目);

Desired behavior for few items to the left; many items to the right.

作为参考,以下是当项目很少时ListView正常工作的方式:

Current behavior for few items.

2 个答案:

答案 0 :(得分:3)

如果ListView不是必需的,并且您只需要具有模板支持的可重复控制 - 您可以使用ItemsControl。由于它使用StackLayout作为其面板,因此它只会扩展到所需的高度。所以,你不需要计算它的高度。 请注意ItemsControl具有非常基本的虚拟化行为(回收) - 因此,如果您有很多项目,那么您将不得不修改控件以支持虚拟化。

其次,您可以将Grid扩展为根据底部内容大小自动将第二个RowDefinition设置为AutoStar。即默认情况下将其保留为Auto,但如果内容大小超过视口高度的50%,则将RowDefinition重置为Star。例如,您可以将自定义SplitterGrid创建为:

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>

enter image description here

答案 1 :(得分:0)

我会选择一个网格,其中定义了两行,其中一行设置为“*”,或者您想要的高度为像素,底部一行设置为“Auto”,listview VerticalOptions设置为“End”。