ListView中的空间超出了我的需要

本文关键字:我的 空间 ListView | 更新日期: 2023-09-27 17:58:40

我使用StackLayout和ListView来显示视图的某些部分,但ListView占用的空间比我需要的要多,并且在列表的最后一行和概要文件的连续部分之间留有空白。我的ListView似乎比实际列表的长度有更多的行,或者它有一个固定的高度,我不知道。。。这是我的XAML:

<ScrollView>
  <StackLayout Orientation="Vertical" Spacing="10">
    <Label Text="{Binding Establishment.Name}" TextColor="Black" HorizontalOptions="StartAndExpand" Style="{DynamicResource TitleStyle}" FontAttributes="Bold"/>
    <Label Text="{Binding Establishment.Category.Name,  StringFormat='Categoria: {0}'}" TextColor="Black" HorizontalOptions="StartAndExpand"  FontAttributes="Bold"/>
    <Label Text="{Binding Establishment.Description}" TextColor="Black" HorizontalOptions="StartAndExpand" LineBreakMode="WordWrap" XAlign="Start"/>
    <Label Text="Contatos" TextColor="Black" HorizontalOptions="StartAndExpand"  FontAttributes="Bold"/>
    <ListView  ItemsSource="{Binding Establishment.Contacts}" VerticalOptions="Start" HasUnevenRows="True">
      <ListView.ItemTemplate>
        <DataTemplate>
          <TextCell Text="{Binding Value}" Detail="{Binding StringType}" DetailColor="Gray"/>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
    <Label Text="Endereço" TextColor="Black" HorizontalOptions="StartAndExpand"  FontAttributes="Bold"/>
    <Label Text="{Binding Establishment.FullAddress}" TextColor="Black" HorizontalOptions="StartAndExpand"  />
    <Button Text="Ver no mapa"/>
  </StackLayout>
</ScrollView>

我该怎么修?我看到有人使用HasUnevenRows="True",但它对我不起作用。

ListView中的空间超出了我的需要

正如hvaughan3所说,这真的不是一个好的做法。但我遇到了同样的情况,我对行为使用了变通方法:

public class ListViewHeightBehavior : Behavior<ListView>
{
    private ListView _listView;
    public static readonly BindableProperty ExtraSpaceProperty =
        BindableProperty.Create(nameof(ExtraSpace),
                                typeof(double),
                                typeof(ListViewHeightBehavior),
                                0d);
    public double ExtraSpace
    {
        get { return (double)GetValue(ExtraSpaceProperty); }
        set { SetValue(ExtraSpaceProperty, value); }
    }
    protected override void OnAttachedTo(ListView bindable)
    {
        base.OnAttachedTo(bindable);
        _listView = bindable;
        _listView.PropertyChanged += (s, args) =>
        {
            var count = _listView.ItemsSource?.Count();
            if (args.PropertyName == nameof(_listView.ItemsSource)
                    && count.HasValue
                    && count.Value > 0)
            {
                _listView.HeightRequest = _listView.RowHeight * count.Value + ExtraSpace;
            }
        };
    }
}

XAML:

     <ListView ItemsSource="{Binding Items}"
               HasUnevenRows="True">
      <ListView.Behaviors>
        <behaviors:ListViewHeightBehavior ExtraSpace="180"/>
      </ListView.Behaviors>
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
             // Your template
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

首先,Xamarin建议不要在ScrollView中放入ListView,因为它们都提供滚动功能并相互争斗。我亲自尝试过,它经常会引起奇怪的行为,尤其是在安卓系统上。

相反,我所做的是将ListView.HeaderListView.HeaderTemplate一起使用,将ListView.FooterListView.FooterTemplate一起使用。Xamarin链接这里这允许你的确切场景,但没有奇怪的行为问题。如果你想看一个这样的例子,请告诉我。

如果你必须使用当前的布局,你可以尝试查看这篇文章,讨论ListView需要如何使用特定的HeightWidthLayoutOptions来调整大小,因为它不应该适合内容的大小。这篇文章中有几个解决方案,我还没有尝试过。

在这篇文章中,给出的一个解决方案是,将ListView添加到StackLayout,并将其添加到另一个StackLayout。然后将内部StackLayoutVerticalOptions设置为LayoutOptions.FillAndExpand

所以它可能看起来像这样:

