Xamarin.Forms菜鸟笔记--3.ListView上拉加载更多

参考地址:https://www.cnblogs.com/devin_zhou/p/9979382.html

参考代码:

public class LoadMoreListView : ListView
{
    private readonly StackLayout LoadingContent;
    private readonly StackLayout LoadMoreContent;
    private readonly StackLayout NoDataContent;

    public LoadMoreListView() : base(ListViewCachingStrategy.RecycleElement)
    {
        Xamarin.Forms.PlatformConfiguration.iOSSpecific.ListView.SetSeparatorStyle(this, Xamarin.Forms.PlatformConfiguration.iOSSpecific.SeparatorStyle.FullWidth);
        LoadingContent = CreateFooter("正在加载中...",true);
        LoadMoreContent = CreateFooter("上拉加载更多",false);
        NoDataContent = CreateFooter("已加载全部数据",false);
        ItemAppearing += LoadMoreListView_ItemAppearing;
    }

    private void LoadMoreListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
    {
        if (ItemsSource is IList items && e.Item == items[items.Count - 1])
        {
            if (CanLoadMore && LoadStatus == LoadMoreStatus.StatusHasData)
            {
                if (CanLoadMore && (LoadMoreCommand?.CanExecute(null) == true))
                    LoadMoreCommand.Execute(null);
            }
        }
    }

    private StackLayout CreateFooterContent(string content,bool indicator = false)
    {
        var item = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            HeightRequest = 50,
            VerticalOptions = LayoutOptions.CenterAndExpand,
            HorizontalOptions = LayoutOptions.CenterAndExpand,
        };
        if(indicator)
        {
            try
            {
                item.Children.Add(new ActivityIndicator
                {
                    IsRunning = true,
                    WidthRequest = 20,
                    HeightRequest = 20,
                    VerticalOptions = LayoutOptions.CenterAndExpand
                });
            }
            catch(Exception e)
            {
                Debug.WriteLine(e.Message);
            }
        }

        item.Children.Add(new Label
        {
            Text = content,
            VerticalOptions = LayoutOptions.CenterAndExpand
        });
        return item;
    }

    private StackLayout CreateFooter(string content,bool hasIndicator)
    {
        var item = new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            HeightRequest = 50,
        };
        var contentStack = CreateFooterContent(content,hasIndicator);
        item.Children.Add(contentStack);
        return item;
    }

    public static readonly BindableProperty LoadMoreCommandProperty = BindableProperty.Create(nameof(LoadMoreCommand), typeof(ICommand), typeof(LoadMoreListView), default(ICommand));

    public ICommand LoadMoreCommand
    {
        get { return (ICommand)GetValue(LoadMoreCommandProperty); }
        set { SetValue(LoadMoreCommandProperty, value); }
    }

    public static readonly BindableProperty CanLoadMoreProperty = BindableProperty.Create(nameof(CanLoadMore), typeof(bool), typeof(LoadMoreListView), false);
    public bool CanLoadMore
    {
        get { return (bool)GetValue(CanLoadMoreProperty); }
        set { SetValue(CanLoadMoreProperty, value); }
    }

    public static readonly BindableProperty LoadStatusProperty = BindableProperty.Create(nameof(LoadStatus), typeof(LoadMoreStatus), typeof(LoadMoreListView), LoadMoreStatus.StatusDefault, propertyChanged: OnLoadStatusChanged);

    public LoadMoreStatus LoadStatus
    {
        get { return (LoadMoreStatus)GetValue(LoadStatusProperty); }
        set { SetValue(LoadStatusProperty, value); }
    }

    private static void OnLoadStatusChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var lv = (LoadMoreListView)bindable;
        lv.NotifyLoadStatus((LoadMoreStatus)newValue);
    }

    public void NotifyLoadStatus(LoadMoreStatus loadStatus)
    {
        switch (loadStatus)
        {
            case LoadMoreStatus.StatusDefault:
                this.Footer = null;
                break;
            case LoadMoreStatus.StatusLoading:
                this.Footer = LoadingContent;
                break;
            case LoadMoreStatus.StatusHasData:
                this.Footer = LoadMoreContent;
                break;
            case LoadMoreStatus.StatusNoData:
                this.Footer = NoDataContent;
                break;
            default:
                this.Footer = null;
                break;
        }
    }

}

public enum LoadMoreStatus
{
    StatusDefault = 0,
    StatusLoading = 1,
    StatusHasData = 2,
    StatusNoData = 3,
}

经过测试我发现LoadStatusProperty并没有触发,所以底部的状态没有呈现出来,我做了如下小改动

