动效还是欠缺了很多,希望各位能够指正. 个人并不是非常喜欢用框架. 所以想写一些比较实用的功能做一个展示.
只是为了实现上面的功能, 所以建立了两个collectionView,
一个用于展示图片(所有图片),
一个用于点击后放大图片并进行展示.
(并且可以实现左右展示,很像以前学过的水平布局展示的collectionView)
遇到的几个问题
1.需要处理的是弹出collectionView的数据展示问题, 以及当前展示的哪张图片问题.
2.监测到手指点击的cell,到底处在屏幕的哪个位置上.
3.图片放大缩小, 会影响外边蒙版的透明度.
额外问题, 当我弹出控制器的时候,会牵扯到将原有模型数组中的模型中的图片取出.
1.当时我想着可以遍历模型数组然后取出. 于是就在建立数组的时候(模型装数组的时候), 将需要传入的图片一起转换过来放入数组中 . 但是我发现会出现 加载程序变慢的情况. (废弃掉)
2.后来我认为可以开辟一个子线程,然后用于专门加载要显示的图片,但到后面,如果我点击过快的话, 很出现数组越界的情况(数组还没有将数据完全加载).
3.后来我不去把加载图片的环节放在当前控制器中处理(本来就该如此,谁的事件 就交给谁处理好了). 然后将字符串url传入就可以了.
代码的相关实现
1.对于控制器的处理,点击Item需要将1.所有数据 2.当前点击的indexPath传入
modal的控制器进行接收. 展示数据, 并将显示转到传入的indexPath.
modal出来的控制器,展示数据,并且把需要显示indexPath转到显示
当点击item的时候,可以通过设置 modal出来的控制器的数据 和展示的 indexPath来控制 modal出来的控制器的显示
实现代码
// 为了确保数据加载完全, 就在viewWillAppear中书写跳转
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.collectionView scrollToItemAtIndexPath:self.indexPath atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
}
2.现在就是第二个难点的处理, 上一篇文章我们可以看出,只要给我们位置,我们可以以我们想要的数据方式进行弹出和关闭,
此时我们需要记录的是, 点击item的尺寸 和 点击item的中心点的位置,这样我们才能更精确的控制modal控制器的弹出.
在modal新的控制器的时候,我们需要做的事情有
- (void)clickShopCell:(LXLShopCell *)cell
{
// 创建需要modal的控制器
ModalViewController *modalVC = [[ModalViewController alloc]init];
// 设置传入的数据
modalVC.images = self.images;
// 设置modal的控制器的代理
modalVC.delegate = self;
// 自定义转场, 设置modal控制器的转场代理, 利用代理去控制,转场动画
modalVC.transitioningDelegate = self.custom;
// 将转场的类型改为自定义, 自己才可以进行修改
modalVC.modalPresentationStyle = UIModalPresentationCustom;
// 取得点击cell 的frame 在控制器view上的
必须书写 superView 否则 就会转换不成功
#warning 必须写superView
CGRect frame = [cell.superview convertRect:cell.frame toView:self.view];
// 获取点击cell的中心点 处在控制器view的什么位置上
CGPoint center = [cell.superview convertPoint:cell.center toView:self.view];
// 转场动画需要这两个值的出入
self.custom.rect = frame;
self.custom.center = center;
// 后期需要. 当滑动collectionView的时候, 需要转换成不同的中心点.
modalVC.custom = self.custom;
// 获取点击cell的indexPath
modalVC.indexPath = [self.collectionView indexPathForCell:cell];
[self presentViewController:modalVC animated:YES completion:^{
}];
}
转场代理中的代码实现
只进行转场动画的代码说明
想法: 1.中心点的迁移
点击中心点---->屏幕中心点
2.尺寸的变化
原cell的尺寸--->全屏幕
需要倒着思考, 本来应该是屏幕中心 ,现在在cell的中线点上.
本来是全屏幕, 现在 transform 到cell的尺寸上
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIView *presentView = [[UIView alloc]init];
// 先进行计算,需要transformScale的大小
CGFloat scaleX = self.rect.size.width / [UIScreen mainScreen].bounds.size.width;
CGFloat scaleY = self.rect.size.height / [UIScreen mainScreen].bounds.size.height;
// 对弹出控制器进行设置动画
// 弹出前的位置,尺寸
if (self.isPop) {
presentView = [transitionContext viewForKey:UITransitionContextToViewKey];
[[transitionContext containerView] addSubview:presentView];
CGPoint point = presentView.center;
presentView.center = self.center;
presentView.transform = CGAffineTransformMakeScale(scaleX , scaleY);
// 动画modal过程,还原尺寸和位置
[UIView animateWithDuration:1.0 animations:^{
presentView.center = point;
presentView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
// 完成后记得关闭上下文, 否则后面的动画将无法执行
[transitionContext completeTransition:YES];
}];
}else
{
presentView = [transitionContext viewForKey:UITransitionContextFromViewKey];
[[transitionContext containerView] addSubview:presentView];
[UIView animateWithDuration:1.0 animations:^{
presentView.center = self.center;
presentView.transform = CGAffineTransformMakeScale(scaleX, scaleY);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
3.写到这里我想基本功能应该是可以实现了, 但是当我们滑动modal控制器的图片时发现, dismiss的时候位置不是需要回退的cell 的位置, 因为此时点击的cell 和我需要回退的cell 已经不是一个了.
这里我们遇到了问题,那么怎么解决呢. 很简单. 当我们滚动的时候,通知控制器,当前展示的是第几个item, 然后他将对应cell的中心点,再传给转场代理就可以了
过程虽然复杂,但是也好做的
modal控制器中的代码的实现
// 苹果提供的方法, 方便我们找到离开实现的cell ,当时我还想找到需要的cell ,但是发现开始的移动根本就不可能找到. 但是此方法是针对与 拖动collectionView展示新的cell时调用, 我们确实需要
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
// 我利用 可显示的cell 的集合, 反正我设置的页面之内只能显示一个. 取出显示的cell
UICollectionViewCell *selectCell = collectionView.visibleCells.lastObject;
// 得到它的indexPath
NSIndexPath *index = [collectionView indexPathForCell:selectCell];
// 调用代理将 indexPath 传给控制器, 那么控制器就能方便的算出中心点了
if ([self.delegate respondsToSelector:@selector(modalViewController:displayCellIndexPath:)]) {
[self.delegate modalViewController:self displayCellIndexPath:index];
}
}
控制器中的代码
只写了modal控制器的代理部分代码
- (void)modalViewController:(ModalViewController *)modalVC displayCellIndexPath:(NSIndexPath *)indexPath
{
// 取出cell
UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
// 算出中心点
CGPoint center = [cell.superview convertPoint:cell.center toView:self.view];
// 给转场代理 设置 值center
self.custom.center = center;
}
现在图片展示功能基本实现了, 下一次,我想研究研究 图文混排的的实现...