你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 《Motion Design for iOS》(四十二)

《Motion Design for iOS》(四十二)

編輯:IOS開發綜合

構建立即響應的按鈕

你玩過Loren Brichter的游戲Letterpress嗎?我很喜歡的Loren構建的一個關於界面的東西可能不是每個人都明顯喜歡的:我喜歡每個按鈕在用戶按下時立即切換到一個不同的狀態的樣子。絕對不會延遲。這不是一個簡單實現的行為,因為即使你可以將一個圖片設為UIButton的UIControlStateHighlighted狀態圖,它也只會在點擊發生後一小會啟動,而且它不允許更進一步的代碼來運行它。如果我想要在用戶點擊一個UIButton後立即運行一個動畫,我就不得不自己寫一個簡單的自定義按鈕類。但首先,先來看一看我們要構建的是什麼。


\


如果我想要在用戶點擊後立即運行代碼,我就不得不自己寫一個好的UIButton子類,這樣我就可以重寫一些方法,即 -touchesBegan:withEvent: 和 -touchesEnded:withEvent:。iOS中的每個界面的控制都從UIResponder繼承了這些方法,它是一個處理所有觸摸控制事件的父類。有了子類,我就可以塞一些自己的代碼來在這些方法啟動的時候運行。來看看DTCTestButton的實現文件,這是我們的按鈕子類,會為我們處理一些魔法。

#import "DTCTestButton.h"
#import "POP.h"

@implementation DTCTestButton

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    // 自定義一些按鈕第一次被點擊時要運行的代碼

    [super touchesBegan:touches withEvent:event];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // 自定義一些按鈕不再被點擊時要運行的代碼

    [super touchesEnded:touches withEvent:event];
}

@end

我們這裡只定義了兩個方法,我們想要將我們的代碼放到這些方法裡面去。當子類化一個蘋果提供的對象,比如UIButton時,做一個好的城市居民並確保調用super的關於這些方法的實現是很重要的,因為我們不知道蘋果在這兩個方法中需要運行什麼代碼,而且不想破壞按鈕的默認行為。我們調用super後,就可以在這兩個方法中添加任何我們想要的行為。

讓我們添加一個Pop動畫到 -touchesBegan:withEvent:中去。

POPSpringAnimation *scale = [self pop_animationForKey:@"scale"];

if (scale) {
    scale.toValue = [NSValue valueWithCGPoint:CGPointMake(0.8, 0.8)];
} else {
    scale = [POPSpringAnimation animationWithPropertyNamed:kPOPViewScaleXY];
    scale.toValue = [NSValue valueWithCGPoint:CGPointMake(0.8, 0.8)];
    scale.springBounciness = 20;
    scale.springSpeed = 18.0f;
    [self pop_addAnimation:scale forKey:@"scale"];
}

這和我們之前寫的Pop代碼有點不同。當使用Pop來構建好的響應動畫去關聯觸摸動作時,一個聰明的做法是看看是否已經有一個Pop動畫關聯到這個視圖或者layer了。如果有,只要更新已經存在的動畫的toValue屬性就可以了。Pop知道當前的值是什麼並且已經設置好彈性和速度變量了,所以你不用做任何其他的事情。這避免了添加另一個錯誤的Pop動畫來操作同樣的值(在這個例子中,是kPOPViewScaleXY),這會造成愚蠢的結果。通過使用現存的動畫,Pop可以優雅地從它的當前位置修改到你設置的新的toValue並進行一個漂亮、平滑的過度。這也是為什麼Pop動畫有一個名字:這樣你就可以通過給出你之前設置的動畫的名字來詢問視圖或者layer它們是否有已經添加進去的Pop動畫並獲取到動畫對象。

如果動畫不是已經存在,我們就和平常一樣創建一個新的Pop動畫對象,設置彈簧的動作屬性,比如彈性,設置toValue,然後添加動畫到視圖或者layer上。在這個例子中,我們動畫了視圖的尺寸,所以我們將動畫添加到視圖上。

現在讓我們在觸摸事件結束時做同樣的事情。這次代碼放在 -touchesEnded:withEvent:中。

POPSpringAnimation *scale = [self pop_animationForKey:@"scale"];

