我在Visual Studio 2015中有一个带有<div class="col-md-6" style="background-color: lightblue;display: flex;align-items: center;">
的Portable项目,通过以下函数ListView
通过API调用填充了一些数据:
refreshData
async Task refreshData()
{
myListView.BeginRefresh();
var apiCallResult = await App.Api.myApiGetCall();
myListView.ItemsSource = apiCallResult;
myListView.EndRefresh();
}
在
refreshData()
一切正常,但在Android上,当初始加载页面时,刷新指示器没有停止或消失在protected override void OnAppearing()
{
base.OnAppearing();
refreshData();
}
上。该页面位于EndRefresh()
中,因此我可以转到另一个标签页然后返回此页面,并在完成API调用后正确启动和停止刷新指示符。
为什么在Android最初加载页面时刷新不会停止?任何帮助将不胜感激。
注意:当我在iOS上运行时,此功能完全正常。
到目前为止,我已尝试过:
将TabbedPage
替换为myListView.BeginRefresh()
,将myListView.IsRefreshing = true
替换为myListView.EndRefresh()
使用myListView.IsRefreshing = false
。
使用Device.BeginInvokeOnMainThread(() => {//update list and endRefresh})
代替async void refreshData()
。
答案 0 :(得分:2)
试试这个:
async void refreshData()
{
Device.BeginInvokeOnMainThread(() => {
myListView.BeginRefresh();
var apiCallResult = await App.Api.myApiGetCall();
myListView.ItemsSource = apiCallResult;
myListView.EndRefresh();
});
}
显然,不需要&#34;任务&#34;了。
如果只在Android中出现错误,那么它可能只是Android处理线程的方式。它不允许线程直接更改可视元素。有时,当我们尝试这样做时,它会抛出一个无声的异常,代码操作没有实际效果。
答案 1 :(得分:1)
个人而言,在 Page Contructor 中启动ListView刷新并在加载数据后将其停止时,我会遇到此问题。有时(经常)Xamarin.Forms ListView
不会取消刷新动画。
我相信您在Android SwipeRefreshLayout
上遇到了一个非常普遍的问题:调用setRefreshing(false)
之后,它可能不会停止刷新动画。本机Android开发人员使用以下方法:
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(refreshing);
}
});
有趣的是,Xamarin.Forms在设置初始刷新状态(code)时会使用此方法;但是,这还不够。您需要一个自定义渲染器:
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;
});
}
}
答案 2 :(得分:0)
您需要遵循MVVM模式
在ViewModel上,您需要:
INotifyPropertyChanged
定义以下属性:
private bool _IsRefreshing;
public bool IsRefreshing
{
get{return _IsRefreshing;}
set{SetProperty(ref _IsRefreshing, value;} /*So every time the property changes the view is notified*/
}
定义获取数据的方法,在您的情况下refreshData()
在您的网页上,您需要:
SetPropertyValue
将ListView.IsRefreshing绑定到ViewModel的IsRefresging:
MyListView.SetBinding<MyViewModel>(ListView.IsRefreshing, vm => vm.IsRefresging);
Here是一篇很棒的文章,讨论了INotifyPropertyChanged