2014-07-19 48 views
1

我正在创建一个自定义的'星'控件的过程中,你将能够通过一个浮动控件作为评级,即2.5和2.5满分5颗星会变成红色,其余变成灰色。Clip CGPath并填充两种不同的颜色

我正在使用带有5分的UIBezier路径绘制星星,这是完美的工作。但是,因为我使用的是花车,所以我需要确保小数点被考虑在内。我认为最好的方法是通过将bezier路径剪切成最终宽度的一部分,然而,这种方法似乎对绘图本身没有任何影响;星星是正常绘制的,没有考虑小数。

正如你可能期望的那样,我确实只是刚刚开始涉足CoreGraphics,并希望解释为什么我的方法不起作用,并有一种方法来解决它,以帮助我的进展该框架。

期待听到一些回应!

- (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context { 
    float width = MKRGlyphSize; 

    CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width); 
    CGFloat yCenter = yOrigin + (0.5 * width); 

    double r = width/2.0; 
    float flip = -1.0; 

    for (NSUInteger i = 0; i < maxRating; i++) { 
     CGContextSaveGState(context); 
     if (i < rating) { 
      if (self.selected) { 
       CGContextSetFillColorWithColor(context, RGB(125, 212, 67).CGColor); 
      } 
      else { 
       CGContextSetFillColorWithColor(context, RGB(215, 35, 32).CGColor); 
      } 
     } 
     else { 
      if (self.selected) { 
       CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 
      } 
      else { 
       CGContextSetFillColorWithColor(context, RGB(178, 178, 178).CGColor); 
      } 
     } 

     double theta = 2.0 * M_PI * (2.0/5.0); 
     UIBezierPath *bezier = [UIBezierPath bezierPath]; 
     [bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)]; 

     for (NSUInteger k = 1; k < 5; k++) { 
      float x = r * sin(k * theta); 
      float y = r * cos(k * theta); 
      [bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)]; 
     } 
     [bezier setLineWidth:1.0f]; 
     [bezier setLineJoinStyle:kCGLineJoinMiter]; 
     [bezier closePath]; 
     [bezier fill]; 
     if (rating - floorf(rating) > 0) { 
      CGRect clipRect = CGRectMake(xCenter, yOrigin, width * (rating - floorf(rating)), width); 
      CGContextClipToRect(context, clipRect); 
     } 
     xCenter += width; 
     CGContextRestoreGState(context); 
    } 
} 
+0

使用绘图是矫枉过正。除非你这样做来提高你的技能,否则我会建议使用许多可用的星级评定控件之一。如果你自己做,不要远离绘画,那是不正确的。 – duci9y

+0

控件将在自定义绘制的表格视图单元格中,所以不幸的是这是唯一的方法 – user43211

+0

不可以,您仍然可以在不绘制的情况下工作。 – duci9y

回答

0

我注意到的一个问题是你只有一条路径[fill]。这意味着对于小数星星,你只会看到恒星的一半,而不是另一半。在下面的代码中,每颗星星都充满了白色,然后如果星星的任何部分都在额定值内,则它再次充满蓝色。

我还注意到,您正在使用的剪裁矩形在xCenter处开始其X,而不是星形的左侧。

我也调整了一下数学来计算每个恒星的填充百分比更一致。

- (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context { 
    float width = MKRGlyphSize; 

    CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width); 
    CGFloat yCenter = yOrigin + (0.5 * width); 

    double r = width/2.0; 
    float flip = -1.0; 

    for (NSUInteger i = 0; i < maxRating; i++) { 
     CGContextSaveGState(context); 

     // for clarity, i removed the colors from the top 
     // and ignore selected state. i use blue/white 
     // colors hard coded below 
     // 
     // you can easily change those colors just as you 
     // had before 

     // create star path 
     double theta = 2.0 * M_PI * (2.0/5.0); 
     UIBezierPath *bezier = [UIBezierPath bezierPath]; 
     [bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)]; 
     for (NSUInteger k = 1; k < 5; k++) { 
      float x = r * sin(k * theta); 
      float y = r * cos(k * theta); 
      [bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)]; 
     } 
     [bezier setLineWidth:1.0f]; 
     [bezier setLineJoinStyle:kCGLineJoinMiter]; 
     [bezier closePath]; 

     // fill background of star with white 
     [[UIColor whiteColor] setFill]; 
     [bezier fill]; 

     // calculate the percentage of this star 
     // that we should fill 
     CGFloat currStar = i; 
     CGFloat percentOfStar; 
     if(rating > currStar){ 
      // at least some of the star should be filled 
      percentOfStar = rating - currStar > 0 ? rating - currStar : 0; 
      percentOfStar = percentOfStar > 1 ? 1 : percentOfStar; 
     }else{ 
      // none of the star should be filled 
      percentOfStar = 0; 
     } 
     if (percentOfStar) { 
      // if we need at least a little filling, then clip to that % of the star 
      // notice (xCenter - .5*width) to align the clipRect to the left side of 
      // the star. 
      // now fill the selected portion of the star with blue 
      CGRect clipRect = CGRectMake(xCenter - .5*width, yOrigin, width * (percentOfStar), width); 
      CGContextClipToRect(context, clipRect); 
      [[UIColor blueColor] setFill]; 
      [bezier fill]; 
     } 
     xCenter += width; 
     CGContextRestoreGState(context); 
    } 
} 
0

你可以做到这一点略有不同:

填充背景色

您的视图的背景使用percentOfStar创建一个反映评级的矩形路径。

使用星形路径进行剪辑。