IOS-一步一步教你自定义评分星级条RatingBar

本文转载至 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];
}

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

时间: 2024-08-14 05:36:46

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

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

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

Android自定义View(四)----一步一步教你实现QQ健康界面

最近一直在学习自定义View相关的知识,今天给大家带来的是QQ健康界面的实现.先看效果图: 可以设置数字颜色,字体颜色,运动步数,运动排名,运动平均步数,虚线下方的蓝色指示条的长度会随着平均步数改变而进行变化.整体效果还是和QQ运动健康界面很像的. 自定义View四部曲,一起来看看怎么实现的. 1.自定义view的属性: <?xml version="1.0" encoding="utf-8"?> <resources> //自定义属性名,定

只需 4 步,手把手教你如何实现滤镜功能

源地址:http://zihua.li/2014/06/implement-instagram-like-filters/ 滤镜对于照片而言,起到的是雪中送炭和锦上添花的作用.优秀的滤镜,能让随手之作显得别有风味,又能为已经绝色的照片画龙点睛.现在几乎凡是和照片相关的应用程序都有滤镜功能,而相较而言介绍滤镜原理和实现的文章又少之又少,为此我专门写了这篇文章来系统地讲解滤镜是如何实现的. 什么是滤镜 滤镜最初是指安装在相机镜头前过滤自然光的附加镜头,用来实现调色和添加效果.一些数字图像处理软件(最

一步一步学ios UITextView(多行文本框)控件的用法详解(五5.8)

本文转载至 http://wuchaorang.2008.blog.163.com/blog/static/48891852201232014813990/ 1.创建并初始化 创建UITextView的文件,并在.h文件中写入如下代码: [csharp] view plaincopy #import <UIKit/UIKit.h> @interface TextViewController : UIViewController <UITextViewDelegate> { UITe

教你一步一步实现图标无缝变形切换

我的简书同步发布:教你一步一步实现图标无缝变形切换 ?欢迎打赏? 转载请注明出处:[huachao1001的专栏:http://blog.csdn.net/huachao1001] 本来这篇文章几天前就应该写好并发布出来的,由于要写小论文,被导师劈头盖脸的骂了几天,一直在搞论文,耽误了博文的编写.今天终于把小论文给投出去了,终于可以好好写博客了! 在上一篇文章<酷炫的Activity切换动画,打造更好的用户体验 >中,我们感受到了过渡切换动画带来的不一样的用户体验.如何你还意犹未尽,那么今天我

一步一步实现iOS应用PUSH功能

1. push原理 iOS push 工作机制可以用下图简要概括 Provider:应用自己的服务器: APNS:Apple Push Notification Service的简称,苹果的PUSH服务器: push的主要工作流程是: iOS设备连接网络后,会自动与APNS保持类似TCP的长链接,等待APNS推送消息的到来: 应用启动时注册消息推送,并获取设备的在APNS中注册的唯一设备标示deviceToken上传给应用服务器(即Provider): 在需要给应用推送消息时,Provider把

一步一步教你在 Android 里创建自己的账号系统(二)--同步数据以及设计账号页面

大家如果喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 在前一篇文章中(一步一步教你在 Android 里创建自己的账号系统(一)),我向大家介绍了如何在 Android 系统中创建自己的账户系统,接下来我会向大家详细介绍一下如何使用账户系统. (一)同步数据 通常而言,我们会在两种情况下使用我们的账号系统: (1)登陆验证 登陆验证其实是一个很实用的功能,试

一步一步跟我学习lucene(13)---lucene搜索之自定义排序的实现原理和编写自己的自定义排序工具

自定义排序说明 我们在做lucene搜索的时候,可能会需要排序功能,虽然lucene内置了多种类型的排序,但是如果在需要先进行某些值的运算然后在排序的时候就有点显得无能为力了: 要做自定义查询,我们就要研究lucene已经实现的排序功能,lucene的所有排序都是要继承FieldComparator,然后重写内部实现,这里以IntComparator为例子来查看其实现: IntComparator相关实现 其类的声明为 public static class IntComparator exte

教你一步一步部署.net免费空间OpenShift系列之一------帐号注册和验证

前几天有博友发布了一篇文章<一键部署mono 免费空间支持ASP.NET MVC 再也不担心伙食费换空间了>,支持MVC3和域名绑定,觉得不错,于是自己实践了一下,发现自己实际遇到的问题真不少,而且网上的关于此空间的帖子要么千篇一律,要么语焉不详,现总结为图文教程系列 帐号注册和验证 打开https://www.openshift.com/products/pricing,出现三种选择,前2种是免费的,建议选择第二个. 点击Create one跳转到创建用户界面 看到如下信息,填写邮箱和密码,