I have a UITableView with a white background, I would like to apply a linear gradient across the tableview cells so that the gradient is one single gradient from the start to end of the tableview see an example below from Adobe Illustrator. Is there a way this can be achieved using Core Graphics?
I actually managed to figure it out, to some extent from this question and help from matt
- (NSArray *)generateCellGradients
{
NSMutableArray *gradientColors = [[NSMutableArray alloc] init];
NSUInteger numberOfIntervals = self.datasource.count;
CGFloat startColorR = 81.0 / 255.0;
CGFloat startColorG = 118.0 / 255.0;
CGFloat startColorB = 214.0 / 255.0;
UIColor *startColor = [UIColor colorWithRed:startColorR
green:startColorG
blue:startColorB
alpha:1.0];
[gradientColors addObject:startColor];
CGFloat endColorR = 0;
CGFloat endColorG = 191.0 / 255.0;
CGFloat endColorB = 120.0 / 255.0;
UIColor *endColor = [UIColor colorWithRed:endColorR
green:endColorG
blue:endColorB
alpha:1.0];
CGFloat intervalR = (endColorR - startColorR) / numberOfIntervals;
CGFloat intervalG = (endColorG - startColorG) / numberOfIntervals;
CGFloat intervalB = (endColorB - startColorB) / numberOfIntervals;
for (NSUInteger i = 0; i < numberOfIntervals; i++) {
startColorR += intervalR;
startColorG += intervalG;
startColorB += intervalB;
UIColor *intervalColor = [UIColor colorWithRed:startColorR green:startColorG blue:startColorB alpha:1.0];
[gradientColors addObject:intervalColor];
}
[gradientColors addObject:endColor];
NSMutableArray *cellGradients = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < gradientColors.count; i++) {
UIColor *startGradientColor = gradientColors[i];
UIColor *endGradientColor;
if (i == gradientColors.count - 1) {
endGradientColor = gradientColors[i];
} else {
endGradientColor = gradientColors[i + 1];
}
NSArray *colors = #[(id)startGradientColor.CGColor, (id)endGradientColor.CGColor];
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colors;
[cellGradients addObject:gradientLayer];
}
return cellGradients;
}
This is how to add it to a subview:
CAGradientLayer *backgroundLayer = self.gradients[indexPath.row];
backgroundLayer.frame = view.bounds;
[view.layer insertSublayer:backgroundLayer atIndex:0];
Here is the result below:
Find below the code to create gradient layer by provide two required colours. You can add this layer to any view. Add this framework #import <QuartzCore/QuartzCore.h> in order to achieve this result.
typedef enum {
GradientType_Linear,
GradientType_Reflected,
}GradientType;
+(CAGradientLayer*) gradientLayerFromColor:(UIColor *)firstColor
secondColor:(UIColor *)secondColor
gradientType:(GradientType)gradientType
{
UIColor *colorStart = firstColor;
UIColor *colorEnd = secondColor;
NSArray *colors;
NSArray *locations;
switch (gradientType) {
case GradientType_Linear:
{
colors = [NSArray arrayWithObjects:(id)colorStart.CGColor, colorEnd.CGColor, nil];
NSNumber *start1 = [NSNumber numberWithFloat:0.0];
NSNumber *stop1 = [NSNumber numberWithFloat:1.0];
locations = [NSArray arrayWithObjects:start1, stop1, nil];
}
break;
case GradientType_Reflected:
{
colors = [NSArray arrayWithObjects:(id)colorStart.CGColor, colorEnd.CGColor, colorEnd.CGColor, colorStart.CGColor, nil];
NSNumber *start1 = [NSNumber numberWithFloat:0.0];
NSNumber *stop1 = [NSNumber numberWithFloat:0.5];
NSNumber *start2 = [NSNumber numberWithFloat:0.5];
NSNumber *stop2 = [NSNumber numberWithFloat:1.0];
locations = [NSArray arrayWithObjects:start1, stop1, start2, stop2, nil];
}
break;
default:
{
colors = [NSArray arrayWithObjects:(id)colorStart.CGColor, colorEnd.CGColor, nil];
NSNumber *start1 = [NSNumber numberWithFloat:0.0];
NSNumber *stop1 = [NSNumber numberWithFloat:1.0];
locations = [NSArray arrayWithObjects:start1, stop1, nil];
}
break;
}
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = colors;
gradientLayer.locations = locations;
return gradientLayer;
}
Related
I'm trying to convert following (link) swift code in objective c.
https://stackoverflow.com/a/49100870/797196
CTFontRef helveticaBold = CTFontCreateWithName( CFSTR("Helvetica-Bold"), 60.0, NULL);
NSString* unicodeString =#"Window Title";
CGColorRef color = [UIColor blueColor].CGColor;
NSNumber* underline = [NSNumber numberWithInt:
kCTUnderlineStyleSingle|kCTUnderlinePatternDot];
NSDictionary* attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)helveticaBold, (NSString*)kCTFontAttributeName,
color, (NSString*)kCTForegroundColorAttributeName,
underline, (NSString*)kCTUnderlineStyleAttributeName, nil];
NSAttributedString* stringToDraw = [[NSAttributedString alloc]
initWithString:unicodeString
attributes:attributesDict];
CGMutablePathRef letters = CGPathCreateMutable();
// CTFontRef font = CTFontCreateWithName((__bridge CFStringRef)#"Avenir",20,nil);
CTLineRef lines = CTLineCreateWithAttributedString((CFAttributedStringRef)stringToDraw);
CFArrayRef runArray = CTLineGetGlyphRuns(lines);
CAShapeLayer *pathLayer = [CAShapeLayer layer];
for (int i = 0; i < CFArrayGetCount(runArray); i++) {
CTRunRef run = CFArrayGetValueAtIndex(runArray, i);
CFDictionaryRef dictRef = CTRunGetAttributes(run);
NSDictionary *dict = (__bridge NSDictionary*)dictRef;
CTFontRef runFont = (__bridge CTFontRef)(dict[(NSString*)kCTFontAttributeName]);
for (int runGlyphIndex=0; runGlyphIndex<CTRunGetGlyphCount(run); runGlyphIndex++) {
CGGlyph glyph;
CGPoint position = CGPointZero;
CTRunGetGlyphs(run, CFRangeMake(runGlyphIndex, 1), &glyph);
CTRunGetPositions(run, CFRangeMake(runGlyphIndex, 1), &position);
CGPathRef letter = CTFontCreatePathForGlyph(runFont, glyph, nil);
CGAffineTransform t = CGAffineTransformMakeTranslation(position.x, position.y);
CGPathAddPath(letters, &t, letter);
CAShapeLayer *pathL = [CAShapeLayer layer];
// pathLayer.frame = _pathLayerView.bounds;
CGRect rect = CGPathGetBoundingBox(letter);
rect.origin = position;
pathL.frame = rect;
pathL.geometryFlipped = true;
pathL.path = letter;
pathL.strokeColor = UIColor.blueColor.CGColor;
pathL.fillColor = UIColor.redColor.CGColor;
pathL.lineWidth = 4.0;
pathL.lineJoin = kCALineJoinBevel;
CABasicAnimation *stroke = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
stroke.fromValue = #(0.0);
stroke.duration = 3.0f;
stroke.repeatCount = 0;
[pathL addAnimation:stroke forKey:nil];
[pathLayer addSublayer:pathL];
}
}
[_pathLayerView.layer addSublayer:pathLayer];
But the problem is letters alignment is not in required position. "i","n","o" letters y position starts from the top. & its obvious, because I didn't use the position of the letters.
I find out the positions of the letters using CTRunGetPositions, but I dont know how to use it or where to use it.
I have an implementation of CorePlot in my project and though I have no relevant errors or warnings in Xcode, have been unsuccessful in getting the plot to show up in the graph. The axis and chart show up fine, but no bars in the graph.
Any help or advice would be appreciated!
Header File
#import <UIKit/UIKit.h>
#import "PresentedViewControllerDelegate.h"
#import <CorePlot/ios/CorePlot.h>
#interface DeviceDetailModal : UIViewController <PresentedViewControllerDelegate, UIWebViewDelegate, UITableViewDataSource, UITableViewDelegate, CPTPlotDataSource,CPTBarPlotDelegate>{
CPTGraph *graph;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (nonatomic, weak) id <PresentedViewControllerDelegate> delegate;
#property (strong,nonatomic) NSArray *dataSet;
#property (nonatomic, strong) CPTBarPlot *aaplPlot;
#property (nonatomic, strong) CPTPlotSpaceAnnotation *priceAnnotation;
#end
Main File
#import <Foundation/Foundation.h>
#import "DeviceDetailModal.h"
#import "DetailCell.h"
#import <CorePlot/ios/CorePlot.h>
#import "Constants.h"
#implementation DeviceDetailModal
NSString * const CPDTickerSymbolAAPL = #"AAPL";
CGFloat const CPDBarWidth = 0.25f;
CGFloat const CPDBarInitialX = 0.25f;
#synthesize aaplPlot = aaplPlot_;
-(void)viewDidLoad{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor colorWithRed:0.03 green:0.06 blue:0.10 alpha:1.0]];
UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:#"Close" style:UIBarButtonItemStylePlain target:self action:#selector(closeView)];
self.navigationItem.leftBarButtonItem = closeButton;
[[UIBarButtonItem appearance] setTintColor:[UIColor lightGrayColor]];
[[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]];
self.tableView.layer.cornerRadius = 10.0;
self.tableView.layer.borderWidth = 0.7;
self.tableView.layer.borderColor = [UIColor whiteColor].CGColor;
self.tableView.opaque = NO;
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.backgroundView = nil;
self.dataSet = [[NSArray alloc] init];
self.dataSet = [NSArray arrayWithObjects:
[NSDecimalNumber numberWithFloat:571.70],
[NSDecimalNumber numberWithFloat:560.28],
[NSDecimalNumber numberWithFloat:610.00],
[NSDecimalNumber numberWithFloat:607.70],
[NSDecimalNumber numberWithFloat:603.00],
nil];
[self configureGraph];
[graph reloadData];
}
-(void)configureGraph {
CGRect hostingRect = CGRectMake(20, 350, 335, 310);
CPTGraphHostingView *hostingView = [[CPTGraphHostingView alloc] initWithFrame:hostingRect];
[self.view addSubview:hostingView];
[hostingView setBackgroundColor:[UIColor colorWithRed:0.03 green:0.06 blue:0.10 alpha:1.0]];
hostingView.layer.cornerRadius = 10.0;
hostingView.layer.borderWidth = 0.7;
hostingView.layer.borderColor = [UIColor whiteColor].CGColor;
graph = [[CPTXYGraph alloc] initWithFrame:hostingView.bounds];
hostingView.hostedGraph = graph;
[[graph defaultPlotSpace] setAllowsUserInteraction:TRUE];
// 1 - Create the graph
graph.plotAreaFrame.masksToBorder = NO;
// 2 - Configure the graph
//[graph applyTheme:[CPTTheme themeNamed:kCPTPlainBlackTheme]];
graph.paddingBottom = 30.0f;
graph.paddingLeft = 30.0f;
graph.paddingTop = -1.0f;
graph.paddingRight = -5.0f;
// 3 - Set up styles
CPTMutableTextStyle *titleStyle = [CPTMutableTextStyle textStyle];
titleStyle.color = [CPTColor whiteColor];
titleStyle.fontName = #"Helvetica-Bold";
titleStyle.fontSize = 16.0f;
// 4 - Set up title
NSString *title = #"Portfolio Prices: April 23 - 27, 2012";
graph.title = title;
graph.titleTextStyle = titleStyle;
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
graph.titleDisplacement = CGPointMake(0.0f, -16.0f);
// 5 - Set up plot space
CGFloat xMin = 0.0f;
CGFloat xMax = 7;
CGFloat yMin = 0.0f;
CGFloat yMax = 800.0f; // should determine dynamically based on max price
NSNumber *xAxisStart = [NSNumber numberWithFloat:xMin];
NSNumber *xAxisLength = [NSNumber numberWithDouble:xMax];
NSNumber *yAxisStart = [NSNumber numberWithFloat:yMin];
NSNumber *yAxisLength = [NSNumber numberWithDouble:yMax];
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *) graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:xAxisStart length:xAxisLength];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:yAxisStart length:yAxisLength];
// 1 - Set up the three plots
self.aaplPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor redColor] horizontalBars:NO];
self.aaplPlot.identifier = CPDTickerSymbolAAPL;
// 2 - Set up line style
CPTMutableLineStyle *barLineStyle = [[CPTMutableLineStyle alloc] init];
barLineStyle.lineColor = [CPTColor lightGrayColor];
barLineStyle.lineWidth = 0.5;
// 3 - Add plots to graph
graph = hostingView.hostedGraph;
CGFloat barX = CPDBarInitialX;
NSArray *plots = [NSArray arrayWithObjects:self.aaplPlot, nil];
for (CPTBarPlot *plot in plots) {
plot.dataSource = self;
plot.delegate = self;
plot.barWidth = [NSNumber numberWithFloat:CPDBarWidth];
plot.barOffset = [NSNumber numberWithFloat:barX];
plot.lineStyle = barLineStyle;
[graph addPlot:plot toPlotSpace:graph.defaultPlotSpace];
barX += CPDBarWidth;
}
// 1 - Configure styles
CPTMutableTextStyle *axisTitleStyle = [CPTMutableTextStyle textStyle];
axisTitleStyle.color = [CPTColor whiteColor];
axisTitleStyle.fontName = #"Helvetica-Bold";
axisTitleStyle.fontSize = 12.0f;
CPTMutableLineStyle *axisLineStyle = [CPTMutableLineStyle lineStyle];
axisLineStyle.lineWidth = 2.0f;
axisLineStyle.lineColor = [[CPTColor whiteColor] colorWithAlphaComponent:1];
// 2 - Get the graph's axis set
CPTXYAxisSet *axisSet = (CPTXYAxisSet *) hostingView.hostedGraph.axisSet;
// 3 - Configure the x-axis
axisSet.xAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
axisSet.xAxis.title = #"Days of Week (Mon - Fri)";
axisSet.xAxis.titleTextStyle = axisTitleStyle;
axisSet.xAxis.titleOffset = 10.0f;
axisSet.xAxis.axisLineStyle = axisLineStyle;
// 4 - Configure the y-axis
axisSet.yAxis.labelingPolicy = CPTAxisLabelingPolicyNone;
axisSet.yAxis.title = #"Price";
axisSet.yAxis.titleTextStyle = axisTitleStyle;
axisSet.yAxis.titleOffset = 5.0f;
axisSet.yAxis.axisLineStyle = axisLineStyle;
}
#pragma mark - CPTPlotDataSource methods
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot {
return [self.dataSet count];
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {
NSLog(#"DATA: %#",[self.dataSet objectAtIndex:index]);
return [self.dataSet objectAtIndex:index];
}
#pragma mark - CPTBarPlotDelegate methods
-(void)barPlot:(CPTBarPlot *)plot barWasSelectedAtRecordIndex:(NSUInteger)index {
// 1 - Is the plot hidden?
if (plot.isHidden == YES) {
return;
}
// 2 - Create style, if necessary
static CPTMutableTextStyle *style = nil;
if (!style) {
style = [CPTMutableTextStyle textStyle];
style.color= [CPTColor yellowColor];
style.fontSize = 16.0f;
style.fontName = #"Helvetica-Bold";
}
// 3 - Create annotation, if necessary
NSNumber *price = [self numberForPlot:plot field:CPTBarPlotFieldBarTip recordIndex:index];
if (!self.priceAnnotation) {
NSNumber *x = [NSNumber numberWithInt:0];
NSNumber *y = [NSNumber numberWithInt:0];
NSArray *anchorPoint = [NSArray arrayWithObjects:x, y, nil];
self.priceAnnotation = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:plot.plotSpace anchorPlotPoint:anchorPoint];
}
// 4 - Create number formatter, if needed
static NSNumberFormatter *formatter = nil;
if (!formatter) {
formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:2];
}
// 5 - Create text layer for annotation
NSString *priceValue = [formatter stringFromNumber:price];
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:priceValue style:style];
self.priceAnnotation.contentLayer = textLayer;
// 6 - Get plot index based on identifier
NSInteger plotIndex = 0;
if ([plot.identifier isEqual:CPDTickerSymbolAAPL] == YES) {
plotIndex = 0;
}
// 7 - Get the anchor point for annotation
CGFloat x = index + CPDBarInitialX + (plotIndex * CPDBarWidth);
NSNumber *anchorX = [NSNumber numberWithFloat:x];
CGFloat y = [price floatValue] + 40.0f;
NSNumber *anchorY = [NSNumber numberWithFloat:y];
self.priceAnnotation.anchorPlotPoint = [NSArray arrayWithObjects:anchorX, anchorY, nil];
// 8 - Add the annotation
[plot.graph.plotAreaFrame.plotArea addAnnotation:self.priceAnnotation];
}
#end
Plot ranges are given as a starting location and length. In your case, make the starting location the min value and the length max - min. Right now it's ok since the min is zero, but the length will be wrong if you ever change the min values.
The -numberForPlot:field:recordIndex: datasource method must check the field parameter and return the correct value for the field. Return the index parameter value for the CPTBarPlotFieldBarLocation field. Return the value from the dataSet array for the CPTBarPlotFieldBarTip field.
I have successfully selected a point, but I hope at this point when selected, the point of color set to different from other points to distinguish,how to implement,Thanks a lot
How to set up only this one in red.
-(void)scatterPlot:(CPTScatterPlot *)plot plotSymbolWasSelectedAtRecordIndex:(NSUInteger)index{
CPTXYGraph graph = (CPTXYGraph)_graph;
if ( _symbolTextAnnotation ){
[graph.plotAreaFrame.plotArea removeAnnotation:_symbolTextAnnotation];
_symbolTextAnnotation = nil;
}
// Setup a style for the annotation
CPTMutableTextStyle *hitAnnotationTextStyle = [CPTMutableTextStyle textStyle];
hitAnnotationTextStyle.color = [CPTColor whiteColor];
hitAnnotationTextStyle.fontSize = 16.0;
hitAnnotationTextStyle.fontName = #"Helvetica-Bold";
// Determine point of symbol in plot coordinates
NSDictionary *dataPoint = _plotData[index];
NSNumber *x = dataPoint[#"x"];
NSNumber *y = dataPoint[#"y"];
NSArray *anchorPoint = #[x, y];
float yValue = [y floatValue];
NSString *yString = [NSString stringWithFormat:#"%.1f",yValue];
CPTTextLayer *textLayer = [[CPTTextLayer alloc] initWithText:yString style:hitAnnotationTextStyle];
CPTImage *background = [CPTImage imageWithCGImage:[UIImage imageNamed:#"bg_red"].CGImage];
textLayer.fill = [CPTFill fillWithImage:background];
textLayer.paddingLeft = 2.0;
textLayer.paddingTop = 2.0;
textLayer.paddingRight = 2.0;
textLayer.paddingBottom = 2.0;
self.symbolTextAnnotation = [[CPTPlotSpaceAnnotation alloc] initWithPlotSpace:graph.defaultPlotSpace anchorPlotPoint:anchorPoint];
_symbolTextAnnotation.contentLayer = textLayer;
_symbolTextAnnotation.contentAnchorPoint = CGPointMake(0.5, 0.0);
_symbolTextAnnotation.displacement = CGPointMake(0.0, 10.0);
[graph.plotAreaFrame.plotArea addAnnotation:_symbolTextAnnotation];
}
Implement the -symbolForScatterPlot:recordIndex: datasource method. Return nil to use the default plotSymbol, [NSNull null] to show no symbol, or a CPTPlotSymbol to show that symbol at the given data index.
I want to display horizontal bar chart... in it.. positive bar chart will animate from left to right and negative bar will animate from right to left..
i also attached my two different types of array...1 for positive and 1 for negative
When i run this code... negative bar value look like mirror effect...and for positive value, it use two color in each bar...
please help me to solve it..
if you can find anything wrong in code.. then please let me know
i attach two images also.. 1 for negative and 1 for positive
and ya, you can see that how values are display in negative bar...i also need to solve it also..
sampleArray:
<__NSArrayM 0xbae0940>(
{
x = 0;
y = "97.71425628662109";
},
{
x = 0;
y = "-70.55500793457031";
}
)
sampleArray:
<__NSArrayM 0x12a295a0>(
{
x = 0;
y = "97.71425628662109";
},
{
x = 0;
y = "450.6826171875";
}
)
Here is my whole code...
CPTGraphHostingView *hostingView = [[CPTGraphHostingView alloc] initWithFrame:CGRectMake(200, 100, 300, 300)];
hostingView.hostedGraph = self.barChart;
[self addSubview:hostingView];
plotSpace = (CPTXYPlotSpace *) self.barChart.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-200.0f) length:CPTDecimalFromDouble(650.0f)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(00.0f) length:CPTDecimalFromDouble(400.0f)];
- (void) animateNow
{
CPTBarPlot *barPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor orangeColor] horizontalBars:YES];
// define the plot range - between LTM and NEW, diffrence is 200
barPlot.plotRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble(200)];//xAxisLength
// LTM will display at 100th point and NEW will display at 300th coz of 200 range
barPlot.barOffset = CPTDecimalFromFloat(100.00f);
barPlot.baseValue = CPTDecimalFromString(#"0");
barPlot.borderColor = [[UIColor clearColor]CGColor];
barPlot.lineStyle = nil;
// Width of the each bar
barPlot.barWidth = CPTDecimalFromFloat(30.0f);
barPlot.cornerRadius = 1.0f;
barPlot.dataSource = self;
// transform.scale.x for horizontal bar growth
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
if([[[self.sampleArray objectAtIndex:0]valueForKey:Y_VAL]floatValue] < 0)
{
anim.toValue = [NSNumber numberWithFloat:-1.0];
anim.fromValue = [NSNumber numberWithFloat:0.0f];
}
else
{
anim.toValue = [NSNumber numberWithFloat:1.0];
anim.fromValue = [NSNumber numberWithFloat:0.0f];
}
[anim setDuration:2.0f];
anim.toValue = [NSNumber numberWithFloat:1.0];
anim.fromValue = [NSNumber numberWithFloat:0.0f];
anim.removedOnCompletion = NO;
anim.delegate = self;
anim.fillMode = kCAFillModeForwards;
barPlot.anchorPoint = CGPointMake(0.0, 0.0);
[barPlot addAnimation:anim forKey:#"grow"];
[self.barChart addPlot:barPlot toPlotSpace:plotSpace ];
}
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
/* if([plot.identifier isEqual:#"LTM"])
return [self.sampleArray count]; */
// return [self.sampleArray count];
return [self.sampleArray count];
}
-(CPTLayer *)dataLabelForPlot:(CPTPlot *)plot recordIndex:(NSUInteger)index
{
NSDictionary *bar;
CPTTextLayer *label;
if([plot.identifier isEqual:#"LTM"])
{
bar = [self.sampleArray objectAtIndex:0];
label = [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:#"%.02f", [[bar valueForKey:Y_VAL]floatValue]]];
}
else if([plot.identifier isEqual:#"NEW"])
{
bar = [self.sampleArray objectAtIndex:1];
label = [[CPTTextLayer alloc] initWithText:[NSString stringWithFormat:#"%.02f", [[bar valueForKey:Y_VAL]floatValue]]]; }
else
{
return nil;
}
float dataLabelOffset;
if([[self.sampleArray objectAtIndex:index]valueForKey:Y_VAL]> 0)
{
dataLabelOffset = -5.0f;
}
else
{
dataLabelOffset = 10.0f;
}
plot.labelOffset = dataLabelOffset;
NSLog(#"Offset = %f",plot.labelOffset);
// label.textStyle = textStyle;
return label;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSDictionary *sample = [self.sampleArray objectAtIndex:index];
if (fieldEnum == CPTScatterPlotFieldX)
{
return [sample valueForKey:X_VAL];
}
else
{
return [sample valueForKey:Y_VAL];
}
}
-(CPTFill *)barFillForBarPlot:(CPTBarPlot *)barPlot recordIndex:(NSUInteger)index
{
CPTColor *color = nil;
// Index = 0, for LTM and Index = 1 for NEW.
NSLog(#"%#",barPlot.identifier);
switch ( index )
{
case 0:
color = [CPTColor colorWithComponentRed:147.0/255.0 green:149.0/255.0 blue:152.0/255.0 alpha:1.0];
break;
case 1:
color = [CPTColor colorWithComponentRed:255.0/255.0 green:160.0/255.0 blue:47.0/255.0 alpha:1.0];
break;
default:
break;
}
CPTGradient *fillGradient = [CPTGradient gradientWithBeginningColor:color endingColor:color];
return [CPTFill fillWithGradient:fillGradient];
}
When setting up the plots, don't use the plotRange or barOffset. You'll get better drawing performance if you use a solid color fill instead of a gradient (your gradient had the same start and end colors).
- (void) animateNow
{
CPTBarPlot *barPlot = [CPTBarPlot tubularBarPlotWithColor:[CPTColor orangeColor] horizontalBars:YES];
barPlot.lineStyle = nil;
barPlot.barWidth = CPTDecimalFromFloat(30.0f);
barPlot.cornerRadius = 1.0f;
barPlot.dataSource = self;
CPTColor *color = [CPTColor colorWithComponentRed:147.0/255.0 green:149.0/255.0 blue:152.0/255.0 alpha:1.0];
barPlot.fill = [CPTFill fillWithColor:color];
CPTBarPlot *barPlot1 = [CPTBarPlot tubularBarPlotWithColor:[CPTColor blueColor] horizontalBars:YES];
barPlot1.barWidth = CPTDecimalFromFloat(30.0f);
barPlot1.lineStyle = nil;
barPlot1.cornerRadius = 1.0f;
barPlot1.dataSource = self;
CPTColor *color1 = [CPTColor colorWithComponentRed:255.0/255.0 green:160.0/255.0 blue:47.0/255.0 alpha:1.0];
barPlot1.fill = [CPTFill fillWithColor:color1];
barPlot.identifier = #"LTM";
[self.barChart addPlot:barPlot toPlotSpace:plotSpace ];
barPlot1.identifier = #"NEW";
[self.barChart addPlot:barPlot1 toPlotSpace:plotSpace ];
}
With plots configured this way, the plot space setup is simpler:
plotSpace = (CPTXYPlotSpace *) self.barChart.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(0.0) length:CPTDecimalFromDouble(450.0)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromDouble(-0.5) length:CPTDecimalFromDouble(1.0)];
I'm assuming you want a single horizontal bar built using two plots to get the different colors. If so, here is how I would write the datasource methods:
// datasource
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
return 1;
}
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
NSDictionary *sample = nil;
if([plot.identifier isEqual:#"LTM"])
{
sample = self.sampleArray[0];
}
else if([plot.identifier isEqual:#"NEW"])
{
sample = self.sampleArray[1];
}
switch (fieldEnum) {
case CPTBarPlotFieldBarLocation:
return #(index);
break;
case CPTBarPlotFieldBarTip:
return sample[Y_VAL];
break;
}
return nil;
}
Note the plot field identifiers are bar plot location and tip rather than the scatter plot enum values. With a horizontal bar plot, the location values are along the y-axis and the tip and base are on the x-axis.
I am trying to animate several views (layers) using CAKeyframeAnimation and CAAnimationGroup. Each view to be animated is contained in an array. My idea is to loop through the array where CAKeyframeAnimation instance of each view would be added to an array of animations, which then would be added to the CAAnimationGroup. My goal is to animate each view one after another. As far as I understand I need to use the group in order to have a reference for the beginTime.
I am probably missing something obvious, but my code doesn't work
CAAnimationGroup *cardAnimationGroup = [CAAnimationGroup animation];
cardAnimationGroup.delegate = self;
cardAnimationGroup.removedOnCompletion = NO;
cardAnimationGroup.beginTime = 0.0f;
[cardAnimationGroup setValue:#"animation0" forKey:#"id"];
cardAnimationGroup.duration = 1.2f * [_myViewsArray count];
NSMutableArray *animationsArray = [[NSMutableArray alloc] init];
// Loop through views
for (UIView *cardView in _myViewsArray)
{
NSUInteger index = [_myViewsArray indexOfObject:cardView];
// my target origin
CGFloat yOffset = (-(cardView.frame.origin.y - _middleCardView.frame.origin.y) - index * 2);
CAKeyframeAnimation *translateCardPositionAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.y"];
translateCardPositionAnimation.removedOnCompletion = YES;
//translateCardPositionAnimation.fillMode = kCAFillModeForwards;
translateCardPositionAnimation.beginTime = 1.2f * index;
translateCardPositionAnimation.duration = 1.2f;
translateCardPositionAnimation.values = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:yOffset],
[NSNumber numberWithFloat:yOffset],nil];
translateCardPositionAnimation.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
[NSNumber numberWithFloat:1.2f], nil];
[_containerCardView addSubview:cardView];
[_containerCardView sendSubviewToBack:cardView];
[animationsArray addObject:translateCardPositionAnimation];
[cardView.layer addObject:translateCardPositionAnimation forKey:#"id"];
if (index == [_myViewsArray count]-1) {
[cardAnimationGroup setAnimations:animationsArray];
}
}