Skip to content
This repository
Browse code

add custom label text

  • Loading branch information...
commit 9bb14e7b373a96cc3dbb0a70b1aa6f5e7aa19292 1 parent f40c0fc
XY Feng authored
1  README.textile
Source Rendered
@@ -46,6 +46,7 @@ Implement Data Source Methods:
46 46 - (NSUInteger)numberOfSlicesInPieChart:(XYPieChart *)pieChart;
47 47 - (CGFloat)pieChart:(XYPieChart *)pieChart valueForSliceAtIndex:(NSUInteger)index;
48 48 - (UIColor *)pieChart:(XYPieChart *)pieChart colorForSliceAtIndex:(NSUInteger)index; //optional
  49 +- (NSString *)pieChart:(XYPieChart *)pieChart textForSliceAtIndex:(NSUInteger)index; //optional
49 50 </pre>
50 51
51 52 Implement  Delegate Methods (OPTIONAL):
7 XYPieChart/XYPieChart.h
@@ -29,19 +29,15 @@
29 29 #import <UIKit/UIKit.h>
30 30
31 31 @class XYPieChart;
32   -
33   -#pragma mark - Data Source Protocol
34   -//Provide value and color for each slice
35 32 @protocol XYPieChartDataSource <NSObject>
36 33 @required
37 34 - (NSUInteger)numberOfSlicesInPieChart:(XYPieChart *)pieChart;
38 35 - (CGFloat)pieChart:(XYPieChart *)pieChart valueForSliceAtIndex:(NSUInteger)index;
39 36 @optional
40 37 - (UIColor *)pieChart:(XYPieChart *)pieChart colorForSliceAtIndex:(NSUInteger)index;
  38 +- (NSString *)pieChart:(XYPieChart *)pieChart textForSliceAtIndex:(NSUInteger)index;
41 39 @end
42 40
43   -#pragma mark - Delegate Protocol
44   -//Method called before and after one slice get selected
45 41 @protocol XYPieChartDelegate <NSObject>
46 42 @optional
47 43 - (void)pieChart:(XYPieChart *)pieChart willSelectSliceAtIndex:(NSUInteger)index;
@@ -50,7 +46,6 @@
50 46 - (void)pieChart:(XYPieChart *)pieChart didDeselectSliceAtIndex:(NSUInteger)index;
51 47 @end
52 48
53   -#pragma mark - Pie Chart
54 49 @interface XYPieChart : UIView
55 50 @property(nonatomic, weak) id<XYPieChartDataSource> dataSource;
56 51 @property(nonatomic, weak) id<XYPieChartDelegate> delegate;
136 XYPieChart/XYPieChart.m
@@ -35,10 +35,12 @@ @interface SliceLayer : CAShapeLayer
35 35 @property (nonatomic, assign) double startAngle;
36 36 @property (nonatomic, assign) double endAngle;
37 37 @property (nonatomic, assign) BOOL isSelected;
  38 +@property (nonatomic, strong) NSString *text;
38 39 - (void)createArcAnimationForKey:(NSString *)key fromValue:(NSNumber *)from toValue:(NSNumber *)to Delegate:(id)delegate;
39 40 @end
40 41
41 42 @implementation SliceLayer
  43 +@synthesize text = _text;
42 44 @synthesize value = _value;
43 45 @synthesize percentage = _percentage;
44 46 @synthesize startAngle = _startAngle;
@@ -48,7 +50,7 @@ - (NSString*)description
48 50 {
49 51 return [NSString stringWithFormat:@"value:%f, percentage:%0.0f, start:%d, end:%d", _value, _percentage, _startAngle/M_PI*180, _endAngle/M_PI*180];
50 52 }
51   -+ (BOOL)needsDisplayForKey:(NSString *)key
  53 ++ (BOOL)needsDisplayForKey:(NSString *)key
52 54 {
53 55 if ([key isEqualToString:@"startAngle"] || [key isEqualToString:@"endAngle"]) {
54 56 return YES;
@@ -74,7 +76,7 @@ - (void)createArcAnimationForKey:(NSString *)key fromValue:(NSNumber *)from toVa
74 76 NSNumber *currentAngle = [[self presentationLayer] valueForKey:key];
75 77 if(!currentAngle) currentAngle = from;
76 78 [arcAnimation setFromValue:currentAngle];
77   - [arcAnimation setToValue:to];
  79 + [arcAnimation setToValue:to];
78 80 [arcAnimation setDelegate:delegate];
79 81 [arcAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]];
80 82 [self addAnimation:arcAnimation forKey:key];
@@ -82,7 +84,7 @@ - (void)createArcAnimationForKey:(NSString *)key fromValue:(NSNumber *)from toVa
82 84 }
83 85 @end
84 86
85   -@interface XYPieChart (Private)
  87 +@interface XYPieChart (Private)
