IOS implementation of fragmented animation detailed _ios

Source: Internet
Author: User
Tags transparent color time 0

Fragmentation effect Diagram

Mask View

There is a Maskview attribute in the UIView, which is the most important variable we have today to implement animation. This property is used after iOS8 to represent the mask of the view. What is a mask? I have been thinking for a long time not to find the right analogy to introduce this. Simply put, an UIView object can be set alpha to change the transparency of the view, and the effect of the mask is the same. The only difference is that by modifying the value between 0~1, the transparency effect is changed, and the properties of the view object, such as the mask, affect the transparency of the backgroundColor alpha transform obscured view.

For example, the following code:

UIView * Viewcontainer = [[UIView alloc] Initwithframe:cgrectmake (0, 0, MB)];
Viewcontainer.backgroundcolor = [Uicolor bluecolor];

UIView * Contentview = [[UIView alloc] Initwithframe:cgrectmake (m, 160, 160)];
Contentview.backgroundcolor = [Uicolor redcolor];
[Viewcontainer Addsubview:contentview];

UIView * Maskview = [[UIView alloc] Initwithframe:cgrectmake (M, M,)];
Maskview.backgroundcolor = [Uicolor yellowcolor];
Contentview.maskview = Maskview;

The matte view determines what the view is displayed in

The above code changes a little, we change maskView the transparency of each contentView , and see what happens to the red view after the mask transparency changes:


Modify transparency. png

Through experiments we can see that the change in the transparency of the view itself or the transparency of the changes maskView achieved the same effect. In other words, the effect of masking a view on the view itself directly determines the two visual properties of transparency and display dimensions.

So what are the properties that obscure the view, in addition to the alpha attribute, that affect the display of the view itself?

Color

The transparency effect above draws a conclusion. The display of the view itself depends on the degree of transparency of the maskview. The view is not transparent when the color does not contain transparent space. But suppose we set the color transparency of the matte view:

Maskview.backgroundcolor = [Uicolor colorwithwhite:1 alpha:0.5]; Any color

The effect shown is the same as the direct setting alpha = 0.5 . The correlation between color rendering and Alpha properties can be learned on the drawing of pixels to the screen

Child view of Maskview

Maskview.backgroundcolor = [Uicolor clearcolor];
UIView * sub1 = [[UIView alloc] Initwithframe:cgrectmake (0, 0, M)];
Sub1.backgroundcolor = [Uicolor blackcolor];
UIView * Sub2 = [[UIView alloc] Initwithframe:cgrectmake (A, M,)];
Sub2.backgroundcolor = [Uicolor blackcolor];
[Maskview addsubview:sub1];
[Maskview ADDSUBVIEW:SUB2];

To understand maskView the effect of the child view on the mask effect, we need to exclude the mask view itself interference, so maskView the background color to be set to transparent color


Effects of child views on masks

As you can see, when the mask itself is transparent, the child view can also implement the effect of a partial matte view. So if we change the transparency of these child views, the mask effect will change as well.

Animation implementation

Back to the animation effect shown above, we can see that the image is divided into several rectangular pieces gradually disappear. The vertical direction is divided into two parts, and about 15 transverse. So we need to maskView add the 2*15 to the top now, evenly distribute the child view. In order to ensure that we can implement the hidden view of the child in the animation, we need to identify the child view:

UIView * Maskview = [[UIView alloc] initWithFrame:contentView.bounds];
Const Nsinteger Horizontalcount =;
Const Nsinteger Verticalcount = 2;
Const CGFloat fadewidth = cgrectgetwidth (maskview.frame)/horizontalcount;
Const CGFloat fadeheight = cgrectgetheight (maskview.frame)/verticalcount;

