简体   繁体   English

区分加载到列表项与滚动事件Xamarin表单ListView的项目

[英]Differentiate items loading to list vs scroll event Xamarin forms listview

This is my code that can successfully detect scroll up or down: 这是我的代码,可以成功检测向上或向下滚动:

 MyListView.ItemAppearing += async (object sender, ItemVisibilityEventArgs e) =>
        {
            var currentIdx = CurrentList.IndexOf((MyClass)e.Item);

            if (currentIdx > _lastItemAppearedIdx)
                ShowChopped();
            else
                ShowFull();

            _lastItemAppearedIdx = CurrentList.IndexOf((MyClass)e.Item);
        };

What is working is the following: Items get added to the list, then once i start scrolling it works fine where ShowChopped and ShowFull are methods with animations that just makes a simple animation to either half the size of an object or make it full. 起作用的是以下内容:将项目添加到列表中,然后一旦我开始滚动, ShowChoppedShowFull是带有动画的方法,它们可以将简单的动画制作为对象大小的一半或使其变满。 This works fine, but if i however click a new category that changes the content in the list, ItemAppearing gets triggered of course and ShowChopped and ShowFull are called even though i only want it called during a scrollevent. 这工作正常,但是如果我单击更改目录中内容的新类别,则ItemAppearing当然会被触发,并且即使我只希望在ShowFull中调用ShowChoppedShowFull也是如此。

How would i be able to differentiate a scroll to a item collection change? 我将如何区分卷轴与项目集合更改? I have only tried this on iOS. 我只在iOS上尝试过。

Updated code: 更新的代码:

public class ListView_iOS : ListViewRenderer
{
    private IDisposable _offsetObserver;
    private double _prevYOffset;
    private IListView _myListView;

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement is IListView)
            _offsetObserver = Control.AddObserver("contentOffset",
                         Foundation.NSKeyValueObservingOptions.New, HandleAction);
    }

    private static bool CloseTo(double x, double y)
    {
        return Math.Abs(x - y) < 0.1;
    }

    private void HandleAction(Foundation.NSObservedChange obj)
    {
        var effectiveY = Math.Max(Control.ContentOffset.Y, 0);
        if (!CloseTo(effectiveY, _prevYOffset) && Element is IListView)
        {
            var myList = Element as IListView;
            myList.IsScrolling = true;
        }
    }
}

You can differentiate items loading from list scrolling by 您可以通过以下方式区分项目加载与列表滚动

1 adding the code if (EmployeeView.IsScrolling) within ItemAppearing method. 1在ItemAppearing方法中添加if (EmployeeView.IsScrolling)代码。

2 adding the code EmployeeView.IsScrolling = false; 2添加代码EmployeeView.IsScrolling = false; within any function you write to change the appearing of items without scrolling action, for example, when you add items or change category. 在编写的任何函数中都可以更改项目的外观,而无需滚动操作,例如,添加项目或更改类别时。

And the EmployeeView.IsScrolling value is set from listview renderer. 并从listview渲染器设置EmployeeView.IsScrolling值。

So the code is like: 所以代码就像:

NativeListView.cs NativeListView.cs

public class NativeListView : ListView
    {
        public static readonly BindableProperty
            IsScrollingProperty =
                BindableProperty.Create(nameof(IsScrolling),
                typeof(bool), typeof(NativeListView), false);

        public bool IsScrolling
        {
            get { return (bool)GetValue(IsScrollingProperty); }
            set { SetValue(IsScrollingProperty, value); }
        }
    }

NativeAndroidListViewRenderer.cs NativeAndroidListViewRenderer.cs

[assembly: ExportRenderer(typeof(NativeListView), typeof(NativeAndroidListViewRenderer))]
namespace App2.Droid
{
    public class NativeAndroidListViewRenderer : ListViewRenderer
    {
        public NativeAndroidListViewRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is NativeListView)
                Control.Scroll += Control_Scroll;
        }
        private void Control_Scroll(object sender, AbsListView.ScrollEventArgs e)
        {
            var myList = Element as NativeListView;
            myList.IsScrolling = true;
        }

    }
}

NativeiOSListViewRenderer.cs NativeiOSListViewRenderer.cs

    private IDisposable _offsetObserver;
    private double _prevYOffset;
    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
    {
        base.OnElementChanged(e);

        if (e.NewElement is NativeListView)
            _offsetObserver = Control.AddObserver("contentOffset",
                         Foundation.NSKeyValueObservingOptions.New, HandleAction);
    }

    private void HandleAction(Foundation.NSObservedChange obj)
    {
        var effectiveY = Math.Max(Control.ContentOffset.Y, 0);
        if (!CloseTo(effectiveY, _prevYOffset) && Element is NativeListView)
        {
            var myList = Element as NativeListView;

            myList.IsScrolling = true;
            _prevYOffset = effectiveY;
        }
    }
    private static bool CloseTo(double x, double y)
    {
        return Math.Abs(x - y) < 0.1;
    }
    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing && _offsetObserver != null)
        {
            _offsetObserver.Dispose();
            _offsetObserver = null;
        }
    }

MainPage.xaml.cs MainPage.xaml.cs中

namespace App2
{
    public partial class MainPage : ContentPage
    {
        ObservableCollection<String> employeeList = new ObservableCollection<String>();
        int count = 0;

        public MainPage()
        {
            InitializeComponent();
            AddButtion.Clicked += AddButtion_Clicked;
            DelButtion.Clicked += DelButtion_Clicked;
            EmployeeView.ItemsSource = employeeList;

            EmployeeView.ItemAppearing += async (object sender, ItemVisibilityEventArgs e) =>
            {
                if (EmployeeView.IsScrolling) {
                    await DisplayAlert("ItemAppearing", e.Item + " row is appearing", "OK");
                    Console.WriteLine("ItemAppearing!!!!!!!!!!");
                }
            };

        }

        private void AddButtion_Clicked(object sender, EventArgs e)
        {
            employeeList.Add("Mr. Mono"+ count++);

            EmployeeView.IsScrolling = false;
        }

        private void DelButtion_Clicked(object sender, EventArgs e)
        {
            if (employeeList.Count > 0) {
                employeeList.RemoveAt(0);
            }
            EmployeeView.IsScrolling = false;

        }
    }
}

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

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