86 88 - (void)updateTimerFired:(NSTimer *)timer;
87 89 - (SliceLayer *)createSliceLayer;
88 90 - (CGSize)sizeThatFitsString:(NSString *)string;
@@ -95,7 +97,7 @@ @implementation XYPieChart
95 97 NSInteger _selectedSliceIndex;
96 98 //pie view, contains all slices
97 99 UIView *_pieView;
98   -
  100 +
99 101 //animation control
100 102 NSTimer *_animationTimer;
101 103 NSMutableArray *_animations;
@@ -116,14 +118,14 @@ @implementation XYPieChart
116 118 @synthesize selectedSliceOffsetRadius = _selectedSliceOffsetRadius;
117 119 @synthesize showPercentage = _showPercentage;
118 120
119   -static CGPathRef CGPathCreateArc(CGPoint center, CGFloat radius, CGFloat startAngle, CGFloat endAngle)
  121 +static CGPathRef CGPathCreateArc(CGPoint center, CGFloat radius, CGFloat startAngle, CGFloat endAngle)
120 122 {
121 123 CGMutablePathRef path = CGPathCreateMutable();
122 124 CGPathMoveToPoint(path, NULL, center.x, center.y);
123   -
  125 +
124 126 CGPathAddArc(path, NULL, center.x, center.y, radius, startAngle, endAngle, 0);
125 127 CGPathCloseSubpath(path);
126   -
  128 +
127 129 return path;
128 130 }
129 131
@@ -136,20 +138,20 @@ - (id)initWithFrame:(CGRect)frame
136 138 _pieView = [[UIView alloc] initWithFrame:frame];
137 139 [_pieView setBackgroundColor:[UIColor clearColor]];
138 140 [self addSubview:_pieView];
139   -
  141 +
140 142 _selectedSliceIndex = -1;
141 143 _animations = [[NSMutableArray alloc] init];
142   -
  144 +
143 145 _animationSpeed = 0.5;
144 146 _startPieAngle = M_PI_2*3;
145 147 _selectedSliceStroke = 3.0;
146   -
  148 +
147 149 self.pieRadius = MIN(frame.size.width/2, frame.size.height/2) - 10;
148 150 self.pieCenter = CGPointMake(frame.size.width/2, frame.size.height/2);
149 151 self.labelFont = [UIFont boldSystemFontOfSize:MAX((int)self.pieRadius/10, 5)];
150 152 _labelRadius = _pieRadius/2;
151 153 _selectedSliceOffsetRadius = MAX(10, _pieRadius/10);
152   -
  154 +
153 155 _showLabel = YES;
154 156 _showPercentage = YES;
155 157 }
@@ -175,21 +177,21 @@ - (id)initWithCoder:(NSCoder *)aDecoder
175 177 _pieView = [[UIView alloc] initWithFrame:self.bounds];
176 178 [_pieView setBackgroundColor:[UIColor clearColor]];
177 179 [self insertSubview:_pieView atIndex:0];
178   -
  180 +
179 181 _selectedSliceIndex = -1;
180 182 _animations = [[NSMutableArray alloc] init];
181   -
  183 +
182 184 _animationSpeed = 0.5;
183 185 _startPieAngle = M_PI_2*3;
184 186 _selectedSliceStroke = 3.0;
185   -
  187 +
186 188 CGRect bounds = [[self layer] bounds];
187 189 self.pieRadius = MIN(bounds.size.width/2, bounds.size.height/2) - 10;
188 190 self.pieCenter = CGPointMake(bounds.size.width/2, bounds.size.height/2);
189 191 self.labelFont = [UIFont boldSystemFontOfSize:MAX((int)self.pieRadius/10, 5)];
190 192 _labelRadius = _pieRadius/2;
191 193 _selectedSliceOffsetRadius = MAX(10, _pieRadius/10);
192   -
  194 +
193 195 _showLabel = YES;
194 196 _showPercentage = YES;
195 197 }
@@ -230,9 +232,9 @@ - (void)setShowPercentage:(BOOL)showPercentage
230 232 if(_showPercentage)
231 233 label = [NSString stringWithFormat:@"%0.0f", layer.percentage*100];
232 234 else
233   - label = [NSString stringWithFormat:@"%0.0f", layer.value];
  235 + label = (layer.text)?layer.text:[NSString stringWithFormat:@"%0.0f", layer.value];
