本文转载至 http://blog.csdn.net/hanhailong726188/article/details/42344131

由于项目的需要,需要设计能评分、能显示评分数据的星级评分条,但是IOS上好像没有这个控件,Android是有RatingBar这个控件的(又发现一个IOS不如Android好的),那就只能自定义了,在网上也找了相关的例子,发现都是很老的版本了,非ARC版本的,而且不能评分成0分,还没有indicator效果,于是我自己重新写了一个控件,命名为RatingBar

先上一张我们做之后的效果图:

第一步:

写一个继承自UIView的RatingBar子控件

第二步:

声明一个RatingBar修改评分的代理,就是评分修改后把最新的评分告诉对方

第三步:

在.h文件中声明一些要暴漏给别人调用的方法

第四步:

在.m文件中实现评分条

具体代码如下:

RatingBar.h文件代码

//
//  RatingBar.h
//
//  Created by HailongHan on 15/1/1.
//  Copyright (c) 2015年 cubead. All rights reserved.
//

#import <UIKit/UIKit.h>

/**
 *  星级评分条代理
 */
@protocol RatingBarDelegate <NSObject>

/**
 *  评分改变
 *
 *  @param newRating 新的值
 */
- (void)ratingChanged:(float)newRating;

@end

@interface RatingBar : UIView

/**
 *  初始化设置未选中图片、半选中图片、全选中图片,以及评分值改变的代理(可以用
 *  Block)实现
 *
 *  @param deselectedName   未选中图片名称
 *  @param halfSelectedName 半选中图片名称
 *  @param fullSelectedName 全选中图片名称
 *  @param delegate          代理
 */
- (void)setImageDeselected:(NSString *)deselectedName halfSelected:(NSString *)halfSelectedName fullSelected:(NSString *)fullSelectedName andDelegate:(id<RatingBarDelegate>)delegate;

/**
 *  设置评分值
 *
 *  @param rating 评分值
 */
- (void)displayRating:(float)rating;

/**
 *  获取当前的评分值
 *
 *  @return 评分值
 */
- (float)rating;

/**
 *  是否是指示器,如果是指示器,就不能滑动了,只显示结果,不是指示器的话就能滑动修改值
 *  默认为NO
 */
@property (nonatomic,assign) BOOL isIndicator;

@end

代码中注释的很详细了,这我就不多解释了,看注释吧,真看不懂,阿门,我也救不了你!废话不多说,再贴RatingBar.m文件代码:

//  RatingBar.m
//
//  Created by HailongHan on 15/1/1.
//  Copyright (c) 2015年 cubead. All rights reserved.
//

#import "RatingBar.h"

@interface RatingBar (){
    float starRating;
    float lastRating;
    
    float height;
    float width;
    
    UIImage *unSelectedImage;
    UIImage *halfSelectedImage;
    UIImage *fullSelectedImage;
}

@property (nonatomic,strong) UIImageView *s1;
@property (nonatomic,strong) UIImageView *s2;
@property (nonatomic,strong) UIImageView *s3;
@property (nonatomic,strong) UIImageView *s4;
@property (nonatomic,strong) UIImageView *s5;

@property (nonatomic,weak) id<RatingBarDelegate> delegate;

@end

@implementation RatingBar

/**
 *  初始化设置未选中图片、半选中图片、全选中图片,以及评分值改变的代理(可以用
 *  Block)实现
 *
 *  @param deselectedName   未选中图片名称
 *  @param halfSelectedName 半选中图片名称
 *  @param fullSelectedName 全选中图片名称
 *  @param delegate          代理
 */