<ScrollView>
  <StackLayout Orientation="Vertical" Spacing="10">
    ....
    <StackLayout VerticalOptions="FillAndExpand">
      <ListView ItemsSource="{Binding Establishment.Contacts}" VerticalOptions="Start" HasUnevenRows="True">
        <ListView.ItemTemplate>
          <DataTemplate>
            <TextCell Text="{Binding Value}" Detail="{Binding StringType}" DetailColor="Gray"/>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>
    </StackLayout>
    ....
  </StackLayout>
</ScrollView>

我对Yehor Hromadskyi的解决方案有问题。

  • 首先,IEnumerable没有Count方法。必须首先将其强制转换为IEnumerable
  • 其次,如果你不设置RowHeight,那么整个列表就会崩溃,你会遇到相反的问题

以下是修复问题的代码更改

public class ListViewHeightBehavior : Behavior<ListView>
{
    private ListView _listView;
    public static readonly BindableProperty ExtraSpaceProperty =
        BindableProperty.Create(nameof(ExtraSpace),
                                typeof(double),
                                typeof(ListViewHeightBehavior),
                                0d);
    public static readonly BindableProperty DefaultRowHeightProperty =
        BindableProperty.Create(nameof(DefaultRowHeight),
                          typeof(int),
                          typeof(ListViewHeightBehavior),
                          40);
    public int DefaultRowHeight
    {
        get => (int)GetValue(DefaultRowHeightProperty);
        set => SetValue(DefaultRowHeightProperty, value);
    }
    public double ExtraSpace
    {
        get { return (double)GetValue(ExtraSpaceProperty); }
        set { SetValue(ExtraSpaceProperty, value); }
    }
    protected override void OnAttachedTo(ListView bindable)
    {
        base.OnAttachedTo(bindable);
        _listView = bindable;
        _listView.PropertyChanged += (s, args) =>
        {
            var count = _listView.ItemsSource?.Cast<object>()?.Count();
            if (args.PropertyName == nameof(_listView.ItemsSource)
                    && count.HasValue
                    && count.Value > 0)
            {
                int rowHeight = _listView.RowHeight > 0 ? _listView.RowHeight : DefaultRowHeight;
                _listView.HeightRequest = rowHeight * count.Value + ExtraSpace;
            }
        };
    }
}

谢谢你们,但对我来说什么都不起作用。我自己认为的解决方案肯定不是最好的,但它对我有效…

在XAML中,我留下了一个空的StackLayout,如下所示:

    <StackLayout x:Name="ContactsList" Orientation="Vertical" Spacing="10" Padding="8,0">
      <!-- Empty because it will be filled in code mode -->
    </StackLayout>

然后,在.cs文件中,我在InitializeComponent()方法之后调用了这个方法:

    private void setUpContacts(Establishment establishment)
    {
        foreach(Contact contact in establishment.Contacts)
        {
            StackLayout row = new StackLayout
            {
                Orientation = StackOrientation.Vertical
            };
            row.Children.Add(new Label
            {
                TextColor = Color.Gray,
                Text = string.Format("{0}:", contact.StringType)
            });
            row.Children.Add(new Label
            {
                TextColor = Color.Black,
                FontAttributes = FontAttributes.Bold,
                Text = contact.Value,
            });
            row.GestureRecognizers.Add(new TapGestureRecognizer {
                Command = new Command(() => OnContactTapped(row, contact))
            });
            ContactsList.Children.Add(row);
        }
    }

我之所以这么做,是因为列表并不是一个真正的ListView,因为我不需要直接在列表中滚动函数,它只是视图的另一部分。我认为它不会造成任何性能问题,因为它会有少量的项目(最多5个)。我把这个标记为正确答案,以帮助其他人解决这个问题。

如果这是一个对其他人不起作用的解决方案,请告诉我,我会找到另一种方法。

示例布局显示,您在ScrollView中使用ListView,并且ListView具有不同高度的子级(HasUnevenRows="True")

<ScrollView>
     <ListView HasUnevenRows="True">
     </ListView>
</ScrollView>

这会导致列表的最后一行和ScrollView之间出现空白。

由于您已经添加了滚动视图作为root用户。您可以使用StackLayout (BindableLayout)用于相同目的

<ScrollView>
    <StackLayout
        x:Name="DummyList"
        BindableLayout.ItemsSource="{Binding ContactList}"
        Orientation="Vertical">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <TextCell
                    Detail="{Binding StringType}"
                    DetailColor="Gray"
                    Text="{Binding Value}" />
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </StackLayout>
</ScrollView>