234 236 CGSize size = [label sizeWithFont:self.labelFont];
235   -
  237 +
236 238 if(M_PI*2*_labelRadius*layer.percentage < MAX(size.width,size.height))
237 239 {
238 240 [textLayer setString:@""];
@@ -274,66 +276,66 @@ - (void)setSliceDeselectedAtIndex:(NSInteger)index
274 276
275 277 - (void)reloadData
276 278 {
277   - if (_dataSource && !_animationTimer)
  279 + if (_dataSource && !_animationTimer)
278 280 {
279 281 CALayer *parentLayer = [_pieView layer];
280 282 NSArray *slicelayers = [parentLayer sublayers];
281   -
  283 +
282 284 _selectedSliceIndex = -1;
283 285 [slicelayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
284 286 SliceLayer *layer = (SliceLayer *)obj;
285 287 if(layer.isSelected)
286 288 [self setSliceDeselectedAtIndex:idx];
287 289 }];
288   -
  290 +
289 291 double startToAngle = 0.0;
290 292 double endToAngle = startToAngle;
291   -
  293 +
292 294 NSUInteger sliceCount = [_dataSource numberOfSlicesInPieChart:self];
293   -
  295 +
294 296 double sum = 0.0;
295 297 double values[sliceCount];
296 298 for (int index = 0; index < sliceCount; index++) {
297 299 values[index] = [_dataSource pieChart:self valueForSliceAtIndex:index];
298 300 sum += values[index];
299 301 }
300   -
  302 +
301 303 double angles[sliceCount];
302 304 for (int index = 0; index < sliceCount; index++) {
303 305 double div;
304 306 if (sum == 0)
305 307 div = 0;
306 308 else
307   - div = values[index] / sum;
  309 + div = values[index] / sum;
308 310 angles[index] = M_PI * 2 * div;
309 311 }
310 312
311 313 [CATransaction begin];
312 314 [CATransaction setAnimationDuration:_animationSpeed];
313   -
  315 +
314 316 [_pieView setUserInteractionEnabled:NO];
315   -
  317 +
316 318 __block NSMutableArray *layersToRemove = nil;
317 319 [CATransaction setCompletionBlock:^{
318   -
  320 +
319 321 [layersToRemove enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
320 322 [obj removeFromSuperlayer];
321 323 }];
322   -
  324 +
323 325 [layersToRemove removeAllObjects];
324   -
  326 +
325 327 for(SliceLayer *layer in _pieView.layer.sublayers)
326 328 {
327 329 [layer setZPosition:kDefaultSliceZOrder];
328 330 }
329   -
  331 +
330 332 [_pieView setUserInteractionEnabled:YES];
331 333 }];
332   -
  334 +
333 335 BOOL isOnStart = ([slicelayers count] == 0 && sliceCount);
334 336 NSInteger diff = sliceCount - [slicelayers count];
335 337 layersToRemove = [NSMutableArray arrayWithArray:slicelayers];
336   -
  338 +
337 339 BOOL isOnEnd = ([slicelayers count] && (sliceCount == 0 || sum <= 0));
338 340 if(isOnEnd)
339 341 {
@@ -341,17 +343,17 @@ - (void)reloadData
341 343 [self updateLabelForLayer:layer value:0];
342 344 [layer createArcAnimationForKey:@"startAngle"
343 345 fromValue:[NSNumber numberWithDouble:_startPieAngle]
344   - toValue:[NSNumber numberWithDouble:_startPieAngle]
  346 + toValue:[NSNumber numberWithDouble:_startPieAngle]
345 347 Delegate:self];
346   - [layer createArcAnimationForKey:@"endAngle"
  348 + [layer createArcAnimationForKey:@"endAngle"
347 349 fromValue:[NSNumber numberWithDouble:_startPieAngle]
348   - toValue:[NSNumber numberWithDouble:_startPieAngle]
  350 + toValue:[NSNumber numberWithDouble:_startPieAngle]
349 351 Delegate:self];
350 352 }
351 353 [CATransaction commit];
352 354 return;
353 355 }
354   -
  356 +
355 357 for(int index = 0; index < sliceCount; index ++)
356 358 {
357 359 SliceLayer *layer;
@@ -359,7 +361,7 @@ - (void)reloadData
359 361 endToAngle += angle;
360 362 double startFromAngle = _startPieAngle + startToAngle;
361 363 double endFromAngle = _startPieAngle + endToAngle;
362   -
  364 +
363 365 if( index >= [slicelayers count] )
364 366 {
365 367 layer = [self createSliceLayer];
@@ -384,7 +386,7 @@ - (void)reloadData
384 386 }
385 387 else if(diff < 0)
386 388 {
387   - while(diff < 0)
  389 + while(diff < 0)
388 390 {
389 391 [onelayer removeFromSuperlayer];
390 392 [parentLayer addSublayer:onelayer];
@@ -399,7 +401,7 @@ - (void)reloadData
399 401 }
400 402 }
401 403 }
402   -
  404 +
403 405 layer.value = values[index];
404 406 layer.percentage = (sum)?layer.value/sum:0;
405 407 UIColor *color = nil;
@@ -407,21 +409,26 @@ - (void)reloadData
407 409 {
408 410 color = [_dataSource pieChart:self colorForSliceAtIndex:index];
409 411 }
410   -
  412 +
411 413 if(!color)
412 414 {
413 415 color = [UIColor colorWithHue:((index/8)%20)/20.0+0.02 saturation:(index%8+3)/10.0 brightness:91/100.0 alpha:1];
414 416 }
415   -
  417 +
416 418 [layer setFillColor:color.CGColor];
  419 + if([_dataSource respondsToSelector:@selector(pieChart:textForSliceAtIndex:)])
  420 + {
  421 + layer.text = [_dataSource pieChart:self textForSliceAtIndex:index];
  422 + }
  423 +
417 424 [self updateLabelForLayer:layer value:values[index]];
418 425 [layer createArcAnimationForKey:@"startAngle"
419 426 fromValue:[NSNumber numberWithDouble:startFromAngle]
420   - toValue:[NSNumber numberWithDouble:startToAngle+_startPieAngle]
  427 + toValue:[NSNumber numberWithDouble:startToAngle+_startPieAngle]
421 428 Delegate:self];
422   - [layer createArcAnimationForKey:@"endAngle"
  429 + [layer createArcAnimationForKey:@"endAngle"
423 430 fromValue:[NSNumber numberWithDouble:endFromAngle]
424   - toValue:[NSNumber numberWithDouble:endToAngle+_startPieAngle]
  431 + toValue:[NSNumber numberWithDouble:endToAngle+_startPieAngle]
425 432 Delegate:self];
426 433 startToAngle = endToAngle;
427 434 }
@@ -442,25 +449,25 @@ - (void)reloadData
442 449 #pragma mark - Animation Delegate + Run Loop Timer
443 450
444 451 - (void)updateTimerFired:(NSTimer *)timer;
445   -{
  452 +{
446 453 CALayer *parentLayer = [_pieView layer];
447 454 NSArray *pieLayers = [parentLayer sublayers];
448 455
449 456 [pieLayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
450   -
  457 +
451 458 NSNumber *presentationLayerStartAngle = [[obj presentationLayer] valueForKey:@"startAngle"];
452 459 CGFloat interpolatedStartAngle = [presentationLayerStartAngle doubleValue];
453   -
  460 +
454 461 NSNumber *presentationLayerEndAngle = [[obj presentationLayer] valueForKey:@"endAngle"];
455 462 CGFloat interpolatedEndAngle = [presentationLayerEndAngle doubleValue];
456 463
457 464 CGPathRef path = CGPathCreateArc(_pieCenter, _pieRadius, interpolatedStartAngle, interpolatedEndAngle);
458 465 [obj setPath:path];
459 466 CFRelease(path);
460   -
  467 +
461 468 {
462 469 CALayer *labelLayer = [[obj sublayers] objectAtIndex:0];
463   - CGFloat interpolatedMidAngle = (interpolatedEndAngle + interpolatedStartAngle) / 2;
  470 + CGFloat interpolatedMidAngle = (interpolatedEndAngle + interpolatedStartAngle) / 2;
464 471 [CATransaction setDisableActions:YES];
465 472 [labelLayer setPosition:CGPointMake(_pieCenter.x + (_labelRadius * cos(interpolatedMidAngle)), _pieCenter.y + (_labelRadius * sin(interpolatedMidAngle)))];
466 473 [CATransaction setDisableActions:NO];
@@ -474,14 +481,14 @@ - (void)animationDidStart:(CAAnimation *)anim
474 481 static float timeInterval = 1.0/60.0;
475 482 _animationTimer= [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(updateTimerFired:) userInfo:nil repeats:YES];
476 483 }
477   -
  484 +
478 485 [_animations addObject:anim];
479 486 }
480 487
481 488 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)animationCompleted
482 489 {
483 490 [_animations removeObject:anim];
484   -
  491 +
485 492 if ([_animations count] == 0) {
486 493 [_animationTimer invalidate];
487 494 _animationTimer = nil;
@@ -493,16 +500,16 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)animationCompleted
493 500 - (NSInteger)getCurrentSelectedOnTouch:(CGPoint)point
494 501 {
495 502 __block NSUInteger selectedIndex = -1;
496   -
  503 +
497 504 CGAffineTransform transform = CGAffineTransformIdentity;
498   -
  505 +
499 506 CALayer *parentLayer = [_pieView layer];
500 507 NSArray *pieLayers = [parentLayer sublayers];
501   -
  508 +
502 509 [pieLayers enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
503 510 SliceLayer *pieLayer = (SliceLayer *)obj;
504 511 CGPathRef path = [pieLayer path];
505   -
  512 +
506 513 if (CGPathContainsPoint(path, &transform, point, 0)) {
507 514 [pieLayer setLineWidth:_selectedSliceStroke];
508 515 [pieLayer setStrokeColor:[UIColor whiteColor].CGColor];
@@ -542,7 +549,7 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
542 549 {
543 550 CALayer *parentLayer = [_pieView layer];
544 551 NSArray *pieLayers = [parentLayer sublayers];
545   -
  552 +
546 553 for (SliceLayer *pieLayer in pieLayers) {
547 554 [pieLayer setZPosition:kDefaultSliceZOrder];
548 555 [pieLayer setLineWidth:0.0];
@@ -553,16 +560,16 @@ - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
553 560
554 561 - (void)notifyDelegateOfSelectionChangeFrom:(NSUInteger)previousSelection to:(NSUInteger)newSelection
555 562 {
556   - if (previousSelection != newSelection)
  563 + if (previousSelection != newSelection)
557 564 {
558 565 if (previousSelection != -1 && [_delegate respondsToSelector:@selector(pieChart:willDeselectSliceAtIndex:)])
559 566 {
560 567 [_delegate pieChart:self willDeselectSliceAtIndex:previousSelection];
561 568 }
562   -
  569 +
563 570 _selectedSliceIndex = newSelection;
564   -
565   - if (newSelection != -1)
  571 +
  572 + if (newSelection != -1)
566 573 {
567 574 if([_delegate respondsToSelector:@selector(pieChart:willSelectSliceAtIndex:)])
568 575 [_delegate pieChart:self willSelectSliceAtIndex:newSelection];
@@ -572,7 +579,7 @@ - (void)notifyDelegateOfSelectionChangeFrom:(NSUInteger)previousSelection to:(NS
572 579 [_delegate pieChart:self didSelectSliceAtIndex:newSelection];
573 580 [self setSliceSelectedAtIndex:newSelection];
574 581 }
575   -
  582 +
576 583 if(previousSelection != -1)
577 584 {
578 585 [self setSliceDeselectedAtIndex:previousSelection];
@@ -584,7 +591,7 @@ - (void)notifyDelegateOfSelectionChangeFrom:(NSUInteger)previousSelection to:(NS
584 591 {
585 592 SliceLayer *layer = [_pieView.layer.sublayers objectAtIndex:newSelection];
586 593 if(_selectedSliceOffsetRadius > 0 && layer){
587   -
  594 +
588 595 if (layer.isSelected) {
589 596 if ([_delegate respondsToSelector:@selector(pieChart:willDeselectSliceAtIndex:)])
590 597 [_delegate pieChart:self willDeselectSliceAtIndex:newSelection];
@@ -636,9 +643,10 @@ - (void)updateLabelForLayer:(SliceLayer *)pieLayer value:(CGFloat)value
636 643 if(_showPercentage)
637 644 label = [NSString stringWithFormat:@"%0.0f", pieLayer.percentage*100];
638 645 else
639   - label = [NSString stringWithFormat:@"%0.0f", value];
  646 + label = (pieLayer.text)?pieLayer.text:[NSString stringWithFormat:@"%0.0f", value];
  647 +
640 648 CGSize size = [label sizeWithFont:self.labelFont];
641   -
  649 +
642 650 [CATransaction setDisableActions:YES];
643 651 if(M_PI*2*_labelRadius*pieLayer.percentage < MAX(size.width,size.height) || value <= 0)
644 652 {

0 comments on commit 9bb14e7

Please sign in to comment.
Something went wrong with that request. Please try again.