I have Portable project in Visual Studio 2015 with a ListView
that gets populated with some data via an API call through the following function refreshData
:
async Task refreshData()
{
myListView.BeginRefresh();
var apiCallResult = await App.Api.myApiGetCall();
myListView.ItemsSource = apiCallResult;
myListView.EndRefresh();
}
refreshData()
is called in
protected override void OnAppearing()
{
base.OnAppearing();
refreshData();
}
Everything is working fine except on Android where the refresh indicator is not stopping or disappearing on EndRefresh()
when the page is initially loaded. The page is in a TabbedPage
so I can go to a different tab and then return to this page and the refresh indicator properly starts and stops with completion of my API call.
Why is refresh is not stopping when the page initially loads on Android? Any help would be appreciated.
Note: This works perfectly fine when I run on iOS.
So far I've tried:
replacing myListView.BeginRefresh()
with myListView.IsRefreshing = true
and myListView.EndRefresh()
with myListView.IsRefreshing = false
Using Device.BeginInvokeOnMainThread(() => {//update list and endRefresh})
.
Using async void refreshData()
instead of async Task refreshData()
.
Pull to Refresh 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. When the user triggers a PullToRefresh the Command will be invoked the Refreshed event.
Now when you pull down from the top of the listview, it will show a refresh animation, while IsRefreshing=”true”. On each platform we can customize a small part of the refresh animation. Android uses the SwipeRefreshLayout control to display an animation while the ListView is being updated.
Alternatively, embedded resources are also a simpler solution to distribute the data files with an app. 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.
unfortunately your library is not compatible with Xamarin Forms unless you use ObservableCollection instead of BindingList, I wonder if this is possible ? Thanks Sir! Sorry, something went wrong.
Personally I can get this problem when I start ListView refreshing in the Page Contructor and stop it after the data is loaded. Sometimes (quite often) Xamarin.Forms ListView
doesn't cancel refreshing animation.
I believe you faced with a quite common issue with Android SwipeRefreshLayout
: it may not stop refreshing animation after setRefreshing(false)
called. Native Android developers use the following approach:
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(refreshing);
}
});
Interestingly, Xamarin.Forms uses this approach when it sets initial refreshing status (code); however, it is not enough. You need a custom renderer:
public class ExtendedListViewRenderer : ListViewRenderer
{
/// <summary>
/// The refresh layout that wraps the native ListView.
/// </summary>
private SwipeRefreshLayout _refreshLayout;
public ExtendedListViewRenderer(Android.Content.Context context) : base(context)
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_refreshLayout = null;
}
base.Dispose(disposing);
}
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
_refreshLayout = (SwipeRefreshLayout)Control.Parent;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == ListView.IsRefreshingProperty.PropertyName)
{
// Do not call base method: we are handling it manually
UpdateIsRefreshing();
return;
}
base.OnElementPropertyChanged(sender, e);
}
/// <summary>
/// Updates SwipeRefreshLayout animation status depending on the IsRefreshing Element
/// property.
/// </summary>
protected void UpdateIsRefreshing()
{
// I'm afraid this method can be called after the ListViewRenderer is disposed
// So let's create a new reference to the SwipeRefreshLayout instance
SwipeRefreshLayout refreshLayoutInstance = _refreshLayout;
if (refreshLayoutInstance == null)
{
return;
}
bool isRefreshing = Element.IsRefreshing;
refreshLayoutInstance.Post(() =>
{
refreshLayoutInstance.Refreshing = isRefreshing;
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With