简体   繁体   English

Xamarin iOS自定义ListView

[英]Xamarin iOS Custom ListView

I'm having trouble with the size of a ListView within a StackedLayout . 我在StackedLayout中使用ListView的大小遇到麻烦。 I want the ListView to take only as much space as necessary by the contained items. 我希望ListView仅占用所包含项目所需的空间。 However, my ListView almost always takes up all the space there is, even if it only contains like 3 items or so. 但是,我的ListView几乎总是占据那里的所有空间,即使它仅包含大约3个项目。

Is there a way to create a custom DynamicListView and override certain methods calculating a custom size whenever items are added or removed? 有没有一种方法可以创建自定义DynamicListView并覆盖某些在添加或删除项时计算自定义大小的方法? For example, I want the list to disappear whenever it's empty. 例如,我希望列表在任何空白时都消失。 Can anyone tell me, which methods to override and/or how to react on items being added/removed to the underlying model? 谁能告诉我,哪些方法可以替代和/或对添加/删除到基础模型的项目如何反应?

My gut feeling tells me something like this: 我的直觉告诉我这样的事情:

namespace Foo.Controls
{
    public class SpottedView : ListView
    {
        public SpottedView()
        {
        }

        protected override void OnChildAdded(Element child)
        {
            Console.WriteLine($"{Util.methodName()}");
            base.OnChildAdded(child);
            InvalidateMeasure();
        }

        protected override void OnChildRemoved(Element child)
        {
            Console.WriteLine($"{Util.methodName()}");
            base.OnChildRemoved(child);
            InvalidateMeasure();
        }
    }
}

I found a solution to this. 我找到了解决方案。 I changed from StackLayout to Grid as follows: 我从StackLayout更改为Grid ,如下所示:

<ContentPage.Content>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <ctrl:CameraView Grid.Row="0" />
        <ctrl:SpottedView Grid.Row="1" RowHeight="40" />

    </Grid>
</ContentPage.Content>

And then I added a custom ListView , a SpottedView as follows: 然后我添加了一个自定义ListViewSpottedView ,如下所示:

namespace Foo.Controls
{
    public class SpottedView : ListView
    {
        ObservableCollection<string> items;

        public SpottedView() : base()
        {
            items = new ObservableCollection<string>();
            ItemsSource = items;
            items.CollectionChanged += onItemsChanged;

            // TODO: test purposes, remove later
            var autoEvent = new AutoResetEvent(false);
            var stateTimer = new Timer(onTimer, autoEvent, 1000, 2000);
        }

        void onItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                HeightRequest = RowHeight * items.Count;
                InvalidateMeasure();
            });
        }

        // TODO test purposes, remove later.
        void onTimer(object state)
        {
            MainThread.BeginInvokeOnMainThread(() =>
            {
                if (items.Count < 2)
                {
                    items.Add("Blah");
                }
                else
                {
                    items.Clear();
                }
            });
        }
    }
}

Works like a charm. 奇迹般有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM