动画三

又偷偷的写了一段代码。
不得不感慨,还是这种代码好写。主要是不伤脑细胞。hhhh

丰富cell的内容

因为时间隔着有些久远,所以及时找回状态呢,就是盯着第一篇文章里的效果图,把cell里面的内容先添加上去。当然这些内容是不用思考的,但有一样是要考虑的,就是添加的层次,我的思路呢就是先添加一个背景View(bgView),然后把展开后下面的那部分label放在一个titleView里面,然后整体放在bgView上,然后再把上面的图片放在上面。 出于美观的考虑,我们还可以在最下面放一层阴影视图,这样在展开关闭的时候看起来自然一下。

添加如下的属性,里面的两个集合视图是自定义的,一个用了iOS9的UIStackView,另一个用的是UIView(- -,是因为自己对stackView不大熟悉,我怕会影响后面对用户视图写动画时不方便)

///卡片控件大背景
@property (nonatomic, strong) UIView *bgView;
///图片视图
@property (nonatomic, strong) UIImageView *coverImageView;
///文本视图
@property (nonatomic, strong) UIView *titleView;
///标题
@property (nonatomic, strong) UILabel *title;
///喜爱标签
@property (nonatomic, strong) UILabel *favoriteLabel;

///星星集合视图
@property (nonatomic, strong) CardStartsView *startsView;
///用户集合视图
@property (nonatomic, strong) CardUsersView *usersView;

然后下面讲这些空间的设置添加,用了Masonry。对于Mansory,比起其他的那些轻量的自动布局的框架,功能更多一些,虽然有些繁琐,所以我们可以花时间去了解一下具体更多的用法,或者去里面观察一下内部实现。但是这里就不讲了。

    //阴影视图
    UIView *shadowView =  [self createShadowView];
    
    //背景视图
    self.bgView = [self setViewWithColor:[UIColor whiteColor] andCornerRadius:5 andAlpha:0.0];
    [shadowView addSubview:self.bgView];
    [self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(shadowView);
    }];
    
    //文字视图
    self.titleView = [self setViewWithColor:[UIColor whiteColor] andCornerRadius:5 andAlpha:1.0];
    [shadowView addSubview:self.titleView];
    [self.titleView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(shadowView.mas_bottom);
        make.left.equalTo(shadowView.mas_left);
        make.right.equalTo(shadowView.mas_right);
        make.height.mas_equalTo(@100);
    }];
    
    //标题
    self.title = [UILabel cz_labelWithText:@"**是个大傻子 * 100" fontSize:16 color:[UIColor lightGrayColor]];
    self.title.numberOfLines = 1;
    [self.titleView addSubview:self.title];
    [self.title mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.titleView.mas_top).offset(15);
        make.left.equalTo(self.titleView.mas_left).offset(15);
        make.width.mas_equalTo(self.contentView.frame.size.width);
    }];
    
    //喜欢
    self.favoriteLabel = [UILabel cz_labelWithText:@"100 comments" fontSize:14 color:[UIColor grayColor]];
    self.favoriteLabel.textAlignment = NSTextAlignmentLeft;
    [self.titleView addSubview:self.favoriteLabel];
    [self.favoriteLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.title.mas_bottom).offset(10);
        make.left.equalTo(self.titleView.mas_left).offset(15);
        make.height.mas_equalTo(@20);
    }];
    
    //评价
    self.startsView = [[CardStartsView alloc] init];
    self.startsView.level = 4;
    [self.titleView addSubview:self.startsView];
    [self.startsView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.equalTo(self.favoriteLabel.mas_centerY);
        make.left.equalTo(self.favoriteLabel.mas_right).offset(10);
        make.width.mas_equalTo(@70);
        make.height.mas_equalTo(@20);
    }];
    
    //用户集合视图
    NSArray *arr = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4",nil];
    self.usersView = [[CardUsersView alloc] init];
    self.usersView.users = arr;
    [self.titleView addSubview:self.usersView];
    [self.usersView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@30);
        make.width.equalTo(@(arr.count * 25 + 5));
        make.top.equalTo(self.favoriteLabel.mas_bottom).offset(3);
        make.left.equalTo(self.titleView.mas_left).offset(15);
    }];
    
    
    //最上面的图片
    self.coverImageView = [[UIImageView alloc] init];
    self.coverImageView.layer.cornerRadius = 5; //切个小圆角
    self.coverImageView.layer.masksToBounds = YES;
    self.coverImageView.userInteractionEnabled = NO;
    [shadowView addSubview:self.coverImageView];
    [self.coverImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(shadowView);
    }];

里面有两个封装了一下的方法,还有一些label的设置是直接用别人的一些包,当然都是对最基本功能的一个简化

- (UIView *)setViewWithColor:(UIColor *)color andCornerRadius:(CGFloat)radius andAlpha:(CGFloat)alpha
{
    UIView *view = [[UIView alloc] init];
    view.alpha = alpha;
    view.backgroundColor = color;
    view.layer.cornerRadius = radius;
    view.layer.masksToBounds = YES;
    
    return view;
}

- (UIView *)createShadowView
{
    //阴影视图
    UIView *shadowView = [[UIView alloc] init];
    shadowView.layer.cornerRadius = 5;
    shadowView.clipsToBounds = NO;
    shadowView.layer.shadowColor = [UIColor colorWithRed:138.0/255 green:138.0/255 blue:138.0/255 alpha:1.0].CGColor;
    shadowView.layer.shadowOffset = CGSizeMake(0, 5);
    shadowView.layer.shadowOpacity = 0.8;
    shadowView.layer.shadowRadius = 10;
    
    [self.contentView addSubview:shadowView];
    [shadowView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.contentView);
    }];
    
    return shadowView;
}

添加手势

后面一定是要添加手势,有一个滑动手势,还有一个点按手势,这里我们先添加滑动手势,至于点按的手势,因为它的作用是为了引出另外一个动画,所以我们就放在后续进行说明。
这里需要说明的就是手势应该在哪份文件添加好(当然是在cell上面添加),为了简便呢,我们在cell的上一层collectionView添加,这样可以省一些两者之间的交互。因为在父类里面可以通过很多现成的方法去拿到子类的内容
其次呢就是说一个小技巧,如何对一个两份代码基本一样,但是刚好运算和一些设置是反着的代码进行封装。这个可以通过对引入一个正负一参数对里面的操作进行正负一运算就可以整合成一起了,对于设置,用这个参数进行三目运算也可以区别开来。

- (void)addGesture
{
    //上滑
    self.up = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeUp:)];
    self.up.direction = UISwipeGestureRecognizerDirectionUp;
    [self.collectionView addGestureRecognizer:self.up];
    
    //下滑
    self.down = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeDown:)];
    self.down.direction = UISwipeGestureRecognizerDirectionDown;
    
    //这里先不添加下滑手势,避免在没展开的时候,同时存在两种手势(只有在上滑以后,才会有下滑手势)
}

- (void)swipeUp:(UISwipeGestureRecognizer *)swipeRecognizer
{
    [self setSwip:swipeRecognizer andDrection:Up];
}

- (void)swipeDown:(UISwipeGestureRecognizer *)swipeRecognizer
{
    [self setSwip:swipeRecognizer andDrection:Down];
}

下面是setSwip的封装方法 ,在这个方法的对cell位置进行操作/获取的方法都是非常常用的。

- (void)setSwip:(UISwipeGestureRecognizer *)swipeRecognizer andDrection:(Direction)direction
{
    //得到point.x位置,用以确定item是第几个
    CGPoint location = [swipeRecognizer locationInView:self.collectionView];
    NSIndexPath *indexpath = [self.collectionView indexPathForItemAtPoint:location];
    //NSLog(@"indexpath.row : %ld",(long)indexpath.row);
    
    //得到对应的cell
    CardCollectionViewCell *swipeCell = (CardCollectionViewCell *)[self.collectionView cellForItemAtIndexPath:indexpath];
    
    if (direction == Up) {
        //返回cell在目标视图(collectionView)中的位置
        CGRect rect = [self.collectionView convertRect:swipeCell.frame toView:self.collectionView];
        
        //手势没在cell范围上(通过打印发现没在位置的时候,size 和 origin 都是 0
        //NSLog(@"size:{%f  %f} origin:{%f  %f}",rect.size.width, rect.size.height, rect.origin.x, rect.origin.y);
        if (rect.origin.x == 0 && rect.origin.y == 0) {
            return;
        }
        
        //没有在当前手势上
        if (indexpath.row != _currentIndex) {
            return;
        }
    }
    
    //执行UIView动画
    [UIView animateWithDuration:0.6 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:3 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        
        //coverImage
        CGRect coverFrame = swipeCell.coverImageView.frame;
        coverFrame.origin.y -= 100 * direction;
        swipeCell.coverImageView.frame = coverFrame;
        
        //bgView
        CGRect bgFrame = swipeCell.bgView.frame;
        bgFrame.size = CGSizeMake(swipeCell.bgView.frame.size.width + 30 * direction, swipeCell.bgView.frame.size.height + 20 * direction);
        bgFrame.origin.x -= 15 * direction;
        swipeCell.bgView.frame = bgFrame;
        swipeCell.bgView.alpha = direction < 0 ? 0.0 : 1.0;
        
        //titleView
        CGRect titleFrame = swipeCell.titleView.frame;
        titleFrame.size = CGSizeMake(swipeCell.titleView.frame.size.width + 30 * direction, swipeCell.titleView.frame.size.height);
        titleFrame.origin.x -= 15 * direction;
        swipeCell.titleView.frame = titleFrame;
        
    } completion:^(BOOL finished) {
        self.collectionView.scrollEnabled = direction > 0 ? NO : YES;
        swipeCell.coverImageView.userInteractionEnabled = direction > 0 ? YES : NO;
        
        if (direction == Up) {
            [self.collectionView removeGestureRecognizer:self.up];
            [swipeCell addGestureRecognizer:self.down];
        } else {
            [self.collectionView addGestureRecognizer:self.up];
            [swipeCell removeGestureRecognizer:self.down];
        }
    }];
}

