JazzHands + AutoLayout 基本使用

在上一篇文章中,我們已經(jīng)能用JazzHands做出一個(gè)完整的 Guide 動(dòng)畫了,但是這個(gè)動(dòng)畫還有一些不足.

  • 它是用 Frame 來布局的,在不同的機(jī)型上適配起來很麻煩

JazzHands 2.0已經(jīng)解決了這個(gè)問題
用 AutoLayout 來布局,用 IFTTTConstraintConstantAnimation 和 IFTTTConstraintMultiplierAnimation來做動(dòng)畫
使用起來代碼會復(fù)雜一些,但是對屏幕適配,屏幕旋轉(zhuǎn), iPad split-screen 支持的更好.

使用 IFTTTAnimatedPagingScrollViewController

IFTTTAnimatedPagingScrollViewController 內(nèi)部Override 下面這2個(gè)方法,結(jié)合 AutoLayout 完成適配.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration:

接下來我們使用AutoLayout 和 JazzHands做一個(gè)簡單的 透明度漸變動(dòng)畫.

創(chuàng)建一個(gè)空 ViewController 繼承 IFTTTAnimatedPagingScrollViewController
這是 JazzHands 提供給我們的方便結(jié)合使用 AutoLayout 制作動(dòng)畫的類,以后我們使用 AutoLayout 做動(dòng)畫直接繼承這個(gè)類就可以了,它已經(jīng)幫我們初始化好了 scrollView,contentView,Animator

在類擴(kuò)展中只需添加我們動(dòng)畫的 View

@interface JazzHandsPageViewControllerDemo ()
@property (strong,nonatomic) UIView  *v;
@end

在 ViewDidLoad 中

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.v=[UIView new];
    self.v.backgroundColor=[UIColor redColor];
    [self.contentView addSubview:self.v]; //注意添加 view到 contentView 中
    self.scrollView.showsHorizontalScrollIndicator=YES;
    self.scrollView.backgroundColor=[UIColor whiteColor];
    
    
    self.edgesForExtendedLayout = UIRectEdgeNone; //ios7以后 NavigationBar 會遮住內(nèi)容,加上這行保證內(nèi)容顯示在 navigationBar 下面,一般來說我們的 Guide 動(dòng)畫都是全屏的,不需要加這行
    [self.v mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.height.equalTo(@30); //固定 view 寬高為30
    }];
    
    [self keepView:self.v onPage:0]; //keepView 下面會說到
    
    IFTTTAlphaAnimation *alpha=[IFTTTAlphaAnimation animationWithView:self.v];
    [self.animator addAnimation:alpha];
    
    [alpha addKeyframeForTime:0 alpha:1];
    [alpha addKeyframeForTime:1 alpha:0]; //注意 time 是 1
}

運(yùn)行一下,效果如圖

JazzHands+AutoLayoutDemo.gif

上面的代碼和我們前2篇文章使用 Frame 布局制作動(dòng)畫類似,但有3點(diǎn)不同.

  1. 將 View 添加到了 contentView中.
  2. Masonry 給 view 布局
  3. addKeyframeForTime:1 time 是1.

關(guān)于第一點(diǎn) : 將 View 添加到了 contentView中.

引用一段 斯坦福大學(xué)公開課:iOS 7應(yīng)用開發(fā)

圖片較大 - scrollView.gif
圖片較大 - scrollView.gif

gif 中手機(jī)屏幕是全屏的 scrollView, 后面的圖片是 contentView, 我們將contentView 用scrollView.addsubView(contentView), 添加到 scrollView 中,再將其他所有需要展示的 View 添加到 contentView 中, scrollView 是為后面的 ContentView提供一個(gè)窗口
我們手指滑動(dòng)屏幕, scrollView.contentOffset.x 改變,我們能看到的 contentView 的內(nèi)容看起來跟著滾動(dòng)變化了,但實(shí)際上 contentView 的位置是固定的.