public class LoadMoreListView : ListView
    {
        #region 全局变量

        private int totleCount = 0;
        private object LastItem;

        private readonly StackLayout LoadingContent;
        private readonly StackLayout LoadMoreContent;
        private readonly StackLayout NoDataContent;

        public static readonly BindableProperty LoadMoreCommandProperty = BindableProperty.Create(nameof(LoadMoreCommand), typeof(ICommand), typeof(LoadMoreListView), default(ICommand));

        /// <summary>
        /// 加载状态改变事件
        /// 未触发,未知原因,先放着
        /// </summary>
        public static readonly BindableProperty LoadStatusProperty = BindableProperty.Create(nameof(LoadStatus), typeof(LoadMoreStatus), typeof(LoadMoreListView), LoadMoreStatus.StatusDefault, propertyChanged: OnLoadStatusChanged);

        #endregion

        #region 构造函数

        public LoadMoreListView() : base(ListViewCachingStrategy.RecycleElement)
        {
            Xamarin.Forms.PlatformConfiguration.iOSSpecific.ListView.SetSeparatorStyle(this, Xamarin.Forms.PlatformConfiguration.iOSSpecific.SeparatorStyle.FullWidth);
            LoadingContent = CreateFooter("加载中...", true);
            LoadMoreContent = CreateFooter("上拉加载更多", false);
            NoDataContent = CreateFooter("已加载全部数据", false);
            ItemAppearing += LoadMoreListView_ItemAppearing;
            // this.Footer = LoadMoreContent;
        }

        #endregion

        #region 加载更多

        public ICommand LoadMoreCommand
        {
            get { return (ICommand)GetValue(LoadMoreCommandProperty); }
            set { SetValue(LoadMoreCommandProperty, value); }
        }

        private void LoadMoreListView_ItemAppearing(object sender, ItemVisibilityEventArgs e)
        {
            IList items = ItemsSource as IList;
            if (items != null && e.Item == items[items.Count - 1])
            {
                // UserDialogs.Instance.ShowLoading();
                if (LoadMoreCommand != null && LoadMoreCommand.CanExecute(null) && LastItem != e.Item)
                {
                    totleCount = items.Count;
                    this.Footer = LoadingContent;
                    System.Threading.Tasks.Task.Delay(500).ContinueWith((t) => {
                        Device.BeginInvokeOnMainThread(() => {
                            this.Footer = null;
                            LastItem = e.Item;
                            LoadMoreCommand.Execute(null);
                            if(totleCount == items.Count)
                                this.Footer = NoDataContent;
                        });
                    });
                }
                // UserDialogs.Instance.HideLoading();
                if(items.Count < 20)
                {
                    this.Footer = NoDataContent;
                }
            }
        }

        #endregion

        #region 生成Footer

        private StackLayout CreateFooterContent(string content, bool indicator = false)
        {
            var item = new StackLayout
            {
                Orientation = StackOrientation.Horizontal,
                HeightRequest = 50,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand,
            };
            if (indicator)
            {
                try
                {
                    item.Children.Add(new ActivityIndicator
                    {
                        IsRunning = true,
                        WidthRequest = 20,
                        HeightRequest = 20,
                        VerticalOptions = LayoutOptions.CenterAndExpand
                    });
                }
                catch (Exception e)
                {
                    //Debug.WriteLine(e.Message);
                }
            }

            item.Children.Add(new Label
            {
                Text = content,
                VerticalOptions = LayoutOptions.CenterAndExpand,
                TextColor = Color.DimGray
            });
            return item;
        }

        private StackLayout CreateFooter(string content, bool hasIndicator)
        {
            var item = new StackLayout
            {
                Orientation = StackOrientation.Horizontal,
                HeightRequest = 50,
            };
            var contentStack = CreateFooterContent(content, hasIndicator);
            item.Children.Add(contentStack);
            return item;
        }

        private static void OnLoadStatusChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var lv = (LoadMoreListView)bindable;
            lv.NotifyLoadStatus((LoadMoreStatus)newValue);
        }

        public void NotifyLoadStatus(LoadMoreStatus loadStatus)
        {
            switch (loadStatus)
            {
                case LoadMoreStatus.StatusDefault:
                    this.Footer = null;
                    break;
                case LoadMoreStatus.StatusLoading:
                    this.Footer = LoadingContent;
                    break;
                case LoadMoreStatus.StatusHasData:
                    this.Footer = LoadMoreContent;
                    break;
                case LoadMoreStatus.StatusNoData:
                    this.Footer = NoDataContent;
                    break;
                default:
                    this.Footer = null;
                    break;
            }
        }

        public LoadMoreStatus LoadStatus
        {
            get { return (LoadMoreStatus)GetValue(LoadStatusProperty); }
            set { SetValue(LoadStatusProperty, value); }
        }

        #endregion

    }

    public enum LoadMoreStatus
    {
        StatusDefault = 0,
        StatusLoading = 1,
        StatusHasData = 2,
        StatusNoData = 3,
    }

我之前没有加状态显示部分,直接在LoadMoreListView_ItemAppearing中

UserDialogs.Instance.ShowLoading();
if (LoadMoreCommand != null && LoadMoreCommand.CanExecute(null) && LastItem != e.Item)
 {
     LastItem = e.Item;
     LoadMoreCommand.Execute(null);
 }
 UserDialogs.Instance.HideLoading();

效果没有添加底部的好,有点卡顿

记录一下,备忘

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值