if (scale) {
    scale.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)];
} else {
    scale = [POPSpringAnimation animationWithPropertyNamed:kPOPViewScaleXY];
    scale.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)];
    scale.springBounciness = 20;
    scale.springSpeed = 18.0f;
    [self pop_addAnimation:scale forKey:@"scale"];
}

如果你看看觸摸事件開始時0.8的toValue以及觸摸結束時的1.0的toValue,你就可以猜到整個動畫會在用戶點擊按鈕時稍微收縮按鈕的尺寸,然後會在他們停止觸摸時彈回完整的尺寸。完全正確!這裡是它現在的樣子。


\


很有意思!讓我們再加一點點旋轉動畫來增色。它基本上和我們已經添加的代碼一樣,只是重復它,修改動畫類型,然後改變toValue值。這裡是完整的代碼,以及一些注釋。

// 當用戶開始點擊時立即調用
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {    
    // 看動畫是否已經被添加到視圖或者layer上
    POPSpringAnimation *scale = [self pop_animationForKey:@"scale"];
    POPSpringAnimation *rotate = [self.layer pop_animationForKey:@"rotate"];

    // 如果scale動畫已經存在,就設置toValue
    if (scale) {
        scale.toValue = [NSValue valueWithCGPoint:CGPointMake(0.8, 0.8)];
    } else {
        // 如果不存在,就創建並添加它
        scale = [POPSpringAnimation animationWithPropertyNamed:kPOPViewScaleXY];
        scale.toValue = [NSValue valueWithCGPoint:CGPointMake(0.8, 0.8)];
        scale.springBounciness = 20;
        scale.springSpeed = 18.0f;
        [self pop_addAnimation:scale forKey:@"scale"];
    }

    // 如果旋轉動畫已經存在,就設置toValue
    if (rotate) {
        rotate.toValue = @(M_PI/6); // 旋轉到1/6th π角度
    } else {
        // 旋轉動畫時layer上的,所以我們添加到layer上去
        rotate = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
        rotate.toValue = @(M_PI/6);
        rotate.springBounciness = 20;
        rotate.springSpeed = 18.0f;

        // 添加到layer上,而不是view
        [self.layer pop_addAnimation:rotate forKey:@"rotate"];
    }

    [super touchesBegan:touches withEvent:event];
}

// 在用戶離開手指時立即調用
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // 看動畫是否存在(由於這是用戶離開時,基本是已經存在的)
    POPSpringAnimation *scale = [self pop_animationForKey:@"scale"];
    POPSpringAnimation *rotate = [self pop_animationForKey:@"rotate"];

    if (scale) {
        // 拉伸回1.0的完整尺寸
        scale.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)];
    } else {
        scale = [POPSpringAnimation animationWithPropertyNamed:kPOPViewScaleXY];
        scale.toValue = [NSValue valueWithCGPoint:CGPointMake(1.0, 1.0)];
        scale.springBounciness = 20;
        scale.springSpeed = 18.0f;
        [self pop_addAnimation:scale forKey:@"scale"];
    }

    if (rotate) {
        // 旋轉回0角度的初始位置
        rotate.toValue = @(0);
    } else {
        rotate = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerRotation];
        rotate.toValue = @(0);
        rotate.springBounciness = 20;
        rotate.springSpeed = 18.0f;

        // 再次確保添加你的layer動畫到layer上去。我曾經失誤過很多次,這會導致一個有趣的bug :)
        [self.layer pop_addAnimation:rotate forKey:@"rotate"];
    }

    [super touchesEnded:touches withEvent:event];
}

動畫代碼是重復的。簡單,但是重復。它的一個缺點是需要很多行代碼來完整構建你的動畫,但優點是能讓你練習寫很多動畫代碼,所以我認為你可以學的更快。

再一次,這裡是我們構建的最終動畫。它是一個很有趣的效果,會在用戶點擊按鈕時立即啟動,它會讓你的界面感覺響應很快。這裡的彈性效果很顯著,所以當添加動畫到你的真實app界面時,去使用一會app的動畫,並確保它們的速度和動作時合適且不分散注意力的。


\


現在讓我們來用Pop做一些有趣的東西!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved