仿猪来了转盘button的实现

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

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

写在前面

猪来了中转盘的按钮十分带感,有一种3D的效果,而实际上是伪3D,且实现起来十分容易,本篇文章就记录一下如何实现这个按钮的效果。

正文

首先解压猪来了的ipa包,从里面找出它的资源文件,然后发现了很多类似于下面的图片资源:

仿猪来了转盘button的实现_第1张图片

从这张图中我们可以很明显的看出这个按钮的实现方式,底座图片共有两张,大的那张放在下面,小的那张盖在button的上面,然后让button做上下的移动,然后就能做出类似的效果,下面是张效果图:

实现

由于本人文笔比较差,大家可以跳过我的介绍直接下载我的Demo
我这里还是简单说一下具体的代码实现:

首先重写View的两个方法,检测手指的按下和抬起,并用一个变量来记录Touch的状态


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

    self.touchState = TouchStatePress;
    [self playPressAnimationAndCallDelegate];

}

- (void)touchesEnded:(NSSet *)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];
}

其实很简单的代码,但是实现的效果却很赞!

(本文结束^_^)

你可能感兴趣的:(ios开发,button,3D)