-(void)setImageDeselected:(NSString *)deselectedName halfSelected:(NSString *)halfSelectedName fullSelected:(NSString *)fullSelectedName andDelegate:(id<RatingBarDelegate>)delegate{
        
    self.delegate = delegate;
    
    unSelectedImage = [UIImage imageNamed:deselectedName];
    halfSelectedImage = halfSelectedName == nil ? unSelectedImage : [UIImage imageNamed:halfSelectedName];
    fullSelectedImage = [UIImage imageNamed:fullSelectedName];
    
    height = 0.0,width = 0.0;
    
    if (height < [fullSelectedImage size].height) {
        height = [fullSelectedImage size].height;
    }
    if (height < [halfSelectedImage size].height) {
        height = [halfSelectedImage size].height;
    }
    if (height < [unSelectedImage size].height) {
        height = [unSelectedImage size].height;
    }
    if (width < [fullSelectedImage size].width) {
        width = [fullSelectedImage size].width;
    }
    if (width < [halfSelectedImage size].width) {
        width = [halfSelectedImage size].width;
    }
    if (width < [unSelectedImage size].width) {
        width = [unSelectedImage size].width;
    }
    
    starRating = 0.0;
    lastRating = 0.0;
    
    _s1 = [[UIImageView alloc] initWithImage:unSelectedImage];
    _s2 = [[UIImageView alloc] initWithImage:unSelectedImage];
    _s3 = [[UIImageView alloc] initWithImage:unSelectedImage];
    _s4 = [[UIImageView alloc] initWithImage:unSelectedImage];
    _s5 = [[UIImageView alloc] initWithImage:unSelectedImage];
    
    [_s1 setFrame:CGRectMake(0,         0, width, height)];
    [_s2 setFrame:CGRectMake(width,     0, width, height)];
    [_s3 setFrame:CGRectMake(2 * width, 0, width, height)];
    [_s4 setFrame:CGRectMake(3 * width, 0, width, height)];
    [_s5 setFrame:CGRectMake(4 * width, 0, width, height)];
    
    [_s1 setUserInteractionEnabled:NO];
    [_s2 setUserInteractionEnabled:NO];
    [_s3 setUserInteractionEnabled:NO];
    [_s4 setUserInteractionEnabled:NO];
    [_s5 setUserInteractionEnabled:NO];
    
    [self addSubview:_s1];
    [self addSubview:_s2];
    [self addSubview:_s3];
    [self addSubview:_s4];
    [self addSubview:_s5];
    
    CGRect frame = [self frame];
    frame.size.width = width * 5;
    frame.size.height = height;
    [self setFrame:frame];
    
}

/**
 *  设置评分值
 *
 *  @param rating 评分值
 */
-(void)displayRating:(float)rating{
    [_s1 setImage:unSelectedImage];
    [_s2 setImage:unSelectedImage];
    [_s3 setImage:unSelectedImage];
    [_s4 setImage:unSelectedImage];
    [_s5 setImage:unSelectedImage];
    
    if (rating >= 0.5) {
        [_s1 setImage:halfSelectedImage];
    }
    if (rating >= 1) {
        [_s1 setImage:fullSelectedImage];
    }
    if (rating >= 1.5) {
        [_s2 setImage:halfSelectedImage];
    }
    if (rating >= 2) {
        [_s2 setImage:fullSelectedImage];
    }
    if (rating >= 2.5) {
        [_s3 setImage:halfSelectedImage];
    }
    if (rating >= 3) {
        [_s3 setImage:fullSelectedImage];
    }
    if (rating >= 3.5) {
        [_s4 setImage:halfSelectedImage];
    }
    if (rating >= 4) {
        [_s4 setImage:fullSelectedImage];
    }
    if (rating >= 4.5) {
        [_s5 setImage:halfSelectedImage];
    }
    if (rating >= 5) {
        [_s5 setImage:fullSelectedImage];
    }
    
    starRating = rating;
    lastRating = rating;
    [_delegate ratingChanged:rating];
}

/**
 *  获取当前的评分值
 *
 *  @return 评分值
 */
-(float)rating{
    return starRating;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    
    if (self.isIndicator) {
        return;
    }
    
    CGPoint point = [[touches anyObject] locationInView:self];
    int newRating = (int) (point.x / width) + 1;
    if (newRating > 5)
        return;
    
    if (point.x < 0) {
        newRating = 0;
    }
    
    if (newRating != lastRating){
        [self displayRating:newRating];
    }
}

@end

将上面的.h和.m拷贝到项目中就可以直接用了,在viewController.m中调用代码如下:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    RatingBar *ratingBar = [[RatingBar alloc] init];
    ratingBar.frame = CGRectMake(100, 100, 200, 50);
    
    [self.view addSubview:ratingBar];
    ratingBar.isIndicator = YES;//指示器,就不能滑动了,只显示评分结果
    [ratingBar setImageDeselected:@"ratingbar_unselected" halfSelected:nil fullSelected:@"ratingbar_selected" andDelegate:self];
}

好了,自定义控件就结束了,谢谢大家!

