Search code examples
xamarinxamarin.iosasync-awaitcore-graphicscore-animation

Xamarin - Make rotations with CoreGraphics.CGAffineTransform


I want to make a UI Image rotate while content is downloading and I can't seem to make it rotate.

I have this event:

public override void ViewDidAppear(bool animated)
{
    NoConnectionView.Hidden = CheckConnectivityStatus();
    Task.Run(async () => await StartSpinningAnimation(true));
}

Which then fires this method:

protected async Task StartSpinningAnimation(bool IsSpinning) 
{
    do
    {
        UpdateActiveImage.Transform = CoreGraphics.CGAffineTransform.MakeRotation((float)Math.PI / 4);
    }
    while (IsSpinning);
    return;
}

The page will eventually change after files are downloaded so I just want it to spin forever. It does animate at all. Does anyone have any ideas?


Solution

  • Using C# and Xamarin.iOS to develop iOS is a letter bit different from the Native language, Whenever you want to invoke some UI element in your background thread(like you need make some UI do an animation), you must use:

    InvokeOnMainThread(delegate {
        //Do something related UI stuff
    });
    

    If you add a try catch for it, you will get the exception like that "You are calling a method that can only be invoked in UI thread";

    And by the way, you can not just use a do while to make an animation, I write a sample for you, you can take a look:

    public partial class ViewController : UIViewController
    {
        bool needAnimate = true;
        int count = 0;
        UIView animationView = new UIView();
    
        public ViewController (IntPtr handle) : base (handle)
        {
        }
    
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            // Perform any additional setup after loading the view, typically from a nib.
    
            animationView.Frame = new CoreGraphics.CGRect (50, 50, 100, 100);
            animationView.BackgroundColor = UIColor.Red;
            this.Add (animationView);
    
            this.View.AddGestureRecognizer (new UITapGestureRecognizer (() => {
                Task.Run(async () => await StartAnimation());
            }));
        }
    
        private async Task StartAnimation() 
        {
            do
            {
                Console.WriteLine ("count = " + count++);
                InvokeOnMainThread(delegate {
                    UIView.Animate(0.25,delegate {
                        animationView.Transform = CoreGraphics.CGAffineTransform.MakeRotation((float)Math.PI / 4 * (count/4 + 1));
                    });
                });
                System.Threading.Thread.Sleep(250);
            }
            while (needAnimate);
            return;
        }
    
        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
    }
    

    The animation is not smoothly, you need to optimize it yourself.

    If you still have some questions, just leave here, I will check it latter.

    Hope it can help you and welcome to Xamarin.