前言
评分功能是我们大家都不陌生的一个功能,现在在很多电商,外卖,餐饮型应用里随处可见,都会在商品结束后评价中有一个星星组件。核心思路就是用UIControl并自定义实现其中的trackTouch的几个方法。而显示不到一个的星星,比如半个星星的思路是根据分数切割星星的图像并显示其中一部分。
实现后效果如下:

单个星星的实现
对于单个星星的实现,先考虑星星有三个状态,完全置灰状态,完全高亮状态,根据百分比半高亮状态。而我这边用的是UIButton来实现,因为UIButton本身已经有普通,高亮,选择的状态。主要实现的就是百分比高亮状态。我们可以根据百分比将图像进行裁剪,让新图像的宽度只有百分比所占的整个图像的宽度。但是这时候调用setImage,会发现图片处于整个button中间。这是因为UIButton的imageView的contentMode默认是AspectFit的,而AspectFit是默认居中的。Contentmode中的UIViewContentModeLeft,是不会把长边缩放到imageView的边长的。况且,直接改变UIButton里的ImageView的ContentMode是没有效果的。要通过UIControl的contentVerticalAlignment属性(垂直)和contentHorizontalAlignment属性(水平)来达到类似ImageView的contentMode的效果。但是这两个属性都没有带Fit后缀的选项,也就是说并不会根据边长等比缩放。所以需要先把图片缩放到和Button大小一致。

之后,我们就可以按百分比裁剪图片
+ (UIImage *)croppedImage:(UIImage *)image fraction:(CGFloat)fractonPart{
CGFloat width = image.size.width * fractonPart * image.scale;
CGRect newFrame = CGRectMake(0, 0, width , image.size.height * image.scale);
CGImageRef resultImage = CGImageCreateWithImageInRect(image.CGImage, newFrame);
UIImage *result = [UIImage imageWithCGImage:resultImage scale:image.scale orientation:image.imageOrientation];
CGImageRelease(resultImage);
return result;
}
并在BackgroundImage设置为灰色的星星图像,设置为Button的highlighted状态
- (void)setFractionPart:(CGFloat)fractionPart{
if (fractionPart == 0) {
return;
}
UIImage *image = [CDZStarButton croppedImage:self.highlightedImage fraction:fractionPart];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
self.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[self setImage:image forState:UIControlStateHighlighted];
[self setBackgroundImage:self.normalImage forState:UIControlStateHighlighted];
self.selected = NO;
self.highlighted = YES;
}










