iOS开发之视觉差动画效果详解

WzxJiang

编辑:Bison
投稿:WzxJiang

"之前家里有事,回家了快7天,今天终于回来上班了…今天给大家讲解一下视觉差动画"


1

视觉差动画可能不太实用,但它能为你的App增加亮点,而且它对技术的要求十分简单,只是逻辑不好理解。 先放效果图:

1

让我们来分解它

首先我们得知道在这个View中的组成:

最底层的三个黑字Label加在一个View上

遮挡黑块View上放着另外三个白字Label.

没错,其实这个上面有每每两份重复的Label。

1

这就是这个视觉差动画的奥秘。

但是这样还不行,所有的最外层的Label会挡住底层Label,所以我们还需要view.clipsToBounds = YES;
1

下面讲解一下代码:


/**
*  最外层的View
*/
@property(nonatomic,strong) UIView * labelView;

/**
*  中间的View
*/
@property(nonatomic,strong) UIView * midView;

/**
*  单个格子的高度
*/
@property(nonatomic,assign) CGFloat  height;

初始化代码:

- (instancetype)initWithFrame:(CGRect)frame andTitleArr:(NSArray *)titleArr
{
    if (self == [super initWithFrame:frame])
    {
        self.backgroundColor = [UIColor whiteColor];

        _height = self.frame.size.height / titleArr.count;

        //添加最里层Label
        for (int i = 0;i < titleArr.count ; i++)
        {
        [self addSubview:[self returnLabel:titleArr[i] andFrame:CGRectMake(0, i*_height, self.frame.size.width, _height) andColor:[UIColor blackColor]]];
        }

        _midView = ({
            UIView * midView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width, _height)];
            midView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
            //设置不显示超出的部分
            midView.clipsToBounds = YES;
            midView.userInteractionEnabled = YES;
            midView;
        });

        [self addSubview:_midView];

        _labelView = ({
            UIView * labelView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, _midView.frame.size.width, _midView.frame.size.height)];
            for (int i = 0;i < titleArr.count ; i++)
            {
                [labelView addSubview:[self returnLabel:titleArr[i] andFrame:CGRectMake(0, i*_height, self.frame.size.width, _height) andColor:[UIColor whiteColor]]];
            }
                labelView;

        });

        [_midView addSubview:_labelView];

        //添加拖动手势
        UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [_midView addGestureRecognizer:pan];

    }
        return self;
}
//自定义一个快速创建Label的方法 避免重复代码
- (UILabel *)returnLabel:(NSString *)title andFrame:(CGRect)rect andColor:(UIColor *)color
{
    UILabel * label = [[UILabel alloc]initWithFrame:rect];
    label.font = [UIFont boldSystemFontOfSize:20];
    label.textColor = color;
    label.text = title;
    label.textAlignment = NSTextAlignmentCenter;
    return label;
}


拖动方法代码

-(void)pan:(UIPanGestureRecognizer *)sender
{
    CGPoint pt = [sender translationInView:self];

    CGPoint midCenter = _midView.center;
    CGPoint labelCenter = _labelView.center;

    midCenter.y += pt.y;
    labelCenter.y -= pt.y;

    //边界
    if (midCenter.y > self.frame.size.height - _height/2.0)
    {
        midCenter.y = self.frame.size.height - _height/2.0 ;
        labelCenter.y = -self.frame.size.height + _height*1.5;
    }
    if (midCenter.y < _height/2.0)
    {
        midCenter.y = _height/2.0 ;
        labelCenter.y = _height/2.0;
    }

    _midView.center = midCenter;
    _labelView.center = labelCenter;

    [sender setTranslation:CGPointZero inView:self];
}

拖动方法的难点在于,我们其实是希望_labelView对最底层的相对位置是不动的,但是要遮挡超出_midView的部分,那么肯定_labelView是加在_midView上的,midView.clipsToBounds = YES也是必须的,那我拖动_midView的时候,_labelView的位置也改动了,所以我们这里要

midCenter.y += pt.y;
labelCenter.y -= pt.y;


这样来弥补_labelView的位移,使它相对最底层的相对位置不动。

这样就完成了这个动画效果

如果你有更好的方法,欢迎一起讨论!
完整代码

GitHub,点我啊


博主app上线啦,快点此来围观吧

更多经验请点击

好文推荐:iOS开发之详解连连支付集成


分享文章