而全高亮的状态可以设置为UIButtonde点击态
- (void)setHighlightedImage:(UIImage *)highlightedImage{
_highlightedImage = [CDZStarButton reSizeImage:highlightedImage toSize:self.frame.size];
[self setImage:_highlightedImage forState:UIControlStateSelected];
}
而点击事件交由给上层的UIControl去处理,因为点击的时候,除了点击的星星本身,之前的星星也应该处于完全高亮状态。在上层初始化按钮的时候把其userInteractionEnabled属性设置为NO即可,这样触摸事件就会忽略传递到Button去做事件处理,从而从响应者链传递上去交由父视图的UIControl处理。
如果点击到星星的一半,我们应该把点击点转换成小数部分给上层。C语言的round函数可以四舍五入,这里的10代表保留一位小数,可以根据实际情况保留位数,一般评分很少需要更高精度的。
- (CGFloat)fractionPartOfPoint:(CGPoint)point{
CGFloat fractionPart = (point.x - self.frame.origin.x) / self.frame.size.width;
return round(fractionPart * 10) / 10;
}
到这里一个可以显示分数的星星按钮就完成了,接下来就是在上层的UIControl去处理触摸事件的响应。
UIControl部分的实现
主要分两块,星星按钮的布局,触摸事件响应。
布局
首先根据星星的数量一个个添加上视图,用UIView的tag来表示对应第几个星星按钮。
- (void)setupView {
for (NSInteger index = 0; index < self.numberOfStars; index++) {
CDZStarButton *starButton = [CDZStarButton.alloc initWithSize:self.starSize];
starButton.tag = index;
starButton.normalImage = self.normalStarImage;
starButton.highlightedImage = self.highlightedStarImage;
starButton.userInteractionEnabled = NO;//关闭事件响应,交由UIControl本身处理
[self addSubview:starButton];
}
}
然后是计算每个星星的位置,计算间隔和上下边距并layout
- (void)layoutSubviews {
[super layoutSubviews];
for (NSInteger index = 0; index < self.numberOfStars; index ++) {
CDZStarButton *starButton = [self starForTag:index];
CGFloat newY = (self.frame.size.height - self.starSize.height) / 2;
CGFloat margin = 0;
if (self.numberOfStars > 1) {
margin = (self.frame.size.width - self.starSize.width * self.numberOfStars) / (self.numberOfStars - 1);
}
starButton.frame = CGRectMake((self.starSize.width + margin) * index, newY, self.starSize.width, self.starSize.height);
}
}
这时,我们可以加上两个方法去找到对应的星星button,根据tag和根据点击的CGPoint
- (CDZStarButton *)starForPoint:(CGPoint)point {
for (NSInteger i = 0; i < self.numberOfStars; i++) {
CDZStarButton *starButton = [self starForTag:i];
if (CGRectContainsPoint(starButton.frame, point)) {
return starButton;
}
}
return nil;
}
- (CDZStarButton *)starForTag:(NSInteger)tag {
__block UIView *target;
[self.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.tag == tag) {
target = obj;
*stop = YES;
}
}];
return (CDZStarButton *)target;
}










