How to remove already created path using CGMutablePathRef? - objective-c

I am plotting line according bottom selected dots.First Showing start from 0 and after that it showing according to selected dots But line chart is showing previous drawn line.
Here I am using SHLineGrapgView. Here is code :
- (void)drawPlot:(SHPlot *)plot {
NSDictionary *theme = plot.plotThemeAttributes;
//
CAShapeLayer *backgroundLayer = [CAShapeLayer layer];
backgroundLayer.frame = self.bounds;
backgroundLayer.fillColor = [UIColor clearColor].CGColor;
backgroundLayer.backgroundColor = [UIColor clearColor].CGColor;
[backgroundLayer setStrokeColor:[UIColor clearColor].CGColor];
[backgroundLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef backgroundPath= CGPathCreateMutable();
//
CAShapeLayer *circleLayer = [CAShapeLayer layer];
circleLayer.frame = self.bounds;
circleLayer.fillColor = [UIColor redColor].CGColor;
circleLayer.backgroundColor = [UIColor clearColor].CGColor;
[circleLayer setStrokeColor:((UIColor *)theme[kPlotPointFillColorKey]).CGColor];
[circleLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef circlePath = CGPathCreateMutable();
//
CAShapeLayer *graphLayer = [CAShapeLayer layer];
graphLayer.frame = self.bounds;
graphLayer.fillColor = [UIColor clearColor].CGColor;
graphLayer.backgroundColor = [UIColor clearColor].CGColor;
[graphLayer setStrokeColor:((UIColor *)theme[kPlotStrokeColorKey]).CGColor];
[graphLayer setLineWidth:((NSNumber *)theme[kPlotStrokeWidthKey]).intValue];
CGMutablePathRef graphPath = CGPathCreateMutable();
double yRange = [_yAxisRange doubleValue]; // this value will be in dollars
double yIntervalValue = yRange / INTERVAL_COUNT;
//logic to fill the graph path, ciricle path, background path.
NSLog(#"plottingValues Dictionary %#",plot.plottingValues);
[plot.plottingValues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDictionary *dic = (NSDictionary *)obj;
NSLog(#"Plotting Dictionary %#",dic);
__block NSNumber *_key = nil;
__block NSNumber *_value = nil;
[dic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
_key = (NSNumber *)key;
_value = (NSNumber *)obj;
}];
int xIndex = [self getIndexForValue:_key forPlot:plot];
//x value
double height = self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE;
double y = height - ((height / ([_yAxisRange doubleValue] + yIntervalValue)) * [_value doubleValue]);
(plot.xPoints[xIndex]).x = ceil((plot.xPoints[xIndex]).x);
(plot.xPoints[xIndex]).y = ceil(y);
}];
//move to initial point for path and background.
CGPathMoveToPoint(graphPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);
CGPathMoveToPoint(backgroundPath, NULL, _leftMarginToLeave, plot.xPoints[0].y);
int count = (int)_xAxisValues.count;
for(int i=0; i< count; i++)
{
CGPathRef path=CGPathCreateCopy(graphPath);
CGPoint point = plot.xPoints[i];
// CGContextRef ref=CGContextCopyPath(<#CGContextRef _Nullable c#>)
// CGContextClip
CGPathAddLineToPoint(graphPath, NULL, point.x, point.y);
CGPathAddLineToPoint(backgroundPath, NULL, point.x, point.y);
CGFloat dotsSize = [_themeAttributes[kDotSizeKey] floatValue];
CGPathAddEllipseInRect(circlePath, NULL, CGRectMake(point.x - dotsSize/2.0f, point.y - dotsSize/2.0f, dotsSize, dotsSize));
}
//move to initial point for path and background.
CGPathAddLineToPoint(NULL, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count -1].y);
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, plot.xPoints[count - 1].y);
//additional points for background.
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave + PLOT_WIDTH, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
CGPathAddLineToPoint(backgroundPath, NULL, _leftMarginToLeave, self.bounds.size.height - BOTTOM_MARGIN_TO_LEAVE);
CGPathCloseSubpath(backgroundPath);
backgroundLayer.path = backgroundPath;
graphLayer.path = graphPath;
circleLayer.path = circlePath;
//animation
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
animation.duration = 1;
animation.fromValue = #(0.0);
animation.toValue = #(1.0);
[graphLayer addAnimation:animation forKey:#"strokeEnd"];
backgroundLayer.zPosition = 0;
graphLayer.zPosition = 1;
circleLayer.zPosition = 2;
[self.layer addSublayer:graphLayer];
[self.layer addSublayer:circleLayer];
[self.layer addSublayer:backgroundLayer];
NSUInteger count2 = _xAxisValues.count;
for(int i=0; i< count2; i++){
CGPoint point = plot.xPoints[i];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor clearColor];
btn.tag = i;
btn.frame = CGRectMake(point.x, point.y - 20, 40, 40);
[btn addTarget:self action:#selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
objc_setAssociatedObject(btn, kAssociatedPlotObject, plot, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self addSubview:btn];
}
}

Related

How do you set a gradient fillcolor for cashapelayer without using a mask?

How do you set a gradient fillcolor for cashapelayer?
Related question with clearer explanation:
Using Cocoa To Follow A Path With A Gradient
I need a gradient that's not a mask, but instead a gradient based on the drawing of the cashapelayer's path.
I can't use a gradient mask on top, because I'm making a route on the minimap in my game. So if the player walks over his own tracks, it should be in a different color.
I want it like this mapview's polyline:
Source: http://cdn4.raywenderlich.com/wp-content/uploads/2014/06/23_multicolor_polyline.png
I made the minimap route by:
logging all the user's different directions, then running them through a loop into bezier paths.
I appended the Bezier paths, and then put it on a cashapelayer.
Is there a way to have a multicolored in a cashapelayer?
Is there a keypath for cabasicanimation that can put a gradient?
My code is below, and some images.
[mymapview.layer.sublayers makeObjectsPerformSelector:#selector(removeFromSuperlayer)];
[[mymapview subviews]
makeObjectsPerformSelector:#selector(removeFromSuperview)];
int i = 0;
int x = 17;
int y = 272;
int m = 16;
UIBezierPath *kpath = [UIBezierPath bezierPath]; while (i < HistDirections.count)
{
if (i > 0)
{
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:CGPointMake(x, y)];
if ([[HistDirections objectAtIndex:i] intValue] ==1)
{
[path addLineToPoint:CGPointMake(x, y-m)];
y = y - m;
}
else if ([[HistDirections objectAtIndex:i] intValue] ==2)
{
[path addLineToPoint:CGPointMake(x-m, y)];
x = x -m;
}
else if ([[HistDirections objectAtIndex:i] intValue] ==3)
{
[path addLineToPoint:CGPointMake(x+m, y)];
x = x+m;
}
else
{
[path addLineToPoint:CGPointMake(x, y+m)];
y = y - m;
}
[kpath appendPath:path];
}
i++;
}
[CATransaction begin];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[CATransaction setCompletionBlock:^{
UIImageView *viewpulse = [[UIImageView alloc] initWithFrame:CGRectMake(x -5, y-5, 10.0, 10.0)];
viewpulse.image = [UIImage imageNamed:#"arro.png"];
viewpulse.backgroundColor = [UIColor clearColor];
if(direction == 1)
{
viewpulse.transform = CGAffineTransformMakeRotation(-M_PI/2);
}
else if (direction == 2)
{
viewpulse.transform = CGAffineTransformMakeRotation(M_PI);
}
else if (direction == 4)
{
viewpulse.transform = CGAffineTransformMakeRotation(M_PI/2);
}
[mymapview addSubview:viewpulse];
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
scaleAnimation.duration = 0.8;
scaleAnimation.repeatCount = HUGE_VAL;
scaleAnimation.autoreverses = YES;
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.6];
scaleAnimation.toValue = [NSNumber numberWithFloat:0.8];
[viewpulse.layer addAnimation:scaleAnimation forKey:#"scale"];
}];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
kpath.lineCapStyle = kCGLineCapRound;
kpath.lineCapStyle = kCGLineJoinRound;
shapeLayer.path = [kpath CGPath];
shapeLayer.strokeColor = [[UIColor colorWithRed:51/255.0f green:(51)/255.0f blue:170/255.0f alpha:1.0f] CGColor];
shapeLayer.lineWidth = 4.0;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.fillColor = [[UIColor clearColor] CGColor];
[mymapview.layer addSublayer:shapeLayer];
CABasicAnimation *HAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
float dur = (HistDirections.count * 0.27);
if (dur > 2)
{
dur = 2;
}
HAnimation.duration = dur;
HAnimation.repeatCount = 1.0;
HAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
HAnimation.toValue = [NSNumber numberWithFloat:1.0f];
/*
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = mymapview.frame;
gradientLayer.colors = #[(__bridge id)[UIColor blueColor].CGColor,(__bridge id)[UIColor greenColor].CGColor,(__bridge id)[UIColor yellowColor].CGColor,(__bridge id)[UIColor orangeColor].CGColor, (__bridge id)[UIColor redColor].CGColor];
gradientLayer.startPoint = CGPointMake(0,0.5);
gradientLayer.endPoint = CGPointMake(1,0.5);
[mymapview.layer addSublayer:gradientLayer];
gradientLayer.mask = shapeLayer;*/
[CATransaction commit];
Gradient mask:
Monocolor line:
Nevermind! I figured out what I can do. Since I create the layer from multiple paths, I just put the cgpaths into an array, and looped each path into a unique cashapelayer with it's own color

UiButton action method not working

I have a banner view that comes over navigation. I have added a custom button that i have added like:
- (id) initWithNotification:(JCNotificationBanner*)notification {
self = [super init];
if (self) {
isPresentedMutex = [NSObject new];
self.backgroundColor = [UIColor clearColor];
self.iconImageView = [UIImageView new];
self.iconImageView.image = [UIImage imageNamed:#"close.png"];
[self addSubview:self.iconImageView];
self.titleLabel = [UILabel new];
self.titleLabel.font = [UIFont boldSystemFontOfSize:16];
self.titleLabel.textColor = [UIColor lightTextColor];
self.titleLabel.backgroundColor = [UIColor clearColor];
[self addSubview:self.titleLabel];
self.messageLabel = [UILabel new];
self.messageLabel.font = [UIFont systemFontOfSize:14];
self.messageLabel.textColor = [UIColor lightTextColor];
self.messageLabel.backgroundColor = [UIColor clearColor];
self.messageLabel.numberOfLines = 0;
[self addSubview:self.messageLabel];
// Button
_detailDisclosureButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_detailDisclosureButton setBackgroundImage:[UIImage imageNamed:#"disclosure.png"] forState:UIControlStateNormal];
[_detailDisclosureButton setBackgroundImage:nil forState:UIControlStateSelected];
// _detailDisclosureButton.hidden = NO;
[_detailDisclosureButton addTarget:self action:#selector(detailDisclosureButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[_detailDisclosureButton setEnabled:YES];
[self addSubview:_detailDisclosureButton];
UITapGestureRecognizer* tapRecognizer;
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[self addGestureRecognizer:tapRecognizer];
self.notificationBanner = notification;
}
return self;
}
Here is what my draw context method is calling.
- (void) drawRect:(CGRect)rect {
CGRect bounds = self.bounds;
CGFloat lineWidth = kJCNotificationBannerViewOutlineWidth;
CGFloat radius = 10;
CGFloat height = bounds.size.height;
CGFloat width = bounds.size.width;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
CGMutablePathRef outlinePath = CGPathCreateMutable();
CGPathMoveToPoint(outlinePath, NULL, lineWidth, 0);
CGPathAddLineToPoint(outlinePath, NULL, lineWidth, height - radius - lineWidth);
CGPathAddArc(outlinePath, NULL, radius + lineWidth, height - radius - lineWidth, radius, -M_PI, M_PI_2, 1);
CGPathAddLineToPoint(outlinePath, NULL, width - radius - lineWidth, height - lineWidth);
CGPathAddArc(outlinePath, NULL, width - radius - lineWidth, height - radius - lineWidth, radius, M_PI_2, 0, 1);
CGPathAddLineToPoint(outlinePath, NULL, width - lineWidth, 0);
CGContextSetRGBFillColor(context, 0, 0, 0, 0.9);
CGContextAddPath(context, outlinePath);
CGContextFillPath(context);
CGContextAddPath(context, outlinePath);
CGContextSetRGBFillColor(context, 0, 0, 0, 1);
CGContextSetLineWidth(context, lineWidth);
CGContextDrawPath(context, kCGPathStroke);
CGPathRelease(outlinePath);
}
And my layout subview methods that arrange frame are like:
- (void) layoutSubviews {
if (!(self.frame.size.width > 0)) { return; }
BOOL hasTitle = notificationBanner ? (notificationBanner.title.length > 0) : NO;
CGFloat borderY = kJCNotificationBannerViewOutlineWidth + kJCNotificationBannerViewMarginY;
CGFloat borderX = kJCNotificationBannerViewOutlineWidth + kJCNotificationBannerViewMarginX;
CGFloat currentX = borderX;
CGFloat currentY = borderY;
CGFloat contentWidth = self.frame.size.width - (borderX * 2.0);
currentY += 2.0;
if (hasTitle) {
self.titleLabel.frame = CGRectMake(currentX, currentY, contentWidth, 22.0);
currentY += 22.0;
}
self.messageLabel.frame = CGRectMake(currentX, currentY, contentWidth, (self.frame.size.height - borderY) - currentY);
[self.messageLabel sizeToFit];
CGRect messageFrame = self.messageLabel.frame;
CGFloat spillY = (currentY + messageFrame.size.height + kJCNotificationBannerViewMarginY) - self.frame.size.height;
if (spillY > 0.0) {
messageFrame.size.height -= spillY;
self.messageLabel.frame = messageFrame;
}
_detailDisclosureButton.frame = CGRectMake(285,self.center.y-15,29,29);
}
My Button action method named detailDisclosureButtonPressed is not being called. Please help me out in this ?

How to set the cagradientcolor to the uibutton cashapelayer objective c.I want to fill colour to different shaped button

I want to add the colour to UIButton CAShape layer.Is that possible according to the reference in the url Gradient color effect on CAShapeLayer.. we can add the colour to the UIButton CAShape layer.I can see the colour to the button stroke but i want the gradient colour to the button CAShape layer.please help in setting the colour to UIButton CAShape layer.The code is
-(void)changeColour:(id)sender
{
#try{
if(m_cObjbuttonPtr1.layer.sublayers.count > 0){for(CALayer *layer in m_cObjbuttonPtr1.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]]) [layer removeFromSuperlayer];}}if (m_cObjbuttonPtr2.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr2.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}if(m_cObjbuttonPtr3.layer.sublayers.count > 0){for(CALayer *layer in m_cObjbuttonPtr3.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]]) [layer removeFromSuperlayer];}}if (m_cObjbuttonPtr4.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr4.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}if(m_cObjbuttonPtr5.layer.sublayers.count > 0){ for(CALayer *layer in m_cObjbuttonPtr5.layer.sublayers){if([layer isKindOfClass:[CAShapeLayer class]])[layer removeFromSuperlayer];}}}#catch (NSException *exception){}
UIButton *tempButton =(UIButton *)sender;
UIBezierPath *aPath = [UIBezierPath bezierPath];
[aPath moveToPoint:CGPointMake(0.0, 0.0)];
[aPath addLineToPoint:CGPointMake(0.0, 35.0)];
[aPath moveToPoint:CGPointMake(0.0, 35.0)];
[aPath addLineToPoint:CGPointMake(80.0, 55.0)];
[aPath moveToPoint:CGPointMake(80.0, 55.0)];
[aPath addLineToPoint:CGPointMake(180.0, 35.0)];
[aPath moveToPoint:CGPointMake(180.0, 35.0)];
[aPath addLineToPoint:CGPointMake(180.0, 0.0)];
[aPath moveToPoint:CGPointMake(180.0, 0.0)];
[aPath addLineToPoint:CGPointMake(0.0, 0.0)];
[aPath closePath];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
if(tempButton.tag == 1)
shapeLayer.frame = m_cObjbuttonPtr1.bounds;
if(tempButton.tag == 2)
shapeLayer.frame = m_cObjbuttonPtr2.bounds;
if(tempButton.tag == 3)
shapeLayer.frame = m_cObjbuttonPtr3.bounds;
if(tempButton.tag == 4)
shapeLayer.frame = m_cObjbuttonPtr4.bounds;
if(tempButton.tag == 5)
shapeLayer.frame = m_cObjbuttonPtr5.bounds;
shapeLayer.path = aPath.CGPath;
[shapeLayer setStrokeColor:[[UIColor redColor] CGColor]];
shapeLayer.fillColor = [[UIColor redColor] CGColor];
shapeLayer.lineWidth = 2;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
if(tempButton.tag == 1)
gradientLayer.frame = m_cObjbuttonPtr1.bounds;
if(tempButton.tag == 2)
gradientLayer.frame = m_cObjbuttonPtr2.bounds;
if(tempButton.tag == 3)
gradientLayer.frame = m_cObjbuttonPtr3.bounds;
if(tempButton.tag == 4)
gradientLayer.frame = m_cObjbuttonPtr4.bounds;
if(tempButton.tag == 5)
gradientLayer.frame = m_cObjbuttonPtr5.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.46f alpha:0.0].CGColor,
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.14f alpha:0.0].CGColor,nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
if(tempButton.tag == 1){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, shapeLayer.frame.size.width, shapeLayer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[shapeLayer setFillRule:kCAFillRuleEvenOdd];
[shapeLayer setFillColor:[[UIColor orangeColor] CGColor]];
[m_cObjbuttonPtr1.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 2){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr2.layer.frame.size.width, m_cObjbuttonPtr2.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.46f alpha:0.0].CGColor,
(id)[UIColor colorWithRed:0.98f green:0.31f blue:0.14f alpha:0.0].CGColor,
nil];
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr2.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 3){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr3.layer.frame.size.width, m_cObjbuttonPtr3.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr3.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 4){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr4.layer.frame.size.width, m_cObjbuttonPtr4.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr4.layer addSublayer:shapeLayer];
}
if(tempButton.tag == 5){
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.startPoint = CGPointMake(0.5,1.0);
gradientLayer.endPoint = CGPointMake(0.5,0.0);
gradientLayer.frame = CGRectMake(0, 0, m_cObjbuttonPtr5.layer.frame.size.width, m_cObjbuttonPtr5.layer.frame.size.height);
NSMutableArray *colors = [NSMutableArray array];
for (int i = 0; i < 10; i++) {
[colors addObject:(id)[[UIColor colorWithHue:(0.1 * i) saturation:1 brightness:.8 alpha:1] CGColor]];
}
gradientLayer.colors = colors;
[gradientLayer setMask:shapeLayer];
[m_cObjbuttonPtr5.layer addSublayer:shapeLayer];
}
}