两个集合视图

下面说一下那两个自定义的集合View
StackView的方便之处就在于他不需要我们进行手动的适配位置。但这样也有不方便的地方,那就是他把很多东西都固定了。所以适用范围就小。

//通过重写Level属性的set方法来对内容赋值
- (void)setLevel:(CGFloat)level
{
    NSInteger startCount = (NSInteger)level;
    
    //满星
    for (NSInteger i = 0; i < startCount; i++) {
        [self createStartWithImageName:@"comtent_star_icon" startPosition:i];
    }
    //半星
    if (level - startCount) {
        [self createStartWithImageName:@"yiban_star_icon" startPosition:startCount];
        startCount++;
    }
    for (NSInteger i = startCount; i < StartCount; i++) {
        [self createStartWithImageName:@"comtent_star_icon nal" startPosition:i];
    }
    
    _level = level;
}

- (void)createStartWithImageName:(NSString *)imageName startPosition:(NSInteger)position
{
    UIImageView *imageView = nil;
    if (self.subviews.count == StartCount) {
        imageView = self.subviews[position];
        imageView.image = [UIImage imageNamed:imageName];
        return;
    }
    
    imageView = [[UIImageView alloc] init];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.image = [UIImage imageNamed:imageName];
    [self addArrangedSubview:imageView];
}

对于用户集合视图也是一样的,只是多了一个约束的添加

- (void)setUsers:(NSArray *)users
{
    NSInteger usersCount = users.count >= UsersCount ? UsersCount : users.count;
    
    for (NSInteger i = 0; i < usersCount; i++) {
        UIImageView *imageView = [self createImageViewWithName:[NSString stringWithFormat:@"%ld",(i + 1) * 10]];
        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.bottom.equalTo(self);
            make.left.equalTo(@(i * 25));
            make.width.equalTo(@30);
        }];  
    }
    
    _users = users;
}

- (UIImageView *)createImageViewWithName:(NSString *)name
{
    UIImageView *imageV = [[UIImageView alloc] init];
    imageV.image = [UIImage circleImage:name];
    [self addSubview:imageV];
    return imageV;
}

这里有一个分类方法 imageV.image = [UIImage circleImage:name],这个是手动写的一个分类,就是做图片切圆的,我们也知道那种Layer的切圆是比较耗费性能的,所以我们很多时候都是用CoreGraphics那一套,当然具体的就不解释了。
一个类方法,一个对象方法

- (instancetype)circleImage
{
    UIGraphicsBeginImageContext(self.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGContextAddEllipseInRect(ctx, rect);
    CGContextClip(ctx);
    
    [self drawInRect:rect];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

+ (instancetype)circleImage:(NSString *)image
{
    return [[self imageNamed:image] circleImage];
}

效果呢就是下面👇这样:


3月-12-2018 16-55-32.gif
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容

  • 用到的组件 1、通过CocoaPods安装 2、第三方类库安装 3、第三方服务 友盟社会化分享组件 友盟用户反馈 ...
    SunnyLeong阅读 14,592评论 1 180
  • 耿睿婕职业生涯规划系列分享之六十三:《餐桌上的生涯能力培养》 在生活中我们常常看到现在很多大学毕业甚至结婚的年...
    睿婕生涯心理咨询工作室阅读 167评论 0 0
  • 下午我们先来到一汽丰田,它与上午的上汽丰田像是亲兄弟,属于同一个集团。重点看了卡罗拉双挈,外观比雷凌更符...
    1803阅读 272评论 0 0
  • 你怎么突然造访 若不是鸟儿愉悦的欢叫 我又怎么会知道 你已经把我拥入怀抱 不过 这种温柔使我陶醉 让我的思路变得通...
    不俗小七阅读 835评论 14 40
  • JavaCV介绍 JavaCV首先提供了计算机视觉领域研究人员常用的函数库的封装:OpenCV, FFmpeg, ...
    JasonDing阅读 1,645评论 0 4