iOS实现支持小数的星星评分组件实例代码

2020-01-21 00:06:24王冬梅

前言

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

实现后效果如下:

ios,星星评分显示,星星评分控件,星星评分

单个星星的实现

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

ios,星星评分显示,星星评分控件,星星评分

之后,我们就可以按百分比裁剪图片


+ (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;
}