我們在繼承 IFTTTAnimatedPagingScrollViewController時(shí)contentView,scrollView 已經(jīng)被初始化好了,我們只需將需要展示的 view 添加到 self.contentView 中即可

關(guān)于第二點(diǎn)

既然我們使用 AutoLayout, 那么對 view 進(jìn)行布局,設(shè)置動(dòng)畫,就都要使用 AutoLayout, 這里使用 Mansonry 開源庫來設(shè)置約束.

關(guān)于第三點(diǎn) : addKeyframeForTime:1 time 是1.

之前我們使用 Frame

//創(chuàng)建一個(gè)透明度動(dòng)畫
    IFTTTAlphaAnimation *alpha=[IFTTTAlphaAnimation animationWithView:self.v];
    //將所有動(dòng)畫添加到 animator 中
    [self.animator addAnimation:alpha];

    //添加2個(gè)幀,在 scrollView 從 0 滾動(dòng)到 200 時(shí), 淡出我們的 View
    [alpha addKeyframeForTime:0 alpha:1.0];
    [alpha addKeyframeForTime:200 alpha:0.0];
    
    
    //scrollView 代理
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView{
        [self.animator animate:scrollView.contentOffset.x];
    }
}

現(xiàn)在我們使用 AutoLayout 和 IFTTTAnimatedPagingScrollViewController

    IFTTTAlphaAnimation *alpha=[IFTTTAlphaAnimation animationWithView:self.v];
    [self.animator addAnimation:alpha];
    
    [alpha addKeyframeForTime:0 alpha:1]; 
    [alpha addKeyframeForTime:1 alpha:0];

IFTTTAnimatedPagingScrollViewController內(nèi)部幫我們做了scrollView.contentOffset.xtime 的轉(zhuǎn)換
具體實(shí)現(xiàn)類似 :

    time = self.scrollView.contentOffset.x / self.pageWidth;

它將 contentOffset.x轉(zhuǎn)換為 頁面寬度的百分比,

    [alpha addKeyframeForTime:0 alpha:1];
    [alpha addKeyframeForTime:1 alpha:0];

所以這段代碼我們設(shè)置的動(dòng)畫是, scrollView 從第一頁滾動(dòng)到第二頁, view 的透明度從1變化到0

[keepView:onPage:]方法

如果你細(xì)心的話,可以發(fā)現(xiàn)上面的例子中,我們并沒有設(shè)置 x 軸的約束,但是紅色方塊的位置在 X 軸居中,
就是因?yàn)?code>[self keepView:self.v onPage:0];,這行代碼

我們寫一個(gè)例子來看看這個(gè)方法及其重載方法的作用,

新建一個(gè)空白 ViewController, 繼承自 IFTTTAnimatedPagingScrollViewController

類擴(kuò)展中

@interface JazzHandsKeepViewDemo ()
@property (strong,nonatomic) UIImageView *ifttt;
@end

ViewDidLoad 中

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.ifttt=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"IFTTTPresents"]];
    self.scrollView.backgroundColor=[UIColor greenColor];
    self.scrollView.showsHorizontalScrollIndicator=YES;
    [self.contentView addSubview:self.ifttt];
    
    self.edgesForExtendedLayout = UIRectEdgeNone;
    
    [self keepView:self.ifttt onPage:0]; 
}

我們還需要 Override 一個(gè)方法,告訴父類我們需要的頁數(shù)

-(NSUInteger)numberOfPages{
    return 4;
}

運(yùn)行一下,效果如圖

KeepViewDemo.gif

我們并沒有給 ITFFF imageView設(shè)置任何的動(dòng)畫和約束,但是它在 X軸居中,
就是因?yàn)槲覀冊O(shè)置了[self keepView:self.ifttt onPage:0];,讓 imageView 出現(xiàn)在第一頁,

我們繼續(xù)使用它的重載方法..

    [self keepView:self.ifttt onPages:@[@(0),@(1)]]; 

