Search code examples
objective-cios5animationobjective-c-blocksuiswipegesturerecognizer

Why does my UIView get distorted on animation?


I am developing an iPad app that uses a swipe gesture to move between months on a calendar. The animation style is fine and the app shows the correct screen before and after my animation. However, during the animation, there are two problems:

-The original view gets distorted or blurred.
-The original month (September) is shown 'on the next page' instead of the next month (October) during the animation.

I had a job to catch a screenshot of this but if you look at the top left corner on the shot from the animation you can see the problem. It looks like all the text has become bold. Here are the images, followed by the code.

Before the animation:

Before the animation http://i1219.photobucket.com/albums/dd427/Dave_Chambers/1-2.png

During the animation:

During the animation

If you look at the 'K-SUPER...' top left, you can see that the text is thicker, due to the distortion caused by the animation.

After the animation:

After the animation

Anybody know how I can solve this so I see September before, October underneath DURING the animation and October afterwards?

The code:

    - (void)swipedInLeftDirection:(UISwipeGestureRecognizer *)sender {
NSLog(@"UserActions: %s", __PRETTY_FUNCTION__);

[MonthlyEventView animateWithDuration:1.0
                 animations:^{
                         [MonthlyEventView setAnimationTransition: UIViewAnimationTransitionCurlUp forView:self cache:NO];
                 }
                 completion:^(BOOL finished) {

                     NSDateComponents* plusOneMonth = [[NSDateComponents alloc] init];
                     [plusOneMonth setMonth:1];
                     NSDate* oneMonthForward = [[NSCalendar currentCalendar] dateByAddingComponents:plusOneMonth toDate:self.selectedDate options:0];
                     [self.delegate monthlyView:self userDidPerformSwipeInDirection:UISwipeGestureRecognizerDirectionLeft andExpectingDateToBeSelected:oneMonthForward];

                 }];

}

For what it's worth, the view size is 704 x 569. Perhaps this matters, I don't know.

Thanks in advance for any solution.


Solution

  • Your text distortion is due to drawing to labels at almost exactly the same location, the almost due to the animation, creating sort of a bold effect. The easiest solution would be to simply have your calendar view be opaque. i.e. set a background color of [UIColor lightGrayColor] for the whole view. This would also make it so the back of the curled page would appear solid gray, as one would expect of gray paper.

    Also about why the old month appeared underneath the animation. The mechanism of the UIView transitions is to essentially capture the current appearance of the view, then render what it should look like after the animation, and then animate that original capture off screen. The completion block is called after all of this has happened. So essentially you animate from the state you are in to the state you are in and then set the calendar to a new date. So as odd as it may sound setting the calendar's date is part of the animation.

    Also there is a more direct block based API for this.

    [UIView transitionWithView:self // since this code is in the view's implementation.
                      duration:0.8
                       options:UIViewAnimationOptionTransitionCurlUp
                    animations:^{
                        NSDateComponents* plusOneMonth = [[NSDateComponents alloc] init];
                        [plusOneMonth setMonth:1];
                        NSDate* oneMonthForward = [[NSCalendar currentCalendar] dateByAddingComponents:plusOneMonth toDate:self.selectedDate options:0];
                        [self.delegate monthlyView:self userDidPerformSwipeInDirection:UISwipeGestureRecognizerDirectionLeft andExpectingDateToBeSelected:oneMonthForward];
                    }
                    completion:^(BOOL b){
                        // If you need notification when the animation completes put a callback here.
                    }];