美文网首页
iOS开发星级评分

iOS开发星级评分

作者: 锈色的栅栏 | 来源:发表于2016-08-03 16:42 被阅读956次

    前言

    在开发电商类的app中,我们经常会遇到用户评价“打星”这样的需求,因为iOS上没有这个控件,所以这时需要我们自定义该控件来满足需求。

    思路

    看到这个需求的时候,我想到了需要自定义此控件来满足需求。
    1)准备两张"星星"图片,一张为未选中状态下图片,一张为选中状态下的图片(如下)

    selectStar.png star.png

    在一个view上创建2个新view,一个是未选中的星星view,一个是选中星星的View,根据所点击的星星位置用选中星星的View覆盖未选中的星星view。


    2)封装一个显示"打星"的界面,来让星星显示在需要的界面上

    由于项目需要部分界面需要完整评分,部分界面则需要不完整的星级评分,所有写了个枚举类型来选中打分样式。

    使用星级打分打的分数可以通过代理方式或者block方式来传递

    实例代码

    #import<UIKit/UIKit.h>
    @class CCStarRateView;
    typedef void(^finishBlock)(CGFloat currentScore);
    typedef NS_ENUM(NSInteger, RateStyle){   
    WholeStar = 0, //只能整星评论   
    HalfStar = 1,  //允许半星评论 
    IncompleteStar = 2  //允许不完整星评论
    };
    @protocol CCStarRateViewDelegate<NSObject>
    -(void)starRateView:(CCStarRateView *)starRateView currentScore:(CGFloat)currentScore;
    @end

    @interface CCStarRateView : UIView
    @property (nonatomic,assign)CGFloat currentScore;  // 当前评分:0-5  默认0
    @property (nonatomic,assign)BOOL isAnimation;      //是否动画显示,默认NO
    @property (nonatomic,assign)RateStyle rateStyle;    //评分样式    默认WholeStar
    @property (nonatomic, weak) id<CCStarRateViewDelegate>delegate;

    -(instancetype)initWithFrame:(CGRect)frame;

    -(instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars rateStyle:(RateStyle)rateStyle isAnination:(BOOL)isAnimation delegate:(id)delegate;

    //block当做一个参数传递
    -(instancetype)initWithFrame:(CGRect)frame finish:(finishBlock)finish;

    //block当做一个参数传递
    -(instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars rateStyle:(RateStyle)rateStyle isAnination:(BOOL)isAnimation finish:(finishBlock)finish;

    @end


    #import "CCStarRateView.h"

    #define ForegroundStarImage @"Selectstar"

    #define BackgroundStarImage @"star"

    typedef void(^completeBlock)(CGFloat currentScore);

    @interface CCStarRateView()

    @property (nonatomic, strong) UIView *foregroundStarView;

    @property (nonatomic, strong) UIView *backgroundStarView;

    @property (nonatomic, assign) NSInteger numberOfStars;

    @property (nonatomic,strong)completeBlock complete;

    @end

    @implementation CCStarRateView

    #pragma mark - 代理方式

    -(instancetype)initWithFrame:(CGRect)frame{

    if (self = [super initWithFrame:frame]) {

    _numberOfStars = 5;

    _rateStyle = WholeStar;

    [self createStarView];

    }

    return self;

    }

    -(instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars rateStyle:(RateStyle)rateStyle isAnination:(BOOL)isAnimation delegate:(id)delegate{

    if (self = [super initWithFrame:frame]) {

    _numberOfStars = numberOfStars;

    _rateStyle = rateStyle;

    _isAnimation = isAnimation;

    _delegate = delegate;

    [self createStarView];

    }

    return self;

    }

    #pragma mark - block方式

    -(instancetype)initWithFrame:(CGRect)frame finish:(finishBlock)finish{

    if (self = [super initWithFrame:frame]) {

    _numberOfStars = 5;

    _rateStyle = WholeStar;

    _complete = ^(CGFloat currentScore){

    finish(currentScore);

    };

    [self createStarView];

    }

    return self;

    }

    -(instancetype)initWithFrame:(CGRect)frame numberOfStars:(NSInteger)numberOfStars rateStyle:(RateStyle)rateStyle isAnination:(BOOL)isAnimation finish:(finishBlock)finish{

    if (self = [super initWithFrame:frame]) {

    _numberOfStars = numberOfStars;

    _rateStyle = rateStyle;

    _isAnimation = isAnimation;

    _complete = ^(CGFloat currentScore){

    finish(currentScore);

    };

    [self createStarView];

    }

    return self;

    }

    #pragma mark - private Method

    //调用这个方法来布局
    -(void)createStarView{

    self.foregroundStarView = [self createStarViewWithImage:ForegroundStarImage];

    self.backgroundStarView = [self createStarViewWithImage:BackgroundStarImage];

    self.foregroundStarView.frame = CGRectMake(0, 0, self.bounds.size.width*_currentScore/self.numberOfStars, self.bounds.size.height);

    [self addSubview:self.backgroundStarView];

    [self addSubview:self.foregroundStarView];

    //添加手势来取得所点击的位置
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userTapRateView:)];

    tapGesture.numberOfTapsRequired = 1;

    [self addGestureRecognizer:tapGesture];

    }

    //使用这个方法来初始化子View
    - (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)userTapRateView:(UITapGestureRecognizer *)gesture {

    //函数返回一个CGPoint类型的值,表示触摸在view这个视图上的位置,这里返回的位置是针对view的坐标系的。调用时传入的view参数为空的话,返回的时触摸点在整个窗口的位置。

    CGPoint tapPoint = [gesture locationInView:self];

    CGFloat offset = tapPoint.x;

    CGFloat realStarScore = offset / (self.bounds.size.width / self.numberOfStars);

    switch (_rateStyle) {

    case WholeStar:

    {

    self.currentScore = ceilf(realStarScore);

    break;

    }

    case HalfStar:

    self.currentScore = roundf(realStarScore)>realStarScore ? ceilf(realStarScore):(ceilf(realStarScore)-0.5);

    break;

    case IncompleteStar:

    self.currentScore = realStarScore;

    break;

    default:

    break;

    }

    }

    - (void)layoutSubviews {

    [super layoutSubviews];

    __weak CCStarRateView *weakSelf = self;

    CGFloat animationTimeInterval = self.isAnimation ? 0.2 : 0;

    [UIView animateWithDuration:animationTimeInterval animations:^{

    weakSelf.foregroundStarView.frame = CGRectMake(0, 0, weakSelf.bounds.size.width * weakSelf.currentScore/self.numberOfStars, weakSelf.bounds.size.height);

    }];

    }

    -(void)setCurrentScore:(CGFloat)currentScore {

    if (_currentScore == currentScore) {

    return;

    }

    if (currentScore < 0) {

    _currentScore = 0;

    } else if (currentScore > _numberOfStars) {

    _currentScore = _numberOfStars;

    } else {

    _currentScore = currentScore;

    }

    if ([self.delegate respondsToSelector:@selector(starRateView:currentScore:)]) {

    [self.delegate starRateView:self currentScore:_currentScore];

    }

    if (self.complete) {

    _complete(_currentScore);

    }
    //重新布局
    [self setNeedsLayout];
    }
    @end

    相关文章

      网友评论

          本文标题:iOS开发星级评分

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