運(yùn)行結(jié)果如下..

KeepViewDemo_2.gif

注意看下面的 scrollIndicator, 即使我滑動(dòng)到第二頁,它還是保持在屏幕中間的位置,

繼續(xù)修改代碼為

    [self keepView:self.ifttt onPages:@[@(0),@(1)] atTimes:@[@(0),@(1)]];

這個(gè)運(yùn)行的結(jié)果和上面一樣,其實(shí)我們調(diào)用 [self keepView:self.ifttt onPages:@[@(0),@(1)]];時(shí),
內(nèi)部會調(diào)用它的重載方法
[self keepView:self.ifttt onPages:@[@(0),@(1)] atTimes:@[@(0),@(1)]];,
所以這2個(gè)方法的效果是一樣的

再次修改代碼,最后一次了...

    [self keepView:self.ifttt onPages:@[@(0),@(1.5)] atTimes:@[@(0),@(1)]]; 

運(yùn)行結(jié)果如下

KeepViewDemo_3.gif

這個(gè)運(yùn)行結(jié)果看起來有點(diǎn)詭異,
先來解釋這個(gè)方法,

[self keepView:self.ifttt onPages:@[@(0),@(1)] atTimes:@[@(0),@(1)]]; 

調(diào)用這個(gè)方法起到的效果是, ImageView 會保持在第一頁和第二頁的中間,
當(dāng)我們調(diào)用這個(gè)方法時(shí),內(nèi)部會給 imageView 和 contentView 添加一個(gè) X 軸的約束,讓 imageView 保持在頁面中間,
onPages:@[@(0),@(1)] 就代表保持在第一二頁的中間, atTimes:@[@(0),@(1)] 代表2個(gè)時(shí)間點(diǎn),

它內(nèi)部的實(shí)現(xiàn)是在 scrollView 滾動(dòng)時(shí),將 scrollView.contentOffset.x 累加給 imageView 和 contentView 的約束的 constant 上,也就是 scrollView 滾動(dòng)多少, imageView 也滾動(dòng)多少,所以產(chǎn)生的效果就是 imageView 一直保持在第一頁和第二頁的中間不動(dòng).

別忘了 JazzHands 是一個(gè)幀動(dòng)畫,所以我們設(shè)置參數(shù)的解釋就是,在 time=0時(shí), imageView 保持在第一頁中間, time=1時(shí), imageView 保持在第二頁中間,我們只需設(shè)置這2個(gè)關(guān)鍵幀,其余的 JazzHands 會幫我們搞定.

那么下面這個(gè)方法呢?..

[self keepView:self.ifttt onPages:@[@(0),@(1.5)] atTimes:@[@(0),@(1)]]; 

在 time=0時(shí), imageView 保持在第一頁中間,在 time=1時(shí), imageView 保持在第二頁中間 再偏離中間0.5倍的位置.

具體的實(shí)現(xiàn)是,現(xiàn)在 scrollView 滾動(dòng)10px, imageView 滾動(dòng) 15px, 所以從第一頁滾動(dòng)到第二頁的過程中,感覺 imageView 滾動(dòng)的距離比較長,滾動(dòng)的比較快.

所以[self keepView:self.ifttt onPages:@[@(0),@(1.5)] atTimes:@[@(0),@(1)]];這個(gè)方法不僅能將 view 保持在某一頁面出現(xiàn),調(diào)整參數(shù)后,還能制作 X 軸偏移的動(dòng)畫,所以后我們給 view設(shè)置約束時(shí),不用設(shè)置 X 軸的約束,只需調(diào)用此方法即可約束 view 的 X 軸位置.

明白了這點(diǎn)就可以無壓力的制作動(dòng)畫了..

Done

所有代碼你可以在 Github 中找到

下一篇 我們用 JazzHands+AutoLayout 來模仿 官方 Demo 的效果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容