ios開發——仿新版iBooks書本開啟與關閉動畫,iosibooks

來源:互聯網
上載者:User

ios開發——仿新版iBooks書本開啟與關閉動畫,iosibooks

IOS新版iBooks迷人的地方除了有乾淨整潔的介面、方便靈活的操作以及大容量的書籍容量以外,還有其優秀的使用者互動,尤其是其動畫的使用。開啟一本書時書本緩慢放大並開啟,關閉一本書後書本關閉並回到原位置。現在我們來實現這個簡單的功能。




用到的知識:

1、CAKeyframeAnimation的應用

2、如何在代理中區分兩個不同的動畫

3、座標系轉換


思路:

這個動畫主要用到的是CAAnimation,並且是CAKeyframeAnimation,當使用者點擊書本時,設定一個UIImageView(為其加上tag方便以後取)並將其放在選中書本的位置上(使用座標系轉換),接著通過動畫將其放大到全屏,完成後將其錨點設定為(0,0.5)並讓其繞y軸選中π/2角度,將早已放在下面的textView(本app中是自訂的readView)展示出來。動畫完成後將UIImageView的透明度設為0。這樣就是書本的開啟過程。關閉過程類似,根據tag取出UIImageView並將其旋轉,然後設定frame到原來書本的位置(可以用私人變數記錄該位置),最後removeFromSuperview即可。


代碼:

首先是“準備階段”

    //BookReadView是展示textView和頂部底部附加view的自訂view    CYZBookItemView *itemView = [notification object];    CYZBookReadView *readView = [[CYZBookReadView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height) ItemView:itemView];    //設定delegate是為了當使用者從閱讀介面返回時做出響應    readView.delegate = self;    //先將其alpha設為0防止使用者剛點擊書本動畫還在進行中時就出現這一介面    readView.alpha = 0.0f;    [self.view addSubview:readView];        //展示動畫的UIImageView    UIImageView *showView = [[UIImageView alloc] initWithImage:itemView.bookImage.currentBackgroundImage];    //座標系轉換    _itemPosition = [itemView.superview convertRect:itemView.frame toView:self.view];    showView.frame = _itemPosition;    //設定tag方便以後取出    showView.tag = 1001;    showView.backgroundColor = [UIColor clearColor];    [self.view addSubview:showView];

關於座標系轉換(以矩形為例,point類似):


- (void)convertRect:toView:方法:

格式[被轉換者所在的View convertRect:被轉換者的frame或bounds toView:轉換到的View];返回在目標View中的rect

例如,將當前視圖的子視圖viewA中的一個imageView轉換到當前視圖。可以如下調用:

[viewA convertRect:viewA.imageView.frame toRect:self.view];

或者[imageView.superView convertRect:imageView.frame toRect:self.view];

其中self指控制器。


- (void)convertRect:fromView:方法:

格式[要轉換到的View convertRect:被轉換者的frame或bounds fromView:被轉換者所在的View];返回在目標View中的rect。

還是上一個例子,可以這樣寫:

[self.view convertRect:viewA.imageView.frame fromView:viewA];

或者[self.view convertRect:imageView.frame fromView:imageView.superView];

其中self指控制器


接著準備工作完成了以後就可以開始動畫了。一下是開啟動畫的部分

    [UIView animateWithDuration:0.5f animations:^{        //將UIImageView放大為全屏        showView.frame = self.view.bounds;    } completion:^(BOOL finished) {        if (finished) {            //展示出readView            readView.alpha = 1.0f;                        //設定錨點            showView.layer.anchorPoint = CGPointMake(0, 0.5);#warning 不知道為什麼,不加下面這句話showView會顯示異常:即只顯示一半            showView.frame = CGRectMake(0, 0, showView.width, showView.height);            CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];            //設定其繞y軸旋轉            animation.keyPath = @"transform.rotation.y";            //設定期間,可以定義一常量來表示            animation.duration = 0.5f;            animation.speed = 0.55f;            animation.removedOnCompletion = NO;            //旋轉π/2度            [animation setValues:[NSArray arrayWithObjects:@0.0f, @-M_PI_2, nil]];            //設定代理便於回調            animation.delegate = self;            //這裡必須設定上key,為了接下來區分不同動畫            [showView.layer addAnimation:animation forKey:@"rotateToOpenBook"];        }    }];

代碼中注釋已經解釋得比較詳細了,只不過正如warning寫得那樣,本來我是用showView.layer.transform來實現動畫的,這樣會省很多事,比如不用在代理中區分動畫、不用記錄position來在方法間傳值等,不過不知道為什麼showView總是只顯示一半,求解釋╮(╯▽╰)╭


回調中:

[showView setAlpha:0.0f];

將其暫時隱藏,關上書時還要用它。


關上書的動畫大致類似

#pragma mark - CYZBookViewDelegate- (void)readViewDidBackWithItem:(CYZBookItemView *)item{    //取出showView    UIImageView *showView = (UIImageView *)[self.view viewWithTag:1001];    //將其顯示出來    showView.alpha = 1.0f;    showView.layer.anchorPoint = CGPointMake(0, 0.5f);    showView.frame = CGRectMake(0, 0, showView.width, showView.height);        CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];    animation.keyPath = @"transform.rotation.y";    animation.duration = 0.5f;    animation.speed = 0.55f;    animation.removedOnCompletion = NO;    //反向旋轉    [animation setValues:[NSArray arrayWithObjects:@-M_PI_2, @0, nil]];    animation.delegate = self;    //設定不同的key為了區分動畫用    [showView.layer addAnimation:animation forKey:@"rotateToCloseBook"];    }

這裡要用一個不同的key來表示這個動畫。

該動畫的回調:

            [UIView animateWithDuration:0.5f animations:^{                showView.frame = _itemPosition;            } completion:^(BOOL finished) {                [showView removeFromSuperview];            }];

_itemPosition是之前用來記錄轉換的座標的私人變數,這幾行代碼的意思就是讓showView回到書本的位置然後令其消失。

這裡的關鍵問題在於,兩個動畫都用到了回調,如何區分呢?就用我們之前設定的key來區分:

回調的完整代碼:

#pragma mark - AnimationDelegate- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{    UIImageView *showView = (UIImageView *)[self.view viewWithTag:1001];    if (flag) {        if (showView && [[showView.layer animationForKey:@"rotateToOpenBook"] isEqual:anim]) {            [showView setAlpha:0.0f];        } else if (showView && [anim isEqual:[showView.layer animationForKey:@"rotateToCloseBook"]]) {            [UIView animateWithDuration:0.5f animations:^{                showView.frame = _itemPosition;            } completion:^(BOOL finished) {                [showView removeFromSuperview];            }];        }    }}
通過showView所在層layer的方法 animationForKey:獲得自己設定的動畫,與代理中的anim做比較即可區分。

另外,在stackOverflow上還看到一種方法:用kvc的方法為animation設值,並在代理中通過kvc的方法根據這個鍵取出值並進行判斷,應該也是可以的。



ibooks圖書封面


歡迎一起交流。


 
ibooks 裡開啟書總是自動彈回案頭

首先要確認IBOOKS軟體正常使用不會自己退出(重裝一下或直接裝別的看書軟體),再把檔案傳進去嘛。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.