【问题标题】:Xamarin forms: Expansion and collapse is not working for list view in iOSXamarin 表单:扩展和折叠不适用于 iOS 中的列表视图
【发布时间】:2021-08-13 09:29:06
【问题描述】:

我在 UI 上列出了一些项目。如果我点击一个项目,它将展开并显示其详细信息。我最初在 UI 上设置了所有内容,包括详细信息并隐藏了详细信息部分。当我点击该项目时,我会更改详细信息的可见性并将其显示在 UI 上。此功能在 android 上运行良好并在 ios 上运行良好。我已经上传了一个示例项目here 供参考。

截图:

Xaml.cs

    private void ItemTapped(object sender, ItemTappedEventArgs e)
    {
        var selectedItem = (Contact)e.Item;
        if (selectedItem != null)
        {
            if (phoneId == selectedItem.phoneOne)
            {
                Hide(selectedItem);
                phoneId = "";
            }
            else
            {
                Open(selectedItem);
            }
        }
        addressbook_listview.SelectedItem = null;
    }

    private void Open(Contact selectedItem)
    {
        
        foreach (var item in contactsList)
        {
            item.PhoneVisibility = false;
        }
        selectedItem.PhoneVisibility = true;
        phoneId = selectedItem.phoneOne;
    }
    
    private void Hide(Contact selectedItem)
    {
        selectedItem.PhoneVisibility = false;
    }

Xaml

    <ListView   
        x:Name="addressbook_listview"
        Grid.Row="1"
        BackgroundColor="Black"
        ItemTapped="addressbook_listview_ItemTapped"
        SelectionMode="None"
        HasUnevenRows="True">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout 
                        Padding="10"
                        Orientation="Vertical">

                        <StackLayout
                                Grid.Column="1"
                                VerticalOptions="CenterAndExpand"
                                Margin="5,0,0,0">

                            <Label 
                                    Text="{Binding contactName}"
                                    TextColor="White">
                                <Label.FontSize>
                                    <OnIdiom x:TypeArguments="x:Double">
                                        <OnIdiom.Phone>15</OnIdiom.Phone>
                                        <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                        <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                    </OnIdiom>
                                </Label.FontSize>
                            </Label>

                            <Label 
                                    Text="{Binding phoneOne}"
                                    TextColor="White">
                                <Label.FontSize>
                                    <OnIdiom x:TypeArguments="x:Double">
                                        <OnIdiom.Phone>15</OnIdiom.Phone>
                                        <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                        <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                    </OnIdiom>
                                </Label.FontSize>
                            </Label>
                        </StackLayout>

                        <StackLayout 
                            HorizontalOptions="CenterAndExpand"
                            Margin="0,10,0,0"
                            IsVisible="{Binding PhoneVisibility}"
                            Orientation="Vertical">

                            <StackLayout 
                                Orientation="Horizontal">

                                <Label 
                                    Text="Phone 1"
                                    TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>

                                    <Label 
                                    Text="{Binding phoneOne}"
                                    TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>

                            </StackLayout>

                            <BoxView HeightRequest="0.5"
                                     HorizontalOptions="FillAndExpand"/>

                            <StackLayout
                                Orientation="Horizontal">

                                <Label 
                                    Text="Phone 2"
                                     TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>

                                <Label 
                                    Text="{Binding phoneTwo}"
                                    TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>
                            </StackLayout>
                        </StackLayout>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.Footer>
            <Label/>
        </ListView.Footer>
    </ListView>

【问题讨论】:

标签: listview xamarin.forms


【解决方案1】:

这是@Shaw 指出的一个已知问题。

您可以调用ViewCell.ForceUpdateSize强制更新单元格的高度。

第一步是删除ItemTapped,改用Tap gesture。

在 ItemTemplate 的根 stackLayout 上添加TapGestureRecognizer。

xaml
<ViewCell x:Name="cell" >
        <StackLayout 
             Padding="10"
             Orientation="Vertical">
             <StackLayout.GestureRecognizers>
                  <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
             </StackLayout.GestureRecognizers>
代码隐藏。
  private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {

            var stack = sender as StackLayout;
            var selectedItem = stack.BindingContext as Contact;

            if (selectedItem != null)
            {
                if (phoneId == selectedItem.phoneOne)
                {
                    HideMessageBody(selectedItem);
                    phoneId = "";
                }
                else
                {
                    OpenMessageBody(selectedItem);
                }
            }
            addressbook_listview.SelectedItem = null;         

            (stack.Parent as ViewCell).ForceUpdateSize();   //add this line 
        }

