oc 評價星星view

第一種:

view.h:

//
//  XHStarRateView.h
//  XHStarRateView
//
//  Created by 江欣華 on 16/4/1.
//  Copyright ? 2016年 jxh. All rights reserved.
//

#import <UIKit/UIKit.h>
@class XHStarRateView;

typedef void(^finishBlock)(CGFloat currentScore);

typedef NS_ENUM(NSInteger, RateStyle)
{
    WholeStar = 0, //只能整星評論
    HalfStar = 1,  //允許半星評論
    IncompleteStar = 2  //允許不完整星評論
};

@protocol XHStarRateViewDelegate <NSObject>

-(void)starRateView:(XHStarRateView *)starRateView currentScore:(CGFloat)currentScore;

@end

@interface XHStarRateView : UIView

@property (nonatomic,assign)BOOL isAnimation;       //是否動畫顯示,默認(rèn)NO
@property (nonatomic,assign)RateStyle rateStyle;    //評分樣式    默認(rèn)是WholeStar
@property (nonatomic, weak) id<XHStarRateViewDelegate>delegate;


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


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

@end

view.m:

//
//  XHStarRateView.m
//  XHStarRateView
//
//  Created by 江欣華 on 16/4/1.
//  Copyright ? 2016年 jxh. All rights reserved.
//

#import "XHStarRateView.h"

#define ForegroundStarImage @"star"
#define BackgroundStarImage @"unstar"

typedef void(^completeBlock)(CGFloat currentScore);

@interface XHStarRateView()

@property (nonatomic, strong) UIView *foregroundStarView;
@property (nonatomic, strong) UIView *backgroundStarView;

@property (nonatomic, assign) NSInteger numberOfStars;
@property (nonatomic,assign)CGFloat currentScore;   // 當(dāng)前評分:0-5  默認(rèn)0

@property (nonatomic,strong)completeBlock complete;

@end

@implementation XHStarRateView

#pragma mark - 代理方式
-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        _numberOfStars = 5;
        _rateStyle = WholeStar;
        [self createStarView];
    }
    return self;
}
-(instancetype)initWithFrame:(CGRect)frame withCurrentScore:(NSInteger)currentScore{
    if (self = [super initWithFrame:frame]) {
        _numberOfStars = 5;
        _currentScore = currentScore;
        _rateStyle = WholeStar;
        [self createStarViewWithCurrentScore];
    }
    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];

}
-(void)createStarViewWithCurrentScore{
    
    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];
}


- (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 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 XHStarRateView *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

第二種:

//
//  TTStarEvaluationView.h
//  OCTest
//
//  Created by rollingstoneW on 2018/9/7.
//  Copyright ? 2018年 zyb. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface TTStarEvaluationView : UIView

@property (nonatomic, strong, nullable) UIImage *starImage; // 星星圖片,默認(rèn)為21*21的星星圖片
@property (nonatomic, strong, nullable) UIImage *starImageForHalf; // 半星圖片
@property (nonatomic, strong, nullable) UIImage *unstarImage; // 未選的星星圖片

/**
 在unstarImage為空的時候才會起作用,自動繪制選中和未選中的星星
 */
@property (nonatomic, strong, nullable) UIColor *starColor; // 星星顏色,默認(rèn)為黃色
@property (nonatomic, strong, nullable) UIColor *unstarColor; // 未選的星星顏色,默認(rèn)為淺灰色

@property (nonatomic, assign) CGFloat starSpace; // 間距 默認(rèn)為圖片寬度的一半
@property (nonatomic, assign) CGFloat horiInset; // 前后縮進(jìn),默認(rèn)為10,建議不要設(shè)置為0,否則滿星和0星不容易選中

@property (nonatomic, assign) NSInteger numberOfStars; // 星星數(shù)量,默認(rèn)為5
@property (nonatomic, assign) NSInteger scorePerStar; // 一個星星代表的分?jǐn)?shù),默認(rèn)為1
@property (nonatomic, assign) CGFloat   currentScore; // 當(dāng)前分?jǐn)?shù)
@property (nonatomic, assign) CGFloat   scoreMinPace; // 分?jǐn)?shù)的最小刻度,默認(rèn),有半星圖片時為半星分?jǐn)?shù),否則為1星分?jǐn)?shù),取值范圍0.1-0.5,整數(shù)
@property (nonatomic, assign) BOOL      canBeZero; // 是否可以選中0星,默認(rèn)YES

@property (nonatomic, strong, nullable) void(^didEvaluateBlock)(CGFloat score); // 選中星星后的回調(diào)

@end

//
//  TTStarEvaluationView.m
//  OCTest
//
//  Created by rollingstoneW on 2018/9/7.
//  Copyright ? 2018年 zyb. All rights reserved.
//

#import "TTStarEvaluationView.h"

static NSString *const DefaultStarImageBase64 = @"aaaaaaaa";

@implementation TTStarEvaluationView
@synthesize scoreMinPace = _scoreMinPace;
@synthesize starSpace = _starSpace;

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self commonInit];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self commonInit];
    }
    return self;
}

