博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS 卡片拖拽+翻转效果 。 仿tableview从缓存池中获取cell机制
阅读量:7118 次
发布时间:2019-06-28

本文共 6975 字,大约阅读时间需要 23 分钟。

1.效果图如下:

 

 

1.拖拽时分三种状态:

  

- (void)panOfRemoveMode:(UIPanGestureRecognizer *)gesture{    if (gesture.state == UIGestureRecognizerStateBegan) {        // 初始手指滑动的距离        __fingerPoiX = 0;        // 当前项        __curItem = self.visiableItems[0];        // 上一项        __lastItem = __visibleIndex > 0 ? [self itemAtIndex:__visibleIndex - 1] : nil;                if (__lastItem) {                        // 先添加上并设置初始位置            [__lastItem removeAlphaMaskView];            [self addSubview:__lastItem];            [self setFinalFrameForItem:__lastItem atIndex:-1 isUpdate:NO isLeftFinal:YES];            [self setTransformForItem:__lastItem atIndex:0];        }    }    else if (gesture.state == UIGestureRecognizerStateChanged) {                CGPoint movedPoint = [gesture translationInView:self];                __fingerPoiX += movedPoint.x;                // 避免一个手势左右滑动,即操作了 curItem,又操作了 lastItem        if (__fingerPoiX < 0 && __lastItem) {            [__lastItem removeFromSuperview];            __lastItem = nil;        }                // 左滑且未至底端        if (__fingerPoiX < 0 && __visibleIndex < [self numberOfItems] - 1) {                        [self calculateItemCenter:__curItem point:movedPoint isDeleteMode:NO];            [self adjustTranslateAngle:__curItem centerX:__curItem.center.x];        }        // 右滑且未至顶端        else if (__fingerPoiX > 0 && __visibleIndex > 0 && __lastItem) {                        [self calculateItemCenter:__lastItem point:movedPoint isDeleteMode:NO];            [self adjustTranslateAngle:__lastItem centerX:__lastItem.center.x];        }                [gesture setTranslation:CGPointZero inView:self];            }    else if (gesture.state == UIGestureRecognizerStateEnded) {                CGPoint vel = [gesture velocityInView:self];                if (__fingerPoiX < 0 && __visibleIndex < [self numberOfItems] - 1) {  // 左滑                    if (vel.x < -800) {                [self cardItemOutOfScreenEndScrollAnimation:__curItem isLeftFinal:YES isFast:YES];            }            else if(__fingerPoiX < -100){                [self cardItemOutOfScreenEndScrollAnimation:__curItem isLeftFinal:YES isFast:NO];            }            else {                [self cardItemToOriginalEndScrollAnimation:__curItem isFast:NO];            }        }        else if (__lastItem && __fingerPoiX > 0){  // 右滑                        if(vel.x > 800) {                [self cardItemToOriginalEndScrollAnimation:__lastItem isFast:YES];            }            else if (__fingerPoiX > CARDITEM_RIGHT_RESPONDLENGTH){                [self cardItemToOriginalEndScrollAnimation:__lastItem isFast:NO];            }            else {                [self cardItemOutOfScreenEndScrollAnimation:__lastItem isLeftFinal:YES isFast:NO];            }        }        else {            // 只对当前可视视图进行纠错            [self cardItemToOriginalEndScrollAnimation:__curItem isFast:NO];        }    }}

 

/**  *  @brief   设置卡片项的放射变换  */- (void)setTransformForItem:(CardViewItem *)item atIndex:(NSInteger)idx{    CGAffineTransform scale = CGAffineTransformMakeScale(1 - self.scaleRatio * idx, 1);    item.transform = CGAffineTransformTranslate(scale, 0, 15 * idx);}

 

/**  *  @brief   设置卡片项的最终位置约束  *  @param   idx   索引,用于新添加 item 还未设置 frame 时添加约束  *  @param   isUpdate   是否是更新约束  *  @param   isLeft   yes - 最终位置在左侧    no - 最终位置在右侧  */- (void)setFinalFrameForItem:(CardViewItem *)item atIndex:(NSInteger)idx isUpdate:(BOOL)isUpdate isLeftFinal:(BOOL)isLeft{    // cx 代表 item.center.x; centerX 代表 item 与 self 中心点的距离    NSInteger cx = -300;    NSInteger centerX = cx - self.center.x;        // 如图:|← 300 →□← 300 →|( | 代表 item.center.x 位置, 300 代表距离,□ 代表self 视图)    if (!isLeft) {        cx = -cx + W(self);    centerX = -centerX;    }        if (isUpdate) {            // 设置旋转角度        [self adjustTranslateAngle:item centerX:cx];        item.center = CGPointMake(cx, H(self)/2 + 100);            [item mas_updateConstraints:^(MASConstraintMaker * make) {            make.centerX.equalTo(@(centerX));            make.centerY.equalTo(@(100));        }];    }    else {        CGRect rect = [self itemRectAtIndex:idx];        item.center = CGPointMake(cx, H(self)/2 + 100);        [item mas_makeConstraints:^(MASConstraintMaker * make) {            make.centerX.equalTo(@(centerX));            make.centerY.equalTo(@(100));            make.width.equalTo(@(rect.size.width));            make.height.equalTo(@(rect.size.height));        }];    }}

 

/**  *  @brief   设置卡片项的初始位置约束  *  @attention   item 缩放时其子视图也缩小;还原时,如果 item 与父视图没有约束,则 item 的子视图不会还原且在滑动时界面出错  */- (void)setOriginalFrameForItem:(CardViewItem *)item atIndex:(NSInteger)idx isUpdate:(BOOL)isUpdate{    SELF_WEAK;    if (isUpdate) {                // 约束不会导致 frame 调整        item.center = CGPointMake(W(self)/2, H(item)/2);        item.transform = CGAffineTransformMakeRotation(0);        [item mas_updateConstraints:^(MASConstraintMaker * make) {            SELF_STRONG;            make.centerX.equalTo(strongSelf);            make.centerY.equalTo(@((H(item) - H(strongSelf))/2 ));        }];    }    else {        CGRect rect = [self itemRectAtIndex:idx];        item.center = CGPointMake(W(self) / 2, rect.size.height / 2);        [item mas_makeConstraints:^(MASConstraintMaker * make) {            SELF_STRONG;            make.centerX.equalTo(strongSelf);            make.centerY.equalTo(@((rect.size.height - H(strongSelf)) /2 ));            make.width.equalTo(@(rect.size.width));            make.height.equalTo(@(rect.size.height));        }];    }}

 

/**  *  @brief   从复用项数组中获取可复用对象,没有则新创建 。仿tableview的cell重用机制  */- (CardViewItem *)dequeueReusableCellWithIdentifier:(NSString *)identifier{    __block CardViewItem * item = nil;        // 有可复用项 + 剩余的项 > _maxItems    if (self.reusableItems.count > 0 && __visibleIndex <= [self numberOfItems] - self.maxItems) {                [self.reusableItems enumerateObjectsUsingBlock:^(CardViewItem * obj, NSUInteger idx, BOOL * stop) {                        if ([obj.reuseIdentifier isEqualToString:identifier]) {                            item = obj;                *stop = YES;            }        }];    }    else {                [self.mapDict enumerateKeysAndObjectsUsingBlock:^(NSString * key, id obj, BOOL * stop) {                        if ([key isEqualToString:identifier]) {                                if ([obj isKindOfClass:[NSString class]]) {   // xib 文件                                    item = (CardViewItem *)[self viewFromXibFile:(NSString *)obj];                }                else {  // 类文件                    item = [[(Class)obj alloc] init];                }                item.reuseIdentifier = key;                                [item addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self                                                                        action:@selector(tap:)]];                *stop = YES;            }        }];    }    return item;}

 

转载于:https://www.cnblogs.com/onlyMyRailGun/p/6380513.html

你可能感兴趣的文章
centos7 svn自动更新至web目录
查看>>
小米9.0系统最简单激活xposed框架的教程
查看>>
全栈开发工程师微信小程序-上(中)
查看>>
spring boot2 整合(三)JOOQ工具
查看>>
【实战】颠覆银行基础架构的区块链
查看>>
第十六章:SpringCloud Config 配置自动刷新
查看>>
iOS APP内弹窗推送版本更新信息(实现跳转、强制更新等)
查看>>
Flutter 系列文章:Flutter Text 控件介绍
查看>>
二、SpringBoot配置文件讲解
查看>>
HTML基础:web前端建站流程
查看>>
http
查看>>
导航栏与scrollerview(或scrollerview的子类)
查看>>
建立个人Maven仓库
查看>>
阿里架构师手写Tomcat——Session源码解析
查看>>
世界杯来了!小程序赛事操作来一波~
查看>>
一个维护版本日志整洁的Git提交规范
查看>>
单例模式总结
查看>>
bootstrapSwitch bootstrap 的开关组件扩展
查看>>
冒泡排序
查看>>
阿里云 OSS 如何设置防盗链, 上个月图床流量耗费50G+,请求次数10W+,什么鬼?
查看>>