【讨论】:

    【解决方案2】:

    简而言之:使用 CollectionView 代替 ListView。

    我认为这是一个已知问题,例如问题 this 和 this,但没有正确回答。
    所以决定搬到CollectionView,应该是官方推荐的。

    我在这里更改的内容:

    • 使用CollectionView
    • 将点击事件移动到TapGestureRecognizer
    • 删除 xaml 中的“网格”
    • 使列表绑定到 xaml,并在 xaml.cs 中绑定到自身
    • 绑定列表应该是公共属性,而不是字段
    • 最后一件事:更新到 Xamarin.Forms 5.0.0.2012(和 Android 设置)

    如果没有新的 XF 包,集合视图在更新高度时会出现另一个问题(在 iOS 上运行时不更新 XF,但这解决了这个问题)。
    我认为这也是一个已知问题,所以升级 XF 包修复了这个问题,
    但这也需要更新“目标 Android 版本”。
    (有些代码仍然可以重构,但现在可以使用)

    MainPage.xaml

    <?xml version="1.0" encoding="utf-8" ?>
    <ContentPage
        x:Class="ExpanderDemo.MainPage"
        xmlns="http://xamarin.com/schemas/2014/forms"
        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
        <StackLayout>
            <CollectionView
                x:Name="addressbook_listview"
                BackgroundColor="Black"
                ItemSizingStrategy="MeasureAllItems"
                ItemsSource="{Binding contactsList}"
                SelectionMode="None">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <StackLayout Padding="10" Orientation="Vertical">
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="addressbook_listview_ItemTapped" />
                            </StackLayout.GestureRecognizers>
    
                            <StackLayout Margin="5,0,0,0">
    
                                <Label Text="{Binding contactName}" TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>
    
                                <Label Text="{Binding phoneOne}" TextColor="White">
                                    <Label.FontSize>
                                        <OnIdiom x:TypeArguments="x:Double">
                                            <OnIdiom.Phone>15</OnIdiom.Phone>
                                            <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                            <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                        </OnIdiom>
                                    </Label.FontSize>
                                </Label>
                            </StackLayout>
    
                            <StackLayout
                                Margin="0,10,0,0"
                                HorizontalOptions="CenterAndExpand"
                                IsVisible="{Binding PhoneVisibility}"
                                Orientation="Vertical">
    
                                <StackLayout Orientation="Horizontal">
    
                                    <Label Text="Phone 1" TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>
    
                                    <Label Text="{Binding phoneOne}" TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>
    
                                </StackLayout>
    
                                <BoxView HeightRequest="0.5" HorizontalOptions="FillAndExpand" />
    
                                <StackLayout Orientation="Horizontal">
    
                                    <Label Text="Phone 2" TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>
    
                                    <Label Text="{Binding phoneTwo}" TextColor="White">
                                        <Label.FontSize>
                                            <OnIdiom x:TypeArguments="x:Double">
                                                <OnIdiom.Phone>15</OnIdiom.Phone>
                                                <OnIdiom.Tablet>20</OnIdiom.Tablet>
                                                <OnIdiom.Desktop>15</OnIdiom.Desktop>
                                            </OnIdiom>
                                        </Label.FontSize>
                                    </Label>
                                </StackLayout>
                            </StackLayout>
                        </StackLayout>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
                <CollectionView.Footer>
                    <Label />
                </CollectionView.Footer>
            </CollectionView>
        </StackLayout>
    </ContentPage>
    

    MainPage.xaml.cs

    using System;
    using System.Collections.ObjectModel;
    using Xamarin.Forms;
    
    namespace ExpanderDemo
    {
        public partial class MainPage : ContentPage
        {
            private string phoneId;
    
            public MainPage()
            {
                InitializeComponent();
                contactsList = new ObservableCollection<Contact>();
                AddNumber();
                BindingContext = this;
            }
    
            public ObservableCollection<Contact> contactsList { get; set; }
    
            private void AddNumber()
            {
                contactsList.Add(new Contact() { contactName = "Smith", phoneOne = "+1 1234567952", phoneTwo = "1478523690", PhoneVisibility = false });
                contactsList.Add(new Contact() { contactName = "Brent", phoneOne = "+1 1234568852", phoneTwo = "1478577690", PhoneVisibility = false });
                contactsList.Add(new Contact() { contactName = "Finch", phoneOne = "+1 1234560052", phoneTwo = "1478529690", PhoneVisibility = false });
                //addressbook_listview.ItemsSource = contactsList;
            }
    
            private void addressbook_listview_ItemTapped(object sender, EventArgs e)
            {
                var layout = sender as StackLayout;
                var selectedItem = layout.BindingContext as Contact;
    
                //var selectedItem = (Contact)e.Item;
                if (selectedItem != null)
                {
                    if (phoneId == selectedItem.phoneOne)
                    {
                        HideMessageBody(selectedItem);
                        phoneId = "";
                    }
                    else
                    {
                        OpenMessageBody(selectedItem);
                    }
                }
                addressbook_listview.SelectedItem = null;
            }
    
            private void HideMessageBody(Contact selectedItem)
            {
                selectedItem.PhoneVisibility = false;
            }
    
            private void OpenMessageBody(Contact selectedItem)
            {
                foreach (var item in contactsList)
                {
                    item.PhoneVisibility = false;
                }
                selectedItem.PhoneVisibility = true;
                phoneId = selectedItem.phoneOne;
            }
        }
    }
    

    Android 更新 XF 后的两项设置


    测试结果

    (我在本地测试时请忽略ios上的颜色。)

    【讨论】:

    • 感谢您的回复。在演示项目中,我只添加了 3 个项目。在我的实际项目中,我首先列出了一些项目,当向下滚动并到达底部时,我将使用 listview 的ItemAppearing 事件获取更多项目。 colectionview 上是否有任何相同类型的事件可用于检测项目的结束?我检查了这个,但没有运气。那么有没有办法用listview 本身来解决这个问题?
    • 这实际上是与ios列表高度不同的问题。但是检查this vedio或the docs link,可以通过检查集合中的阈值来实现。或者只是发布一个新的 Q 以便我们可以讨论一些真实的代码。
    猜你喜欢
    • 2010-11-25
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2013-09-07
    • 1970-01-01
    相关资源
    最近更新 更多