- (void)commonInit {
    NSData *imageData = [[NSData alloc] initWithBase64EncodedString:DefaultStarImageBase64 options:NSDataBase64DecodingIgnoreUnknownCharacters];
    self.starImage = [UIImage imageWithData:imageData scale:3];
    self.backgroundColor = [UIColor clearColor];
    self.starColor = [UIColor orangeColor];
    self.unstarColor = [UIColor lightGrayColor];
    self.numberOfStars = 5;
    self.scorePerStar = 1;
    self.starSpace = -1;
    self.horiInset = 10;
    self.canBeZero = YES;
}

#define RedrawWithVar(var, ...) if (_##var != var) { \
_##var = var; \
{__VA_ARGS__; }\
[self setNeedsDisplay]; \
}
- (void)setStarImage:(UIImage *)starImage {
    RedrawWithVar(starImage, [self sizeToFit]);
}

- (void)setStarImageForHalf:(UIImage *)starImageForHalf {
    RedrawWithVar(starImageForHalf);
}

- (void)setUnstarImage:(UIImage *)unstarImage {
    RedrawWithVar(unstarImage);
}

- (void)setStarSpace:(CGFloat)starSpace {
    RedrawWithVar(starSpace, [self sizeToFit]);
}

- (void)setHoriInset:(CGFloat)horiInset {
    RedrawWithVar(horiInset);
}

- (void)setNumberOfStars:(NSInteger)numberOfStars {
    RedrawWithVar(numberOfStars, [self sizeToFit]);
}

- (void)setCurrentScore:(CGFloat)currentScore {
    currentScore = floorf(MIN(currentScore, self.numberOfStars) / self.scoreMinPace) * self.scoreMinPace;
    if (!self.canBeZero) {
        currentScore = MAX(currentScore, self.scoreMinPace);
    }
    RedrawWithVar(currentScore);
}

- (void)setScoreMinPace:(CGFloat)scoreMinPace {
    if (scoreMinPace >= 1) {
        scoreMinPace = floor(scoreMinPace);
    } else {
        scoreMinPace = MIN(MAX(0.1, scoreMinPace), 0.5);
    }

    if (_scoreMinPace != scoreMinPace) {
        _scoreMinPace = scoreMinPace;
        [self setCurrentScore:self.currentScore];
    }
}

#undef SetPropertyAndSizeToFit

- (CGSize)intrinsicContentSize {
    return [self sizeThatFits:CGSizeZero];
}

- (void)sizeToFit {
    self.bounds = (CGRect){CGPointZero, [self sizeThatFits:CGSizeZero]};
}

- (CGSize)sizeThatFits:(CGSize)size {
    return CGSizeMake(self.starImage.size.width * self.numberOfStars + MAX(self.numberOfStars - 1, 0) * self.starSpace + self.horiInset * 2,
                      self.starImage.size.height);
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGFloat left = self.horiInset;
    CGSize imageSize = self.starImage.size;
    for (NSInteger i = 0; i < self.numberOfStars; i++) {
        UIImage *image = self.starImage;;
        if (i <= self.currentScore - 1) {
            image = self.starImage;
        } else if (i > ceilf(self.currentScore - 1)) {
            image = self.unstarImage ?: self.starImage;
        } else {
            image = self.starImageForHalf ?: self.starImage;
        }
        CGRect rect = CGRectMake(left, 0, imageSize.width, imageSize.height);
        [image drawInRect:rect];
        left = CGRectGetMaxX(rect) + self.starSpace;
    }

    if (!self.unstarImage) {
        NSInteger spaceCount = MAX(ceilf(self.currentScore) - 1, 0);
        CGFloat starColorWidth = self.horiInset + spaceCount * self.starSpace + self.starImage.size.width * self.currentScore;
        [self.unstarColor set];
        UIRectFillUsingBlendMode(CGRectMake(starColorWidth, 0, CGRectGetWidth(self.bounds) - starColorWidth, CGRectGetHeight(self.bounds)),
                                 kCGBlendModeSourceIn);
        [self.starColor set];
        UIRectFillUsingBlendMode(CGRectMake(0, 0, starColorWidth, CGRectGetHeight(self.bounds)), kCGBlendModeSourceIn);
    }
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self calculateScoreAtLocation:[[touches anyObject] locationInView:self]];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self calculateScoreAtLocation:[[touches anyObject] locationInView:self]];
}

