iOS之星星评分(二)

作者: Mr_Victory | 来源:发表于2016-06-01 12:29 被阅读815次
      在上一篇文章中,我们讲了通过重绘的方式来创建星星评分。但是通过这种方法创建的星星个数是“死的”,用户不能通过点击来改变星星的个数。 那么今天我们就来详细讲一讲,如何动态改变星星的个数。
    
    starView.gif

    首先我们创建一个基于UIView的类,就叫YYStarView吧。在YYStarView.h文件中我们写下如下代码:

    #import <UIKit/UIKit.h>
    @class YYStarView;
    @protocol YYStarViewDelegate <NSObject>
    @optional
    // 星星百分比(得分值)发生变化的代理
    - (void)starView:(YYStarView *)starView scorePercentDidChange:(CGFloat)newScorePercent;
    @end
    
    @interface YYStarView : UIView
    
    @property (nonatomic, assign) CGFloat scorePercent;//得分值,范围为0~1,默认1
    @property (nonatomic, assign) BOOL hasAnimation;//是否允许动画,默认为NO
    @property (nonatomic, assign) BOOL allowIncompleteStar;//评分时是否允许不是整星,默认为NO
    
    @property (nonatomic, weak) id<YYStarViewDelegate>delegate;
    - (instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars;
    @end
    
    

    在YYStarView.m文件中我们写下如下代码:

    #import "YYStarView.h"
    #define STAR_FRONT_NAME @"star_yellow" //点亮星星图片
    #define STAR_BACK_NAME @"star_gray" // 未点亮星星图片
    #define DEFALUT_STAR_NUMBER 5 // 默认星星个数
    #define ANIMATION_TIME_INTERVAL 0.2 // 动画延时
    
    @interface YYStarView ()
    
    // 前景视图
    @property (nonatomic, strong) UIView *foregroundStarView;
    // 背景视图
    @property (nonatomic, strong) UIView *backgroundStarView;
    // 星星个数
    @property (nonatomic, assign) NSInteger numberOfStars;
    
    @end
    
    @implementation YYStarView
    
    - (instancetype)initWithFrame:(CGRect)frame {
        // 初始化,这里我设置星星个数为5
        return [self initWithFrame:frame numberOfStars:DEFALUT_STAR_NUMBER];
    }
    
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
        
        if (self = [super initWithCoder:aDecoder]) {
            _numberOfStars = DEFALUT_STAR_NUMBER;
            [self createDataAndUI];
        }
        return self;
    }
    
    - (instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars {
        if (self = [super initWithFrame:frame]) {
            _numberOfStars = numberOfStars;
            [self createDataAndUI];
        }
        return self;
    }
    
    #pragma mark - Private Methods
    // 创建视图
    - (void)createDataAndUI {
        _scorePercent = 1;//默认为1
        _hasAnimation = NO;//默认为NO
        _allowIncompleteStar = NO;//默认为NO
        
        self.foregroundStarView = [self createStarViewWithImage:STAR_FRONT_NAME];
        self.backgroundStarView = [self createStarViewWithImage:STAR_BACK_NAME];
        
        [self addSubview:self.backgroundStarView];
        [self addSubview:self.foregroundStarView];
        
        // 添加点按手势(也可以添加拖动手势)
        UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userTapRateView:)];
        tapGesture.numberOfTapsRequired = 1;
        [self addGestureRecognizer:tapGesture];
    }
    
    - (void)userTapRateView:(UITapGestureRecognizer *)gesture {
        CGPoint tapPoint = [gesture locationInView:self]; // 手指当前点
        CGFloat offset = tapPoint.x;
        // 当前偏移的X值 = 手指当前的位置*(星星视图总宽度/星星个数)
        CGFloat realStarScore = offset / (self.bounds.size.width / self.numberOfStars);
        // ceilf函数:返回浮点数整数部分(舍弃小数点部分,往个位数进1)如12.234 → ceilf(12.234)=13
        // 这句的意思是 是否显示整星
        CGFloat starScore = self.allowIncompleteStar ? realStarScore : ceilf(realStarScore);
        // 用手指移动的距离/星星的个数  == 点亮星星个数
        self.scorePercent = starScore / self.numberOfStars;
    }
    
    - (UIView *)createStarViewWithImage:(NSString *)imageName {
        UIView *view = [[UIView alloc] initWithFrame:self.bounds];
        view.clipsToBounds = YES;
        view.backgroundColor = [UIColor clearColor];
        for (NSInteger i = 0; i < self.numberOfStars; i ++)
        {
            UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
            imageView.frame = CGRectMake(i * self.bounds.size.width / self.numberOfStars, 0, self.bounds.size.width / self.numberOfStars, self.bounds.size.height);
            imageView.contentMode = UIViewContentModeScaleAspectFit;
            [view addSubview:imageView];
        }
        return view;
    }
    
    - (void)layoutSubviews {
        [super layoutSubviews];
        __weak YYStarView *weakSelf = self;
        CGFloat animationTimeInterval = self.hasAnimation ? ANIMATION_TIME_INTERVAL : 0;
        [UIView animateWithDuration:animationTimeInterval animations:^{
            weakSelf.foregroundStarView.frame = CGRectMake(0, 0, weakSelf.bounds.size.width * weakSelf.scorePercent, weakSelf.bounds.size.height);
        }];
    }
    
    #pragma mark - Get and Set Methods
    
    - (void)setScorePercent:(CGFloat)scroePercent {
        if (_scorePercent == scroePercent) {
            return;
        }
        // 得分范围我设置的是0~1 这个可以你自己设定
        if (scroePercent < 0) {
            _scorePercent = 0;
        } else if (scroePercent > 1) {
            _scorePercent = 1;
        } else {
            _scorePercent = scroePercent;
        }
        // 代理方法,当星星百分比发生变化时候调用
        if ([self.delegate respondsToSelector:@selector(starView:scorePercentDidChange:)]) {
            [self.delegate starView:self scorePercentDidChange:scroePercent];
        }
        // 重新布局, 刷新视图
        [self setNeedsLayout];
    }
    @end
    

    如何使用?这个非常简单,引入头文件,简单初始化一下就好了,是不是非常简单啊?

    YYStarView *starView = [[YYStarView alloc] initWithFrame:CGRectMake(10, 100, 300, 40) numberOfStars:5];
        starView.scorePercent = 0.3;
        starView.allowIncompleteStar = YES;
        starView.hasAnimation = YES;
        [self.view addSubview:starView];
    
      如果有什么好的建议,可以@我。对了我已经将此starView封装好了 欢迎下载使用,别忘了Star哟
    

    https://github.com/VictDog/YYStarGradeView/tree/master/YYStarGrade

    相关文章

      网友评论

      • PhoenixZhai:demo下不了
        Mr_Victory:@PhoenixZhai 这个貌似是地址给错了,给的是下一级目录,你只需返回上级目录就可下载。 https://github.com/VictDog/YYStarGradeView。 可能是手机问题之前没有收到到你的留言,真的很抱歉。
        Mr_Victory:@南人在外 这个上传了github啊,在文章结尾给出了地址,貌似地址给错了,这就尴尬了。https://github.com/VictDog/YYStarGradeView
        钱刀为:@PhoenixZhai 作者好像没有传上去 :cry:
      • Mr_Bob_:封装的可以的
      • 芝麻绿豆:有没有考虑过绘制?
        Mr_Victory:@芝麻绿豆 没有,第一篇是绘制的

      本文标题:iOS之星星评分(二)

      本文链接:https://www.haomeiwen.com/subject/agpcdttx.html