在Xamarin Forms中自动调整iOS的列表行

时间:2016-08-03 11:35:50

标签: c# ios xamarin xamarin.forms

我遇到了在iOS上调整Xamarin Forms行大小的问题。我的代码在Android上完美运行。当我通过增加大小来调整iOS的行大小时,它将与下面的行重叠。谷歌搜索这给我这样的结果:http://forums.xamarin.com/discussion/comment/67627/#Comment_67627

结果声称由于性能问题,Xamarin Forms未实现此功能。我只找到1岁以上的结果,所以我不知道这是否仍然是原因。

我发现了许多不同的方法可以在我发现的不同主题中解决这个问题,但都非常复杂。

对我来说,在应用程序中通常会在选择时扩展项目。我想知道这里是否有人可以提出解决方案来解决这个问题?如果可能的话,我真的希望避免一遍又一遍地重新计算确切的高度。我应该使用Xamarin.iOS和依赖注入注入自定义列表吗?

我会在这里发布我的XAML,但XAML可能不是问题,因为它在Android上运行得很好。

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="simpletest.PlayGroundPage">
    <ContentPage.Content>
        <StackLayout>
            <ListView VerticalOptions="FillAndExpand" HasUnevenRows="True" SeparatorVisibility="None" ItemsSource="{Binding AllItems}" SelectedItem="{Binding MySelectedItem}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout VerticalOptions="FillAndExpand">
                                <Label Text="{Binding MyText}" />
                                <Button Text="button1" IsVisible="{Binding IsExtraControlsVisible}" />
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

我的表单项目包:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="FreshEssentials" version="2.0.1" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
  <package id="Xamarin.Forms" version="2.3.1.114" targetFramework="portable-net45+win+wp80+MonoTouch10+MonoAndroid10+xamarinmac20+xamarintvos10+xamarinwatchos10+xamarinios10" />
</packages>

这是我的viewmodel。

public class PlayGroundViewModel : INotifyPropertyChanged
{

    private Item _mySelectedItem;
    private ObservableCollection<Item> _allItems;

    public PlayGroundViewModel(ObservableCollection<Item> allItems)
    {
        AllItems = allItems;
        MySelectedItem = allItems.First();

        ItemClicked = (obj) => { ExpandRow(obj); };

    }

    public ObservableCollection<Item> AllItems { get { return _allItems; } set { _allItems = value; SetChangedProperty("AllItems"); } }

    public Action<Item> ItemClicked { get; private set; }

    public Item MySelectedItem
    {
        get { return _mySelectedItem; }
        set { _mySelectedItem = value; SetChangedProperty("MySelectedItem"); }
    }

    private void ExpandRow(Item item)
    {
        foreach (Item x in AllItems)
        {
            x.IsExtraControlsVisible = false;
        }

        if (item != null)
        {
            item.IsExtraControlsVisible = true;
        }

        SetChangedProperty("MySelectedItem");
        SetChangedProperty("AllItems");
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void SetChangedProperty(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

}

代码隐藏:

    public PlayGroundPage()
    {
        InitializeComponent();
        ObservableCollection<Item> items = new ObservableCollection<Item>();
        items.Add(new Item("One"));
        items.Add(new Item("Two"));
        items.Add(new Item("Three"));

        PlayGroundViewModel viewModel = new PlayGroundViewModel(items);
        BindingContext = viewModel;
        Action<Item> itemClickedAction = viewModel.ItemClicked;
        ItemList.ItemTapped += (object sender, ItemTappedEventArgs e) =>
          {
              Item item = (Item)e.Item;
              itemClickedAction.Invoke(item);
          };
    }
}

项目:

public class Item : INotifyPropertyChanged
{


    public Item(string text)
    {
        _myText = text;
        _isExtraControlsVisible = false;
    }

    private string _myText;
    private bool _isExtraControlsVisible;

    public event PropertyChangedEventHandler PropertyChanged;


    public string MyText
    {
        get { return _myText; }
        set { _myText = value; OnPropertyChanged("MyText"); }
    }

    public bool IsExtraControlsVisible
    {
        get { return _isExtraControlsVisible; }
        set { _isExtraControlsVisible = value; OnPropertyChanged("IsExtraControlsVisible"); }
    }

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}

我会在列表视图下方发布两张图片。第一张照片没有点击。第二张照片是在点击&#34; Two&#34;之后。单元格中出现一个按钮,但单元格与下面的单元格重叠(&#34; Three&#34;)。

Unclicked

Clicked

2 个答案:

答案 0 :(得分:11)

我不确定为什么SushiHangover没有同样的问题,但我得到了与你完全相同的结果。默认情况下,我的也不会调整大小。

无论您是想在更新项目时使用他的建议,还是使用您最初的方式,都应该强制您的单元格更新为正确的大小。

更改您的ViewCell以处理点按。

<ViewCell Tapped="Handle_Tapped">

然后在你的xaml页面的代码隐藏

void Handle_Tapped(object sender, System.EventArgs e)
{
    (sender as ViewCell).ForceUpdateSize();
}

ForceUpdateSize()的{​​{3}}表示要小心,因为它可能很昂贵,但是如果它确实是最少的努力让它去做你正在寻找的东西对

答案 1 :(得分:0)

可悲的是,ListView(也不是TableView)无法在iOS上动态调整其列的高度(在Android上工作完美)甚至调用ForceUpdateSize()方法。目前我正在使用Xamarin Forms 2.5.0。

更荒谬的是,当我向下滚动然后向后滚动以再次显示它们时,单元格会调整到正确的高度(!)。

经过大量的研究和测试很多解决方案后,我决定改变方法:我在ScrollView中创建了一个StackLayout,并在代码中动态地添加了ViewCells(我必须更改为ContentViews) - 在StackLayout后面。我从https://stackoverflow.com/a/41157227/2816119

得到了这个想法

这让我觉得这些集合视图还没有为这种用例做好准备。

自2014年以来,您可以找到许多人患此病。例如:https://xamarin.uservoice.com/forums/258559-xamarin-forms-suggestions/suggestions/6205412-make-it-possible-to-set-listview-cell-s-height-to#comments