图像不会以while循环Xamarin形式旋转

时间:2017-05-23 22:48:47

标签: c# xamarin xamarin.forms

我正在尝试在收集数据时实施定制的旋转加载轮。我目前面临的问题是,如果我在代码中的某个位置使activityImage.IsVisible为false,则轮子永远不会开始旋转。

我正在做的是将图像设置为可见true一旦我进入页面并收集数据直到数据被收集并且我将其设置为false然后带有图像的while循环应该停止旋转。

但是使用我当前的代码,图像变得可见并且看起来不可见,但图像不会旋转。

这就是我正在使用的:

收集数据:

public async void GetData ()
{
  var getData = await phpApi.getData(category);

  activityImage.IsVisible = true;
  loadLoadingWheel();

  foreach (var items in getData["results"])
  {
    ...gathering data    
  }
  activityImage.IsVisible = false; 
}

图像旋转功能:

async Task loadLoadingWheel()
{
    while (activityImage.isVisible)
    {
        await activityImage.RelRotateTo(500, 1000, Easing.SinOut);
    }
}

为什么车轮不旋转?如果我完全移除activityImage.IsVisible = false;轮子旋转但显然轮子没有被移除/一旦数据被收集就停止旋转。

1 个答案:

答案 0 :(得分:1)

从它看起来,您尝试在后台线程上更新UI。您只能更新主线程上的UI。我做了一些非常相似的事情,让我自己的动画发生。这非常笨拙,其他人可能有更好的解决方案。事实上,我会把钱投给有更好解决方案的人。这些内容可能适合您:

private CancellationTokenSource animateTimerCancellationTokenSource;

async void StartAnimationTimer(CancellationTokenSource tokenSource)
{
    try
    {
        //maintain a reference to the token so we can cancel when needed
        animateTimerCancellationTokenSource = tokenSource;

        int idleTime = 1000; //ms

        await Task.Delay(TimeSpan.FromMilliseconds(idleTime), tokenSource.Token);

        //Do something here
        Device.BeginInvokeOnMainThread(() =>
        {
            if (activityImage.isVisible)
            {
                activityImage.RelRotateTo(500, 1000, Easing.SinOut);

                //Do this if you want to have it possibly happen again
                StartAnimationTimer(new CancellationTokenSource());
            }
        });
    }
    catch (TaskCanceledException ex)
    {
        //if we cancel/reset, this catch block gets called
        Debug.WriteLine(ex);
    }
    // if we reach here, this timer has stopped
}

要取消动画再次发生,您可以运行此功能。

if (animateTimerCancellationTokenSource != null)
{
    animateTimerCancellationTokenSource.Cancel();
    animateTimerCancellationTokenSource.Dispose();
    animateTimerCancellationTokenSource = null;
}

这里的关键是这个人:Device.BeginInvokeOnMainThread(() => { });

您需要在主线程上完成所有UI工作。这允许您从后台线程调用主线程上的东西,这是您async方法正在使用的方法。

所以你最终会得到这个

public async void GetData ()
{
    var getData = await phpApi.getData(category);

    activityImage.IsVisible = true;
    StartAnimationTimer(new CancellationTokenSource());

    foreach (var items in getData["results"])
    {
        ...gathering data    
    }
    activityImage.IsVisible = false;

    if (animateTimerCancellationTokenSource != null)
    {
        animateTimerCancellationTokenSource.Cancel();
        animateTimerCancellationTokenSource.Dispose();
        animateTimerCancellationTokenSource = null;
    }
}