for (Nsinteger line = 0, line < Horizontalcount +) {for
  (nsinteger row = 0; row < Verticalcount; row++) {
    CGRect frame = CGRectMake (Line*fadewidth, Row*fadeheight, Fadewidth, fadeheight);
    UIView * Fadeview = [[UIView alloc] initwithframe:frame];
    Fadeview.tag = [self viewtag:line*verticalcount+row];
    Fadeview.backgroundcolor = [Uicolor whitecolor];
    [Maskview Addsubview:fadeview];
  }
Contentview.maskview = Maskview;

So at the beginning of the animation, we need to iterate through maskView all the child views above, and let them animate sequentially:

for (Nsinteger line = 0, line < Horizontalcount +) {for
  (nsinteger row = 0; row < Verticalcount; row++) {
    Nsinteger idx = line*verticalcount+row;
    UIView * Fadeview = [Contentview.maskview viewwithtag: [self viewwithtag:idx];
    [UIView animatewithduration:fadeduration delay:interval*idx options:uiviewanimationoptioncurvelinear animations: ^{
      fadeview.alpha = 0;
    } Completion:nil];
  }

We are implementing the animation at the same time, should consider how to wrap the animation to facilitate reuse later. The above fragmented animation can be encapsulated as a whole to UIView category reduce intrusion and achieve low coupling requirements:

#define LXDMAXDURATION 1.2 #define LXDMINDURATION. 2 #define lxdmultipled @interface UIView (lxdfadeanimation)/*!
* @brief View is hidden * * * @property (nonatomic, assign, ReadOnly) BOOL Isfade;
 /*!
* @brief is in the animation/@property (nonatomic, assign, ReadOnly) BOOL isfading;
 /*! * @brief the number of vertical squares.
The default is 3 */@property (nonatomic, assign) Nsinteger Verticalcount;
 /*! * @brief the number of horizontal squares.
The default is */@property (nonatomic, assign) Nsinteger Horizontalcount;
 /*! * @brief the interval between the 0.2~1.2 of the square animation.
Default 0.7 */@property (nonatomic, assign) Nstimeinterval intervalduration;
 /*! * @brief The animation time 0.05~0.3 per square, up to 25% of the length of the animation.

The default is 0.175 */@property (nonatomic, assign) Nstimeinterval fadeanimationduration; -(void) Configuratewithverticalcount: (Nsinteger) Verticalcount Horizontalcount: (nsinteger) Horizontalcount interval

: (nstimeinterval) Interval duration: (nstimeinterval) duration;
-(void) Reversewithcomplete: (void (^) (void)) complete;
-(void) Animatefadewithcomplete: (void (^) (void)) complete; -(void) ReversewithoutanimaTe @end

In iOS, all the property compilers declared in category are not automatically bound getter and setter methods, which means we need to rewrite both methods, and we can't access the variables directly with the underscore + variable name. So we need to import objc/runtime.h the file to objc_associateObject dynamically add properties to the view using the mechanism provided by the dynamic:

-(BOOL) Isfade
{return
  [Objc_getassociatedobject (Self, kisfadekey) boolvalue];
}  
Getassociatedobject method

-(void) Setisfade: (BOOL) isfade
{
  objc_setassociatedobject (self, Kisfadekey, @ (Isfade), objc_association_retain_nonatomic);
}
Other Setassociatedobject method

Animations with a fragmented hidden view also require a restore animation effect:

Nsinteger fadecount = Self.verticalcount * SELF.HORIZONTALCOUNT;
for (Nsinteger idx = fadeCount-1 idx >= 0; idx--) {
  UIView * subview = [Self.maskview viewwithtag: [Self subview TAG:IDX]];
  [UIView animateWithDuration:self.fadeAnimationDuration delay:self.intervalDuration * (fadeCount-1-idx) options:uivi Ewanimationoptioncurvelinear animations: ^{
    subview.alpha = 1;
  } Completion:nil];

Now we have to consider a problem: if the user clicks on a picture when the view is hidden from the state to start hiding/display of animation, when the user clicks repeatedly, we should determine whether the animation state, if it is, then do not continue to execute animation code. In addition, before the beginning of the animation, we need to set the status of the logo animation isFading YES , but because each block hidden there is an animation, animation end time How to judge it? fadeViewthe number of known is count , then when the last block is hidden that is the first count animation to complete, the entire fragmentation of the animation is over. So we need to use a temporary variable to record:

__block Nsinteger timecount = 0;
//......
[UIView animateWithDuration:self.fadeAnimationDuration delay:self.intervalDuration * (fadeCount-1-idx) options:uivi Ewanimationoptioncurvelinear animations: ^{
  subview.alpha = 1;
} completion: ^ (BOOL finished) {
  if (+ + Timecount = = fadecount) {
    self.isfade = NO;
    self.isfading = NO;
    if (complete) {complete ();}}}
];
//......

After we get the animation end time, we can add one to block provide the caller with additional processing at the end of the animation.

Carousel Fragmentation Animation

After I know the implementation of the fragment animation, I want to do a cool AD carousel page. The same category way to implement it. Now put the effect chart:


AD Carousel Page

So what steps do you need to implement an ad page carousel?

1. Insert a picture below the current animation UIImageView to show the next picture. If you can, try to reuse this.imageView

2, add UIPageControl to identify the image of the subscript

So I provided an interface to the array of images to perform the animation:

Gets the Uiimageview-(Uiimageview *) associatetempbannerwithimage for a temporary display of dynamic bindings
: (UIImage *) image
{
  Uiimageview * Tempbanner = Objc_getassociatedobject (self, ktempimagekey);
  if (!tempbanner) {
    Tempbanner = [[Uiimageview alloc] initWithFrame:self.frame];
    Objc_setassociatedobject (self, ktempimagekey, Tempbanner, objc_association_retain_nonatomic);
    [Self.superview Insertsubview:tempbanner belowsubview:self];
  }
  Tempbanner.image = image;
  return tempbanner;
}

In addition, at pageControl first I added to the top of the animation imageView , but when the animation is half done, pageControl it will also be hidden with the local hidden animation. Therefore, the imageView appropriate size range is recalculated according to the current coordinates:

-(void) Associatepagecontrolwithcurrentidx: (nsinteger) idx
{
  Uipagecontrol * Pagecontrol = objc_ Getassociatedobject (self, kpagecontrolkey);
  if (!pagecontrol) {
    Pagecontrol = [[Uipagecontrol alloc] Initwithframe:cgrectmake (self.frame.origin.x, Cgrectgetheight (self.frame)-Panax Notoginseng + SELF.FRAME.ORIGIN.Y, Cgrectgetwidth (self.frame), Panax Notoginseng)];
    [Self.superview Addsubview:pagecontrol];
    Pagecontrol.numberofpages = Self.bannerImages.count;
    Objc_setassociatedobject (self, kpagecontrolkey, Pagecontrol, objc_association_retain_nonatomic);
  Pagecontrol.currentpage = idx;
}

The same fragment animation code needs to be executed again every time the animation of the picture is completed. And the end of the animation is through block execution, that we need to nest in the block same one block , so first we need to declare this execution code as a block variable. In addition, a declaration is required to idx update the picture each time the fragment animation is completed, with a __block modification to let us modify the value in the callback:

-(void) Fadebanner Nsparameterassert (Self.superview);
  Uiimageview * Tempbanner = [self associatetempbannerwithimage: [UIImage imagenamed:self.bannerimages[1]]];
  Self.stop = NO;
  __block Nsinteger idx = 0;
  __weak typeof (self) weakself = self;

  [Self associatepagecontrolwithcurrentidx:idx];
    void (^complete) = ^{Nsinteger Updateindex = [weakself updateimagewithcurrentindex: ++idx Tempbanner:tempbanner];
    IDX = Updateindex;
  [Weakself Associatepagecontrolwithcurrentidx:idx];
  };
  Save block and perform animation objc_setassociatedobject (self, Kcompleteblockkey, complete, objc_association_copy_nonatomic);
    [Self Animatefadewithcomplete: ^{if (!self.stop) {complete ();
}
  }]; //update the displayed picture, and return to the next image to be displayed subscript-(Nsinteger) Updateimagewithcurrentindex: (nsinteger) idx Tempbanner: (Uiimageview *)
  Tempbanner {if (idx >= self.bannerImages.count) {idx = 0;}
  Self.image = [UIImage imagenamed:self.bannerimages[idx]];
  [Self reversewithoutanimate]; NsintegerNEXTIDX = idx + 1;
  if (Nextidx >= self.bannerImages.count) {nextidx = 0;}
  Tempbanner.image = [UIImage imagenamed:self.bannerimages[nextidx]]; [Self Animatefadewithcomplete: ^{if (!self.stop) {void (^complete) () = Objc_getassociatedobject (self, Kcomplet
      Eblockkey);
    Complete ();
  }
  }];
return idx; }

What you need to be aware of in the code is that the mechanism I used above objc_Associate saves the completion callback block , which is necessary. Let's say you don't like to encapsulate the code that updates the picture, put this step directly in the declaration above, and still keep it complete alive, otherwise the block execution to the third image fragment will be released to cause a crash.

Don't forget to restore all the child view masks after each picture switch is complete, and update the picture display

-(void) reversewithoutanimate
{
  if (self.isfading) {
    NSLog (@ "It ' s animating!");
    return;
  }
  For (UIView * Subview in self.maskView.subviews) {
    subview.alpha = 1;
  }
}

Summarize

This is all about the iOS implementation of the fragmented animation, I hope the content of this article will help you develop iOS animation.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.