之前很喜欢收藏dribbble里面的一些动效gif,里面不仅是动效还是配色等等都非常的美,作为一个视觉动物,真的想把他们一个一个都实现出来,作为自己的一个作品,那真的是一件赏心悦目的事情,看着G20也快结束了,赶紧趁还闲着,先实现一个,我先挑选了一个比较简单的动效—–抽屉式效果列表
我们先来看下效果:
原来的动效地址找不到了…有知道的请留言给我…
代码地址:https://github.com/Yuzeyang/GCDrawerTableView
老样子,我们来分析下步骤
0x00 cell的处理
我们将cell
和详情界面
分开来处理
我们可以看到,当我们选中其中一个cell
的时候,该cell
会移动到列表上方的某一个位置,其他cell
则不显示,点击x
的时候,cell
返回为原位,其他cell
又重新显示
选中处理:首先是先将其他cell
隐藏,我们取出tableview
的可见cell
,然后将除了选中的cell
之外的透明度都设置为0
1 2 3 4 5 6 7
| GCTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; [self.tableView bringSubviewToFront:cell]; for (UIView *subcell in tableView.visibleCells) { if (subcell != cell) { subcell.alpha = 0; } }
|
然后改变选中cell
的原点值,并且给cell
增加阴影,这里我偷懒没有做按钮的动画,只是用文字表示了按钮的状态
1 2 3 4 5 6 7 8 9 10 11 12 13
| [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来回调关闭的状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| - (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
1 2 3 4 5 6 7 8 9
| [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
移到最前
1
| [self.tableView bringSubviewToFront:cell];
|
然后在cell的下一层加上遮挡视图
和详情页
,并根据cell的origin做frame的变化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 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]; }];
|
然后在关闭的时候,移除掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| - (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(); } }]; }
|
这样就实现了抽屉式的效果,但是总感觉还有更好的办法实现,如果有思路的,欢迎交流~