- (void)calculateScoreAtLocation:(CGPoint)location {
    CGFloat locationX = MIN(MAX(location.x - self.horiInset, 0), CGRectGetWidth(self.bounds));
    NSInteger intPart = 0;
    CGFloat decimalPart = 0;
    if (self.scoreMinPace >= self.scorePerStar) {
        intPart = ceilf(locationX / (self.starImage.size.width + self.starSpace));
    } else if (self.scoreMinPace == .5 * self.scorePerStar) {
        intPart = floorf(locationX / (self.starImage.size.width + self.starSpace));
        decimalPart = MIN((locationX - intPart * (self.starImage.size.width + self.starSpace)) / self.starImage.size.width, 1);
        if (decimalPart >= .5) {
            decimalPart = 1;
        } else {
            decimalPart = .5;
        }
    } else {
        intPart = floorf(locationX / (self.starImage.size.width + self.starSpace));
        decimalPart = MIN((locationX - intPart * (self.starImage.size.width + self.starSpace)) / self.starImage.size.width, 1);
    }
    self.currentScore = intPart + decimalPart;
    !self.didEvaluateBlock ?: self.didEvaluateBlock(self.currentScore);
}

- (CGFloat)scoreMinPace {
    if (_scoreMinPace) {
        return _scoreMinPace;
    }
    if (self.unstarImage && self.starImageForHalf) {
        return .5 * self.scorePerStar;
    }
    return self.scorePerStar;
}

- (CGFloat)starSpace {
    if (_starSpace <= 0) {
        return self.starImage.size.width / 2;
    }
    return _starSpace;
}

@end

實(shí)現(xiàn):

//
//  ViewController.m
//  TTStarEvaluationView
//
//  Created by rollingstoneW on 2018/9/7.
//  Copyright ? 2018年 demo. All rights reserved.
//

#import "ViewController.h"
#import "TTStarEvaluationView.h"
#import "XHStarRateView.h"
@interface ViewController ()<XHStarRateViewDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];


    TTStarEvaluationView *star = [[TTStarEvaluationView alloc] init];
    star.starImage = [UIImage imageNamed:@"star"];
    star.starImageForHalf = [UIImage imageNamed:@"half-star"];
    star.unstarImage = [UIImage imageNamed:@"unstar"];
    star.currentScore = 2;
    star.center = CGPointMake(self.view.center.x, self.view.center.y - 30);
    [self.view addSubview:star];

    UILabel *label1 = [[UILabel alloc] init];
    label1.center = CGPointMake(star.center.x, star.center.y + 40);
    [self.view addSubview:label1];
    star.didEvaluateBlock = ^(CGFloat score) {
        label1.text = [NSString stringWithFormat:@"%.1f分", score];
        [label1 sizeToFit];
    };
    star.didEvaluateBlock(star.currentScore);

    TTStarEvaluationView *star2 = [[TTStarEvaluationView alloc] init];
    star2.starImage = [UIImage imageNamed:@"star"];
    star2.scoreMinPace = 1;
    star2.scorePerStar = 1;
    star2.starSpace = 20;
    star2.center = CGPointMake(self.view.center.x, self.view.center.y + 60);
    [self.view addSubview:star2];

    UILabel *label2 = [[UILabel alloc] init];
    label2.center = CGPointMake(star2.center.x, star2.center.y + 40);
    [self.view addSubview:label2];
    star2.didEvaluateBlock = ^(CGFloat score) {
        label2.text = [NSString stringWithFormat:@"%.1f分", score];
        [label2 sizeToFit];
    };
    star2.didEvaluateBlock(star2.currentScore);
    
    
    for (int i=0; i<2; i++) {
        
        XHStarRateView *starRateView = [[XHStarRateView alloc] initWithFrame:CGRectMake(50, (50 + 8) * i/1 + 60, 180, 50)];
        starRateView.isAnimation = YES;
        starRateView.rateStyle = WholeStar;
        starRateView.tag = I;
        starRateView.delegate = self;
        
        [self.view addSubview:starRateView];
    }
    
}

#pragma mark - XHStarRateViewDelegate
-(void)starRateView:(XHStarRateView *)starRateView currentScore:(CGFloat)currentScore{
    //NSLog(@"%ld----  %f",starRateView.tag,currentScore);
    NSString *appraise_res = [NSString stringWithFormat:@"%d",(int)currentScore];
    
    
}


@end
1041695378440_.pic.jpg

注意:圖片換成自己的

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容