Xamarin Forms Pull To Refresh With ListView

The Xamarin Forms ListView control has the ability to allow the user to pull down from the top of the ListView to trigger a refresh command. I say a refresh command, because the pull to refresh, just triggers a command and you can do whatever you want in that command, including not updating the ListView.

Properties

There are 3 properties you need to be aware of to implement the pull to refresh functionality.

 <ListView ItemsSource="{Binding MyList}"
           IsPullToRefreshEnabled="True"
           RefreshCommand="{Binding RefreshCommand}"
           IsRefreshing="{Binding IsRefreshing}" />

Set IsPullToRefreshEnabled=”True” to enable the functionality, then create these 2 properties in your ViewModel.

private bool _isRefreshing = false;
public bool IsRefreshing { 
get { return _isRefreshing; }
set {
    _isRefreshing = value;
    OnPropertyChanged(nameof(IsRefreshing));
    }
}
public ICommand RefreshCommand
{
    get {
        return new Command(async () =>
        {
            IsRefreshing = true;
            
            await RefreshData();

            IsRefreshing = false;
        });
    }
}

Now when you pull down from the top of the listview, it will show a refresh animation, while IsRefreshing=”true”.

Pull To Refresh Android  Pull To Refresh iOS

Pull To Refresh Customization

On each platform we can customize a small part of the refresh animation.

Android

Android uses the SwipeRefreshLayout control to display an animation while the ListView is being updated. The SwipeRefreshLayout is internal in the ListViewRenderer, hence you are not able to call any properties on it directly, unless you want to write a whole new ListViewRenderer. Hence, until this has some access given, it’s currently impossible to do, without writing your own ListViewRenderer.

However, there is a way, using reflection and a custom renderer, that this can be done. It’s not the best solution, but it works.

First create a new file in Resources > values in your Android project, called array.xml

<?xml version="1.0" encoding="utf-8"?>
<resources> 
    <color name="red">#FF0000</color> 
    <array name="SwipeRefreshColors"> 
        <item>@color/red</item> 
    </array>
</resources>

Now create a custom renderer, to get this private field, and set the color.

[assembly: ExportRenderer(typeof(Xamarin.Forms.ListView), typeof(CustomListViewRenderer))]
namespace Mobile.Droid
{ 
    public class CustomListViewRenderer : ListViewRenderer 
    { 
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e) 
        { 
            base.OnElementChanged(e);
            if (e.NewElement != null) 
            { 
                FieldInfo[] fields = typeof(ListViewRenderer).GetFields( BindingFlags.NonPublic | BindingFlags.Instance);
                var refresh = (SwipeRefreshLayout)fields.First(x => x.Name == "_refresh").GetValue(this); 
                refresh.SetColorSchemeColors(this.Context.Resources.GetIntArray(Resource.Array.SwipeRefreshColors)); 
            }
        }
    }
}

iOS

In iOS the UIRefreshControl to display the animation while refreshing data. The UIRefreshControl has a TintColor and AttributedTitle, however unlike Android, we have a way to interact with this control. The ListViewRenderer has a ViewController, which is actually a UITableViewController. From here we can reach the RefreshControl.

[assembly: ExportRenderer(typeof(ListView), typeof(ListViewRender))]
namespace Mobile.iOS
{
    public class ListViewRender: ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);

            ((UITableViewController)ViewController).RefreshControl.TintColor = UIColor.Red;
        }
    }
}

Limitations

  • Not available on UWP, Android or Windows Phone 8.1
  • Not able to easily customize the refresh animation.
  • Only limited styling options available.


XAMARIN.FORMS MONTHLY NEWSLETTER

JOIN 1,100+ SUBSCRIBERS

  1. Don't miss out on updates
  2. The latest info from this site, Xamarin and the community
  3. Unsubscribe at any time*

* We use MailChimp, with double opt-in, and instant unsubscribe

Microsoft MVP | Xamarin MVP | Xamarin Certified Developer | Exrin MVVM Framework | Xamarin Forms Developer | Melbourne, Australia

Related Posts

6 Comments

    1. Adam Pedley

      RefreshData is just a placeholder that I used in my example. You will need to create it yourself to get a new version of the data and bind it to the list.

    1. Adam Pedley

      OnPropertyChanged can be written yourself or may be part of your MVVM framework. To ensure that updates from your ViewModel to your View are recognized, your ViewModel should inherit INotifyPropertyChanged.

      This will then create an event called PropertyChanged.

      Then you create a function, to call this event. e.g.

      public class BaseViewModel : INotifyPropertyChanged
      {
      public event PropertyChangedEventHandler PropertyChanged;

      public void OnPropertyChanged([CallerMemberName] string propertyName = “”)
      {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
      }