IOS-一步一步教你自定义评分星级条RatingBar的更多相关文章

  1. IOS-一步一步教你自定义评分星级条RatingBar ——转载的

    由于项目的需要,需要设计能评分.能显示评分数据的星级评分条,但是IOS上好像没有这个控件,Android是有RatingBar这个控件的(又发现一个IOS不如Android好的),那就只能自定义了,在 ...

  2. 一步一步教你实现iOS音频频谱动画(二)

    如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第一篇:一步一步教你实现iOS音频频谱动画(一) 本文是系列文章中的第二篇,上篇讲述了音频播放和频谱数据计算,本篇讲 ...

  3. 一步一步教你实现iOS音频频谱动画(一)

    如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第二篇:一步一步教你实现iOS音频频谱动画(二) 基于篇幅考虑,本次教程分为两篇文章,本篇文章主要讲述音频播放和频谱 ...

  4. 一步一步教你将普通的wifi路由器变为智能广告路由器

    一步一步教你将普通的wifi路由器变为智能广告路由器 相信大家对WiFi智能广告路由器已经不再陌生了,现在很多公共WiFi上网,都需要登录并且验证,这也就是WiFi广告路由器的最重要的功能.大致就是下 ...

  5. 通过Dapr实现一个简单的基于.net的微服务电商系统(九)——一步一步教你如何撸Dapr之OAuth2授权

    Oauth2授权,熟悉微信开发的同学对这个东西应该不陌生吧.当我们的应用系统需要集成第三方授权时一般都会做oauth集成,今天就来看看在Dapr的语境下我们如何仅通过配置无需修改应用程序的方式让第三方 ...

  6. 通过Dapr实现一个简单的基于.net的微服务电商系统(十)——一步一步教你如何撸Dapr之绑定

    如果说Actor是dapr有状态服务的内部体现的话,那绑定应该是dapr对serverless这部分的体现了.我们可以通过绑定极大的扩展应用的能力,甚至未来会成为serverless的基础.最开始接触 ...

  7. 通过Dapr实现一个简单的基于.net的微服务电商系统(十一)——一步一步教你如何撸Dapr之自动扩/缩容

    上一篇我们讲到了dapr提供的bindings,通过绑定可以让我们的程序轻装上阵,在极端情况下几乎不需要集成任何sdk,仅需要通过httpclient+text.json即可完成对外部组件的调用,这样 ...

  8. 一步一步教你编写与搭建自动化测试框架——python篇

    [本文出自天外归云的博客园] 这两天用python写了一个自动化测试框架,取名为Auty.准备用来做Web方面的接口测试,以下为Auty框架一步一步的搭建过程——

  9. 一步一步教你如何在linux下配置apache+tomcat(转)

    一步一步教你如何在linux下配置apache+tomcat   一.安装前准备. 1.   所有组件都安装到/usr/local/e789目录下 2.   解压缩命令:tar —vxzf 文件名(. ...

随机推荐

  1. 八幅漫画理解使用 JSON Web Token 设计单点登录系统

    原文出处: John Wu 上次在<JSON Web Token – 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家 ...

  2. Ubuntu安装使用SS客户端上网

    1.安装shadowsocks sudo apt-get install python-pip pip install shadowsocks 以上代码用root执行效果较好 查找shadowsock ...

  3. android:如何通过自定义工程模板让新建的工程都默认支持lambda表达式

    首先参考这篇文章:自定义Android Studio工程模板,了解如何自定义模板   然后结合我们上一篇文章 android: 在android studio中使用retrolambda的步骤的要点, ...

  4. 使用PostgreSQL存储时序数据

    操作系统 :CentOS7.3.1611_x64 PostgreSQL版本 :9.6 问题描述 在InfluxDB中存储时序数据时,当tag值和时间戳都相同时会执行覆盖操作.在PostgreSQL中能 ...

  5. Long polling failed, will retry in 16 seconds. appId: zeus-guard, cluster: default, namespaces: application, long polling url: null, reason: Get config services failed from···

    当dubbo应用启动之前, 如果apollo 未启动好,那么我们dubbo应用会一直等待,直到apollo准备就绪,注意其中轮询时间是从1,2,3,4,8,14,32, 方式一直增长,单位是s.

  6. 小型IT部门建设之我见

    ​​关于IT团队建设,一般的原则是四大块组成: 1:业务分析师,对接业务部门,把业务需求转变成技术需求               专注于BRS( Business Requirement Speci ...

  7. stale element reference: element is not attached to the page document 异常

    在执行脚本时,有时候引用一些元素对象会抛出如下异常 org.openqa.selenium.StaleElementReferenceException: stale element referenc ...

  8. 每日英语:These Gadgets Aim To Put Some Teeth Into The Internet Of Things

    What the world needs now is a Web-enabled toothbrush. That part is clear to several oral-hygiene com ...

  9. android的左右滑动效果实现-ViewFlipper

    说到android的左右滑动效果我们可以说是在每个应用上面都可以看到这样的效果,不管是微博,还是QQ等.实现左右滑动的方式很多,有ViewPaer(不过这个和需要android-support-v4. ...

  10. 小patch(psu)的打法 -- 实例

      从patch中的readme来. bug:10214450     测试数据:   SQL> create table t (t timestamp); Table created. SQL ...