ios开发——滑动星型评分控件的实现
时间:2014-12-04 08:50:07
收藏:0
阅读:453
在App Store或者其他一些应用中我们可以通过点击或滑动星星来给应用评分,效果图如下
现在我们来实现这一功能。
首先我们需要准备两张图片作为素材,一个是灰色背景星星,另一个是黄色星星表示评分。
(亮色星星)
(暗色星星)
实际操作中可以用自己需要的图片替代。
接着,我们建立自己的类继承View,来实现这个评分视图,这里假设起名为CYZStarRageView。现在来看一下头文件
@class CYZStarRateView; @protocol CYZStarRateViewDelegate <NSObject> /** * 通知代理改变评分到某一特定的值 * * @param starRateView 指当前评分view * @param percentage 新的评分值 */ - (void)starRateView:(CYZStarRateView *)starRateView didChangedScorePercentageTo:(CGFloat)percentage; @end @interface CYZStarRateView : UIView /** * 代理 */ @property (weak, nonatomic) id<CYZStarRateViewDelegate> delegate; /** * 是否使用动画,默认为NO */ @property (assign, nonatomic) BOOL shouldUseAnimation; /** * 是否允许非整型评分,默认为NO */ @property (assign, nonatomic) BOOL allowIncompleteStar; /** * 是否允许用户手指操作评分,默认为YES */ @property (assign, nonatomic) BOOL allowUserInteraction; /** * 当前评分值,范围0---1,表示的是黄色星星占的百分比,默认为1 */ @property (assign, nonatomic) CGFloat percentage; /** * 初始化方法,需传入评分星星的总数 * * @param frame 该starView的大小与位置 * @param count 评分星星的数量 * * @return 实例变量 */ - (id)initWithFrame:(CGRect)frame starCount:(NSInteger)count; /** * 设置当前评分为某一值,是否使用动画取决于shouldUseAnimation属性的取值 * * @param score 新的评分值 */ - (void)setScore:(CGFloat)score;
首先写一个协议,当评分更改后会触发该协议方法。其次,对于这个类,设立一些属性来控制相应的功能。例如:是否允许非整型评分,是否允许用户交互,是否设立动画等等。同时需要一个初始化方法,在这里传入星星的数量。应用时可以通过直接设置percentage属性或者通过调用setScore方法来设置,实质上这两个是一样的。
关键代码:
一、初始化方法。
在初始化方法中,为私有变量starCount赋值,计算出每个星星的宽度以便之后初始化子视图用。接着对默认值、子视图、手势进行初始化。为了让该方法保持“整洁”,将后面的一系列操作封装到一个私有方法- (void)initStarView 中。
- (id)initWithFrame:(CGRect)frame starCount:(NSInteger)count {
self = [super initWithFrame:frame];
if (self) {
self.starCount = count;
self.starWidth = (CGFloat)self.frame.size.width / self.starCount;
[self initStarView];
}
return self;
}initStarView方法:
- (void)initStarView {
//默认值
self.percentage = 1.0f;
self.shouldUseAnimation = NO;
self.allowIncompleteStar = NO;
self.allowUserInteraction = YES;
//星星视图
self.lightStarView = [self starViewWithImageName:LIGHT_STAR_IMAGE_NAME];
self.grayStarView = [self starViewWithImageName:DARK_STAR_IMAGE_NAME];
[self addSubview:self.grayStarView];
[self addSubview:self.lightStarView];
//此处用pan手势,达到用户可以滑动手指评分的效果
self.pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self addGestureRecognizer:self.pan];
}二、添加子视图方法
之前在初始化方法中已经获得了评分星星的总数量,接着将相应数量的星星添加到该视图中即可。
- (UIView *)starViewWithImageName:(NSString *)imageName {
UIView *view = [[UIView alloc] initWithFrame:self.bounds];
view.clipsToBounds = YES;
view.backgroundColor = [UIColor clearColor];
//添加星星
for (int i = 0; i < self.starCount; i++) {
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(i * self.starWidth, 0, self.starWidth, self.bounds.size.height)];
iv.image = [UIImage imageNamed:imageName];
iv.contentMode = UIViewContentModeScaleAspectFit;
[view addSubview:iv];
}
return view;
}设置view的clipsToBounds属性来达到记下来评分的效果。注意到之前的初始化方法中得到了gray视图和light视图后,添加子视图的顺序不能变。我们要做的就是根据评分让亮星星覆盖暗星星.
三、手势的相应方法
这里算是比较核心的代码了,为了实现手指滑动评分,我们选择的方法是添加pan手势(如果不要这个功能,简单的tap手势即可)。所以在这里我们根据手势的状态进行相应的计算和操作
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
static CGFloat startX = 0;
CGFloat starScorePercentage = 0;
if (recognizer.state == UIGestureRecognizerStateBegan) {
startX = [recognizer locationInView:self].x;
starScorePercentage = startX / self.starWidth;
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CGFloat location = [recognizer translationInView:self].x + startX;
starScorePercentage = location / self.starWidth;
} else {
return;
}
CGFloat realScore = self.allowIncompleteStar ? starScorePercentage : ceilf(starScorePercentage);
self.percentage = realScore / self.starCount;
}思路是,记录起点,记录偏移量,计算偏移量是单位星星宽度的多少倍,然后根据是否允许非整形评分来计算实际倍数,用该值去除以总数即可得到范围为0-1的评分。给percentage赋值即可,接下来可以看到,我们在percentage的setter中将进行额外的操作。
四、setter
直接贴上代码:
- (void)setPercentage:(CGFloat)percentage {
if (percentage >= 1) {
_percentage = 1;
} else if (percentage < 0) {
_percentage = 0;
} else {
_percentage = percentage;
}
[self setNeedsLayout];
if ([self.delegate respondsToSelector:@selector(starRateView:didChangedScorePercentageTo:)]) {
[self.delegate starRateView:self didChangedScorePercentageTo:_percentage];
}
}
这里主要是对数值的合理性检验,调用代理,以及通知view进行重新布局。在布局方法中我们真正实现评分的效果
五、layoutSubview方法
- (void)layoutSubviews {
[super layoutSubviews];
__weak CYZStarRateView *weakSelf = self;
CGFloat duration = self.shouldUseAnimation ? DEFAULT_DURATION : 0.0f;
[UIView animateWithDuration:duration animations:^{
weakSelf.lightStarView.frame = CGRectMake(0, 0, weakSelf.percentage * weakSelf.bounds.size.width, weakSelf.bounds.size.height);
}];
}通过改变lightStarView的frame来改变亮星星的显示个数和范围,露出下面的灰色星星。这样就达到我们想要的效果了。
原文:http://blog.csdn.net/u013604612/article/details/41707617
评论(0)