仿豬來了轉盤button的實現

作者:代培
地址:http://daipei.me/posts/imitate_button_in_pigcoming/

我的博客已經搬家了^_^,我的新博客地址:daipei.me

寫在前面

豬來了中轉盤的按鈕十分帶感,有一種3D的效果,而實際上是僞3D,且實現起來十分容易,本篇文章就記錄一下如何實現這個按鈕的效果。

正文

首先解壓豬來了的ipa包,從裏面找出它的資源文件,然後發現了很多類似於下面的圖片資源:

這裏寫圖片描述

從這張圖中我們可以很明顯的看出這個按鈕的實現方式,底座圖片共有兩張,大的那張放在下面,小的那張蓋在button的上面,然後讓button做上下的移動,然後就能做出類似的效果,下面是張效果圖:

這裏寫圖片描述

實現

由於本人文筆比較差,大家可以跳過我的介紹直接下載我的Demo
我這裏還是簡單說一下具體的代碼實現:

首先重寫View的兩個方法,檢測手指的按下和擡起,並用一個變量來記錄Touch的狀態


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {

    self.touchState = TouchStatePress;
    [self playPressAnimationAndCallDelegate];

}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {

    self.touchState = TouchStateFree;
    [self playFreeAnimationAndCallDelegate];

}

然後我們看一下核心的兩個方法playPressAnimationAndCallDelegateplayFreeAnimationAndCallDelegate,這裏只分析第一個方法。開始先判斷當前是否有動畫在進行,如果是直接返回。然後判斷當前轉盤的狀態,如果是free狀態,則播放完全按下的動畫,在動畫結束的回掉中,更新button的狀態,此時要注意的是去檢查Touch的狀態,如果如果是鬆開的狀態,那還要去調用playFreeAnimationAndCallDelegate,在動畫block外,根據轉盤的狀態決定是否通知代理。


- (void)playPressAnimationAndCallDelegate {
    if (self.animated) {
        return ;
    }
    self.animated = YES;
    CGFloat height = self.frame.size.height;
    if (self.spinState == SpinStateFree) {
        [UIView animateWithDuration:0.08 animations:^{
            self.button.frame = CGRectMake(0, height / 16, self.button.frame.size.width, self.button.frame.size.height);
        } completion:^(BOOL finished) {
            self.button.frame = CGRectMake(0, height / 16, self.button.frame.size.width, self.button.frame.size.height);
            self.animated = NO;
            self.buttonState = ButtonStateLow;
            if (self.touchState == TouchStateFree) {
                [self playFreeAnimationAndCallDelegate];
            }
        }];
    }else if (self.spinState == SpinStateBusy) {
        [UIView animateWithDuration:0.05 animations:^{
            self.button.frame = CGRectMake(0, height / 60, self.button.frame.size.width, self.button.frame.size.height);
        } completion:^(BOOL finished) {
            self.button.frame = CGRectMake(0, height / 60, self.button.frame.size.width, self.button.frame.size.height);
            self.animated = NO;
            self.buttonState = ButtonStateMid;
            if (self.touchState == TouchStateFree) {
                [self playFreeAnimationAndCallDelegate];
            }
        }];
    }
    if (self.spinState == SpinStateFree) {
        if (self.delegate && [self.delegate respondsToSelector:@selector(giftSpinButtonDidPress:)]) {
            [self.delegate giftSpinButtonDidPress:self];
        }
    }
}

最後我們看一下唯一的一個接口的實現,首先記錄轉盤的狀態,這裏要注意如果轉盤狀態變爲free而button是被按下的,我們要再次播放動畫並通知代理(這裏應對的情況是如果能一直按着這個按鈕,當轉盤停下來時是會繼續轉的)。


- (void)spinStateChangeTo:(SpinState)state {
    self.spinState = state;
    if (state == SpinStateFree && self.touchState == TouchStatePress) {
        if (self.buttonState == ButtonStateMid) {
            [self playPressAnimationAndCallDelegate];
        } else if (self.buttonState == ButtonStateLow) {
            if (self.delegate && [self.delegate respondsToSelector:@selector(giftSpinButtonDidPress:)]) {
                [self.delegate giftSpinButtonDidPress:self];
            }
        }
    }
}

使用

說完實現,說一下這個View該如果使用。在VC中實例化這個View,並將其代理設爲這個VC,這裏要注意的一點是一般情況下是要在-giftSpinButtonDidPress:的代理方法中調用spinStateChangeTo:方法的,因爲按下後轉盤轉起來按鈕就按不下去了。


- (void)giftSpinButtonDidPress:(DPSpinButton *)giftSpinButton {

    ...

    [giftSpinButton spinStateChangeTo:SpinStateBusy];
}

其實很簡單的代碼,但是實現的效果卻很贊!

(本文結束^_^)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章