Move to few point with CAKeyframeAnimation

I have code :
NSMutableArray * pathArray = [[NSMutableArray alloc]init];
CGPoint currentPoint = CGPointMake(xp, yp);
[pathArray addObject:[NSValue valueWithCGPoint: currentPoint]];
NSMutableArray * pathArray = [algorithm CreatePath];
CGMutablePathRef path = CGPathCreateMutable();
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.values = pathArray;
pathAnimation.path = path;
pathAnimation.duration = 1.0;
[self.firstBall.ballLayer addAnimation:pathAnimation forKey:#"position"];
And in path array I have few CGPoints wrapped in NSValue. But when animation go its only move from first to last coordinate? Why it not use other points?
New code:
-(void)MoveBallWithAlgorithm:(CGPoint)start end:(CGPoint)end;
{
FindWayAlgorithm *algorithm = [[FindWayAlgorithm alloc]init];
algorithm.LX = algorithm.LY = self.columns;
[algorithm CreateBoard:self.fieldsArray];
[algorithm FindWay:start end:end];
CGMutablePathRef path = CGPathCreateMutable();
NSMutableArray * pathArray = [algorithm CreatePath];
#try
{
CGPathMoveToPoint(path, NULL, self.firstBall.ballCoordinates.x, self.firstBall.ballCoordinates.y);
for (NSValue * pointValue in pathArray) {
CGPoint point = [pointValue CGPointValue];
Field* field = [self FindFieldWithPoint:point];
CGPathAddLineToPoint(path, NULL, field.ballCoordinates.x, field.ballCoordinates.y);
}
}
#catch(NSException* ex)
{
NSLog(#"Bug captured when move ball with algorithm: %# %#",ex, [NSThread callStackSymbols]);
}
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.duration = 2.0;
pathAnimation.path = path;
[pathAnimation setDelegate:self];
[self.firstBall.ballLayer addAnimation:pathAnimation forKey:#"position"];
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag{
NSInteger firstBallIndex = [self.fieldsArray indexOfObject:self.firstBall];
NSInteger secondBallIndex = [self.fieldsArray indexOfObject:self.secondBall];
self.ballFrom = [self.fieldsArray objectAtIndex:firstBallIndex];
self.ballTo = [self.fieldsArray objectAtIndex:secondBallIndex];
self.ballTo.ballLayer = self.ballFrom.ballLayer;
CGPoint endPt = CGPointMake(self.secondBall.ballCoordinates.x,self.secondBall.ballCoordinates.y);
self.ballTo.ballLayer.frame = CGRectMake(endPt.x, endPt.y, self.ballSize, self.ballSize);
self.ballFrom.ballLayer = nil;
[self.fieldsArray replaceObjectAtIndex:firstBallIndex withObject:self.ballFrom];
[self.fieldsArray replaceObjectAtIndex:secondBallIndex withObject:self.ballTo];
self.firstBall = nil;
self.secondBall = nil;
}
My problem is resolved. I add:
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
Now my layer not back to first position ;)
The CAKeyframeAnimation documentation states:
Specifying a path overrides the values property.
so you should not set pathAnimation.path if you want to set the keyframe values with
pathAnimation.values = pathArray.
I tested it with a simple label and the following code:
NSArray * pathArray = #[
[NSValue valueWithCGPoint:CGPointMake(10., 10.)],
[NSValue valueWithCGPoint:CGPointMake(100., 10.)],
[NSValue valueWithCGPoint:CGPointMake(10., 100.)],
[NSValue valueWithCGPoint:CGPointMake(10., 10.)],
];
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.values = pathArray;
pathAnimation.duration = 5.0;
[self.label.layer addAnimation:pathAnimation forKey:#"position"];

Create Grid of UIVews in NSArray

What I am trying to do is align views in a grid that are in an array. I have created the views and the array.
for (int i = 0; i < [directoryContents count]; i++){
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,120)];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 100, 100);
button.accessibilityIdentifier = [directoryContents objectAtIndex:i];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 100, 20)];
label.textAlignment = NSTextAlignmentCenter;
label.text = [directoryContents objectAtIndex:i];
[containerView addSubview:button];
[containerView addSubview:label];
[self.view addSubview:containerView];
[_containerViewArray addObject:containerView];
}
[self layoutViews:_containerViewArray inView:self.view];
What I have working is aligning them next to each other the problem I am having is I need to have them wrap down instead of going off the edge. What I am doing to algin them is this
- (void)layoutViews:(NSArray *)views inView:(UIView *)contentView
{
NSInteger overallWidth = 0;
for ( UIView *view in views ) {
overallWidth += view.frame.size.width;
}
CGSize contentSize = contentView.frame.size;
CGFloat startOffset = (contentSize.height - overallWidth)/2.0;
CGFloat offset = startOffset;
for ( UIView *view in views ) {
CGRect frame = view.frame;
frame.origin.x = offset;
view.frame = frame;
offset += view.frame.size.width;
}
}
If we assumed that we have an array of sections (your views) and you need to layout 3 item per row the view has size 98*98 and spacing 6.5px horizontally and 8px Vertically
for (int i = 0; i< [sectionsArray count]; i++) {
int row = (int)i/3;
int col = i%3;
float x = 6.5 + (104.5*col);
float y = 8 + (106*row);
UIView *sectionView = [[UIView alloc] initWithFrame:CGRectMake(x, y, 98, 98)];
sectionView.backgroundColor = [UIColor clearColor];
//button
UIButton *sectionButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[sectionButton setTintColor:[UIColor grayColor]];
sectionButton.frame = CGRectMake(0, 0, 98, 98);
sectionButton.tag = i+100;
[sectionButton addTarget:self action:#selector(showSectionDetail:) forControlEvents:UIControlEventTouchUpInside];
[sectionView addSubview:sectionButton];
//adding title
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 75, 98, 20)];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.backgroundColor=[UIColor clearColor];
titleLabel.font=[UIFont fontWithName:#"Helvetica" size:14];
titleLabel.textColor = [UIColor colorWithRed:241.0/255.0 green:124.0/255.0 blue:22.0/255.0 alpha:1.0];
titleLabel.text = [[sectionsArray objectAtIndex:i] objectForKey:#"Title"];
[sectionView addSubview:titleLabel];
[titleLabel release];
[scroll addSubview:sectionView];
[sectionView release];
}
int numberOfRows;
if ([sectionsArray count]/3.0f == 0) {
numberOfRows = [sectionsArray count]/3;
}else{
numberOfRows = [sectionsArray count]/3 +1;
}
scroll setContentSize:CGSizeMake(320, numberOfRows*106);
Here's what I used until the UICollectionView was released, easy to modify to accommodate for how many rows you want in the grid, and the size of the views.
NSUInteger buttonWidth = 100;
NSUInteger buttonHeight = 100;
NSUInteger space = 5;
float scrollContentY = (ceilf((float)imageNames.count / 3.0f) * (buttonHeight + space));
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
int row = idx / 3;
int column = idx % 3;
UIView *view = [UIView new];
[view setBackgroundColor:[UIColor redColor]];
view.frame = CGRectMake((buttonWidth + space) * column + space, (buttonHeight + space) * row + space , buttonWidth, buttonHeight);
[view setTag:(NSInteger)idx];
[self.scrollView addSubview:view];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width, scrollContentY)];
}];
Mind you, this might not be advisable if you have a large array to enumerate because this doesn't have any kind of reusable views. It will alloc/init a view for every item in the array.