"之前家里有事,回家了快7天,今天终于回来上班了…今天给大家讲解一下视觉差动画"
视觉差动画可能不太实用,但它能为你的App增加亮点,而且它对技术的要求十分简单,只是逻辑不好理解。 先放效果图:
让我们来分解它
首先我们得知道在这个View中的组成:
最底层的三个黑字Label加在一个View上
遮挡黑块View上放着另外三个白字Label.
没错,其实这个上面有每每两份重复的Label。
这就是这个视觉差动画的奥秘。
但是这样还不行,所有的最外层的Label会挡住底层Label,所以我们还需要view.clipsToBounds = YES;
下面讲解一下代码:
/**
* 最外层的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的位移,使它相对最底层的相对位置不动。
这样就完成了这个动画效果
如果你有更好的方法,欢迎一起讨论!
完整代码
好文推荐:iOS开发之详解连连支付集成