之前很喜欢收藏dribbble里面的一些动效gif,里面不仅是动效还是配色等等都非常的美,作为一个视觉动物,真的想把他们一个一个都实现出来,作为自己的一个作品,那真的是一件赏心悦目的事情,看着G20也快结束了,赶紧趁还闲着,先实现一个,我先挑选了一个比较简单的动效-----抽屉式效果列表
我们先来看下效果:
原来的动效地址找不到了...有知道的请留言给我...
代码地址:https://github.com/Yuzeyang/GCDrawerTableView
老样子,我们来分析下步骤
0x00 cell的处理
我们将cell
和详情界面
分开来处理,我们可以看到,当我们选中其中一个cell
的时候,该cell
会移动到列表上方的某一个位置,其他cell
则不显示,点击x
的时候,cell
返回为原位,其他cell
又重新显示
选中处理:首先是先将其他cell
隐藏,我们取出tableview
的可见cell
,然后将除了选中的cell
之外的透明度都设置为0
GCTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self.tableView bringSubviewToFront:cell];
for (UIView *subcell in tableView.visibleCells) {
if (subcell != cell) {
subcell.alpha = 0;
}
}
然后改变选中cell
的原点值,并且给cell
增加阴影,这里我偷懒没有做按钮的动画,只是用文字表示了按钮的状态
[UIView animateWithDuration:0.3 animations:^{
CGRect rect = self.frame;
self.originCellFrame = rect;
CGPoint origin = CGPointMake(0, contentOffsetY + 30);
rect.origin = origin;
self.frame = rect;
// 详情页处理
[self addShadowWithView:self];
[self addShadowWithView:self.detailView];
[self.detailButton setTitle:@"×" forState:UIControlStateNormal];
}];
由于cell
的动画处理是放在自定义cell
里面做的,所以在点击关闭的时候,需要在动画结束之后回调给视图控制器,所以这里就用了block来回调关闭的状态
- (void)deselectCell {
[UIView animateWithDuration:0.3 animations:^{
self.frame = self.originCellFrame;
self.layer.shadowColor = [UIColor clearColor].CGColor;
self.layer.shadowRadius = 0;
self.layer.shadowOpacity = 0.0;
// 详情页处理
[self.detailButton setTitle:@"..." forState:UIControlStateNormal];
} completion:^(BOOL finished) {
[self.helperHideView removeFromSuperview];
[self.detailView removeFromSuperview];
if (_deselectBlock) {
_deselectBlock();
}
}];
}
然后在试图控制器里面,将其他的cell
透明度改成1
[cell addDeselectBlock:^() {
for (UIView *subcell in tableView.visibleCells) {
if (subcell != cell) {
subcell.alpha = 1;
}
}
tableView.allowsSelection = YES;
tableView.scrollEnabled = YES;
}];
0x01 详情页
可以看到详情页
是类似于从上掉落的感觉,可能会联想到电商的那些筛选栏,但是筛选栏点击的时候,是上部分开始出现一直到下面,展示的顺序是反过来的,后面想了很久,只能想到利用视觉错误的效果,将详情页添加到cell
的下一层,然后cell
动画时候,详情页也做相应的动画,但是由于详情页的size
比cell
肯定是要大的,所以如果加到cell
下一层时,是遮挡不住的,所以就需要一个遮挡的view来遮住详情页
首先我们需要将cell
移到最前
[self.tableView bringSubviewToFront:cell];
然后在cell
的下一层加上遮挡视图
和详情页
,并根据cell
的origin做frame的变化
UIView *superview = self.superview;
CGFloat height = CGRectGetMinY(self.frame) - contentOffsetY + 30;
[self.helperHideView setFrame:CGRectMake(0, contentOffsetY, CGRectGetWidth(self.frame), height)];
[superview insertSubview:self.helperHideView belowSubview:self];
[self.detailView setFrame:CGRectMake(0, CGRectGetMaxY(self.frame) - (GCDeviceHeight - 100 - 30*2),
CGRectGetWidth(self.frame), GCDeviceHeight - 100 - 30*2)];
[superview insertSubview:self.detailView belowSubview:self.helperHideView];
[UIView animateWithDuration:0.3 animations:^{
// cell处理
CGRect rect2 = self.helperHideView.frame;
self.originHelperViewFrame = rect2;
CGPoint origin2 = CGPointMake(0, contentOffsetY + 30 - height);
rect2.origin = origin2;
self.helperHideView.frame = rect2;
CGRect rect1 = self.detailView.frame;
self.originDetailViewFrame = rect1;
CGPoint origin1 = CGPointMake(0, 100 + 30 + contentOffsetY);
rect1.origin = origin1;
self.detailView.frame = rect1;
[self addShadowWithView:self];
[self addShadowWithView:self.detailView];
[self.detailButton setTitle:@"×" forState:UIControlStateNormal];
}];
然后在关闭的时候,移除掉
- (void)deselectCell {
[UIView animateWithDuration:0.3 animations:^{
// cell处理
self.detailView.layer.shadowColor = [UIColor clearColor].CGColor;
self.detailView.layer.shadowRadius = 0;
self.detailView.layer.shadowOpacity = 0.0;
self.detailView.frame = self.originDetailViewFrame;
self.helperHideView.frame = self.originHelperViewFrame;
[self.detailButton setTitle:@"..." forState:UIControlStateNormal];
} completion:^(BOOL finished) {
[self.helperHideView removeFromSuperview];
[self.detailView removeFromSuperview];
if (_deselectBlock) {
_deselectBlock();
}
}];
}
这样就实现了抽屉式的效果,但是总感觉还有更好的办法实现,如果有思路的,欢迎交流~
网友评论