Core Plot CPTBorderedLayer not animating - calayer

I have a CPTPlotSpaceAnnotation whose contentLayer property is a CPTBorderedLayer object. I'm trying to animate the CPTBorderedLayer object with the following:
CGRect originalBounds = annotation.contentLayer.bounds;
CGRect expandedBounds = annotation.contentLayer.bounds;
expandedBounds.size.width *= 1.5f;
expandedBounds.size.height *= 1.5f;
CABasicAnimation* boundsAnimation = [CABasicAnimation animationWithKeyPath:#"bounds"];
boundsAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
boundsAnimation.fromValue = [NSValue valueWithCGRect:originalBounds];
boundsAnimation.toValue = [NSValue valueWithCGRect:expandedBounds];
boundsAnimation.duration = 1.0f;
boundsAnimation.removedOnCompletion = NO;
[annotation.contentLayer addAnimation:boundsAnimation forKey:#"bounds"];
But this isn't animating. Setting the bounds directly to expandedBounds works, but it won't animate. Thoughts?

The issue was that I had the collapsesLayers property on my CPTGraphHostingView set to YES. Setting it to NO fixed the issue.

Related

CorePlot hosting view and CPTXYGraph frame issues

I'm trying to set up a simple pie chart in my OSX project, in Xcode 5, following the tutorial at :http://www.raywenderlich.com/13269/how-to-draw-graphs-with-core-plot-part-1.
The problem is that the graph doesn't show and both the CPTGraphHostingView and the CPTXYGraph have a height and width of 0.00.
Here is the code I use, after which I should be able to see the title for the graph in the view. The hostView is a reference to an NSView in the xib file.
-(void)configureHost {
self.graphHostingView = [(CPTGraphHostingView *)[CPTGraphHostingView alloc] initWithFrame:CGRectMake(0, 0, 1103, 532)];
NSLog(#"%f", self.graphHostingView.frame.size.width);
[hostView addSubview:self.graphHostingView];
}
-(void)configureGraph {
NSRect parentRect = CGRectMake(0, 0, 1103, 532);
//create graph
CPTGraph *graph = [[CPTXYGraph alloc] init];
[graph setFrame:parentRect];
NSLog(#"%f", graph.frame.size.width);
self.graphHostingView.hostedGraph = graph;
graph.paddingBottom = 0.0f;
graph.paddingLeft = 0.0f;
graph.paddingTop = 0.0f;
graph.paddingRight = 0.0f;
graph.axisSet = nil;
//text in graph
CPTMutableTextStyle *textStlye = [CPTMutableTextStyle textStyle];
textStlye.color = [CPTColor grayColor];
textStlye.fontName = #"Helvetica-Bold";
textStlye.fontSize = 16.0f;
//graph title
graph.title = #"Title";
graph.titleTextStyle = textStlye;
graph.titlePlotAreaFrameAnchor = CPTRectAnchorTop;
graph.titleDisplacement = CGPointMake(0.0f, -12.0f);
self.theme = [CPTTheme themeNamed:kCPTPlainWhiteTheme];
}
Not as important, but I'm also getting an error when I use the kCPTPlainWhiteTheme const, or other theme consts. a thread 1:EXC_BAD_ACCESS(code=1, address=0x0).
It's probably an obvious issue but I just cant see it.
Thanks in advance.

How to rotate a view that is already moving with core animation?

I use core animation (CAKeyframeAnimation) to move a view using a given path and at the same time to display the path (dotted line).
While animating the view along the given path i want it to face the direction it is going to.
In other words i want the view to rotate progressively while moving.
After some research i find out it may be possible to do it with CAKeyFrameAnimation using keytimes and values but no success. I have no idea on how to implement it.
As i am still new in IOS programming, i don't know if there is another (better?) way to do such kind of animation.
Here is the code i use:
- (CGMutablePathRef) getPathFromPoints:(NSMutableArray*)points {
CGMutablePathRef path = CGPathCreateMutable();
CGPoint p = [points[0] CGPointValue];
CGPathMoveToPoint(path, NULL, p.x, p.y);
for (int i = 1; i < points.count; ++i) {
p = [points[i] CGPointValue];
CGPathAddLineToPoint(path, NULL, p.x, p.y);
}
return path;
}
- (void)animateView:(UIView*)view
withPoints:(NSMutableArray*)points
withFillMode:(NSString*)fillMode
withDuration:(int)duration
withRepeatCount:(int)repeat
withSpeed:(int)speed
withDashed:(BOOL)dashed{
CGMutablePathRef path = [self getPathFromPoints:points];
if (dashed) {
CAShapeLayer* pathLayer = [CAShapeLayer layer];
pathLayer.frame = view.superview.layer.bounds;
pathLayer.bounds = view.superview.layer.bounds;
pathLayer.geometryFlipped = NO;
pathLayer.path = path;
pathLayer.strokeColor = [[UIColor blackColor] CGColor];
pathLayer.fillColor = nil;
pathLayer.lineWidth = 10.0f;
pathLayer.lineJoin = kCALineJoinBevel;
[pathLayer setLineDashPattern:[[NSArray alloc] initWithObjects:
[NSNumber numberWithInt:15],
[NSNumber numberWithInt:15],
nil]];
[view.superview.layer addSublayer:pathLayer];
CABasicAnimation *dottedAnimation = [CABasicAnimation animationWithKeyPath:#"strokeEnd"];
dottedAnimation.duration = duration;
dottedAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
dottedAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[pathLayer addAnimation:dottedAnimation forKey:#"strokeEnd"];
[view.superview bringSubviewToFront:view];
}
CAKeyframeAnimation* pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = fillMode;
pathAnimation.duration = duration;
pathAnimation.repeatCount = repeat;
pathAnimation.speed = speed;
pathAnimation.path = path;
[view.layer addAnimation:pathAnimation forKey:_myAnimationKey];
CGPoint p = [[points lastObject] CGPointValue];
view.layer.position = CGPointMake(p.x, p.y);
}
Thank you in advance for you help,
Have a look at CAKeyframeAnimation's rotationMode property. That should accomplish exactly what you are hoping to do.
Add this line to the -animateView: method where the properties for the *pathAnimation CAKeyframeAnimation instance are being set:
pathAnimation.rotationMode = kCAAnimationRotateAuto;
There's also another setting value, kCAAnimationRotateAutoReverse, that allows the animated object to maintain an anti-parallel orientation with respect to the path tangent.
Link to Apple docs: CAKeyframeAnimation

UITextView, setContentOffset and missing bottom part

For some strange reason, my UITextView's text appears cropped when the scrollofset is set.
Here's what it looks like:
This happens after doing:
textview.contentInset = UIEdgeInsetsZero;
[textview setContentOffset:CGPointMake(0, startypos + offset_yshift) animated:NO];
I tried manually setting contentSize.height, but that introduced another strange behavior, where the content offset seems to be ignored..
''Edit'': This is the code used to instantiate the textfield:
CGRect myImageRect = CGRectMake(-50.0f, -50.0f, 40.0f, 40.0f);
textview = [[UITextView alloc] initWithFrame: myImageRect];
textview.autocapitalizationType = UITextAutocapitalizationTypeNone;
[textview setScrollEnabled:YES];
textview.hidden = YES;
textview.contentInset = UIEdgeInsetsZero;
textview.opaque = NO;
textview.backgroundColor = [UIColor clearColor];
textview.textColor = [UIColor colorWithWhite:1 alpha:1];
textview.textAlignment = NSTextAlignmentCenter;
textview.frame = CGRectMake(0, 0, 250, 30);
textview.scrollEnabled = NO;
And the "update" code that checks the content positioning every frame:
// setting the actual size here
UITextPosition * pos = [textview positionFromPosition: textview.endOfDocument offset:nil];
CGRect therect = [textview caretRectForPosition:pos];
CGRect frame = textview.frame;
if([textview.text length] == 0){
frame.size.height = 30;
} else {
frame.size.height = therect.origin.y + therect.size.height;
}
// and here, we're changing the frame variable's height to max to 50
if(frame.size.height > 50){
frame.size.height = 50;
}
frame.size.width = desiredwidth; // some other variable
textview.frame = frame;
/*
... snip, unrelated code ...
*/
// later on
textview.contentInset = UIEdgeInsetsZero;
[textview setContentOffset:CGPointMake(0, startypos + offset_yshift) animated:NO];
As you can imagine, the setContentOffset bit there is what's causing the issue.
What is going on?
please try this from prev post
CGPoint offset = CGPointMake(0, self.textView.contentSize.height - self.textView.frame.size.height);
[self.textView setContentOffset: CGPointMake(0,0) animated:NO];
or
[self.textView setContentOffset:bottomOffset animated:YES];
[post]: UITextView contentOffset on iOS 7 "prev post"\
I ran into a very similar issue in iOS7 with UITextField - looks almost exactly the same. Mine had to do with content insets as well.
The solution (for me) - was to eliminate the UITextField from nib/storyboard and instantiate it and add it to the view purely from code. Behavior worked as expected afterwards.
I don't know what was up other than it probably being a iOS7 / XCode 5 bug... Curious to know if that solves it for you too.
My thougts would be, to adjust the size of the UITextView based on its content.
Like asked here: how-do-i-size-a-uitextview-to-its-content
Code taken from jhibberd ´s answer
- (void)textViewDidChange::(UITextView *)textView
{
CGFloat fixedWidth = textView.frame.size.width;
CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = textView.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
textView.frame = newFrame;
}

Inaccurate rotation with CABasicAnimation... doesn't match the correct angle

I am developing a maps application. I draw an animated line in the map and then use an image (a ruler image) which should be draw just over the line. To draw the line I use a CABasicAnimation with path:
-(void)lineaAnimation {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"path"];
animation.duration = animDuration;
animation.delegate=self;
animation.repeatCount = 0;
animation.autoreverses = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = (id)inip;
animation.toValue = (id)finp;
animation.fillMode=kCAFillModeForwards;
animation.removedOnCompletion=NO;
[shapeLayer addAnimation:animation forKey:#"animatePath"];
}
-(void)linea:(CGPoint)origen to:(CGPoint)destino animado:(BOOL)anim duracion:(float)durac inicio:(float)delay {
inip = CGPathCreateMutable();
finp = CGPathCreateMutable();
CGPathMoveToPoint(inip, nil, origen.x, origen.y);
CGPathAddLineToPoint(inip, nil, origen.x, origen.y);
CGPathCloseSubpath(inip);
CGPathMoveToPoint(finp, nil, origen.x, origen.y);
CGPathAddLineToPoint(finp, nil, destino.x, destino.y);
CGPathCloseSubpath(finp);
rootLayer = [CALayer layer];
rootLayer.frame = fondo.bounds;
[fondo.layer addSublayer:rootLayer];
shapeLayer = [CAShapeLayer layer];
shapeLayer.path = inip;
UIColor *fillColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7];
shapeLayer.fillColor = fillColor.CGColor;
UIColor *strokeColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.7];
shapeLayer.strokeColor = strokeColor.CGColor;
shapeLayer.lineWidth = 5.0;
shapeLayer.fillRule = kCAFillRuleEvenOdd;
[morrallaLayer addObject:shapeLayer];
[rootLayer addSublayer:shapeLayer];
animDuration=durac;
[self performSelector:#selector(lineaAnimation) withObject:nil afterDelay:delay];
}
Then I try to move the center of the rule to the point and rotate the ruler image using this code:
delta=acos((destino.y-origen.y)/(destino.x-origen.x));
giroIni=0.0;
giroFin=delta;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.fromValue= [NSNumber numberWithFloat:giroIni];
animation.toValue= [NSNumber numberWithFloat:giroFin];
animation.delegate = self;
animation.repeatCount = 0;
animation.autoreverses = NO;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.duration = animDuration;
animation.fillMode=kCAFillModeForwards;
animation.removedOnCompletion=NO;
[ruleL addAnimation:animation forKey:#"giroAngulo"];
The problem is that the ruler borderline doesn't match the line draw, there are around a degree of difference depending on the final orientation... why?
Thanks a lot!
Ooooops... sorry for your time :(
I found the problem and.. as usual the error is not in the stars but in ourselves
I use the acos function when OBVIOUSLY I should use atan

Image size resets to original after performing pich using UIPichGestureRecognizer in iphone

I have one view controller in which I have added UIScrollView & UIImageView programatically. I have added UIPichGestureRecognizer to the UIImageView. My UIImageView is added to UIScrollView as a subview.
My problem is when I try to pinch the image , it zoom in. But when I release the touches from screen it again come to its default size. I can not find the error in code. Please help me.
Below is my code
- (void)createUserInterface {
scrollViewForImage = [[UIScrollView alloc]initWithFrame:CGRectMake(20.0f, 60.0f, 280.0f, 200.0f)];
scrollViewForImage.userInteractionEnabled = YES;
scrollViewForImage.multipleTouchEnabled = YES;
scrollViewForImage.backgroundColor = [UIColor redColor];
scrollViewForImage.autoresizesSubviews = YES;
scrollViewForImage.maximumZoomScale = 1;
scrollViewForImage.minimumZoomScale = .50;
scrollViewForImage.clipsToBounds = YES;
scrollViewForImage.delegate = self;
scrollViewForImage.bouncesZoom = YES;
scrollViewForImage.contentMode = UIViewContentModeScaleToFill;
[self.contentView addSubview:scrollViewForImage];
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 280.0f, 200.0f)];
[imageView setBackgroundColor:[UIColor clearColor]];
imageView.userInteractionEnabled = YES;
imageView.multipleTouchEnabled = YES;
UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinch:)];
[pinchRecognizer setDelegate:self];
[imageView addGestureRecognizer:pinchRecognizer];
//[self.contentView addSubview:imageView];
[self.scrollViewForImage addSubview:imageView];
scrollViewForImage.contentSize = CGSizeMake(imageView.frame.size.width , imageView.frame.size.height);
}
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)inScroll {
return imageView;
}
-(void)pinch:(id)sender {
[self.view bringSubviewToFront:[(UIPinchGestureRecognizer*)sender view]];
if([(UIPinchGestureRecognizer*)sender state] == UIGestureRecognizerStateEnded) {
lastScale = 1.0;
return;
}
CGFloat scale = 1.0 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]);
CGAffineTransform currentTransform = [(UIPinchGestureRecognizer*)sender view].transform;
CGAffineTransform newTransform = CGAffineTransformScale(currentTransform, scale, scale);
[[(UIPinchGestureRecognizer*)sender view] setTransform:newTransform];
lastScale = [(UIPinchGestureRecognizer*)sender scale];
}
From what I can see the problem lies here:
scrollViewForImage.maximumZoomScale = 1;
You are setting the maximum zoom scale of the image to 1 x its full size. This means once you finish pinching the image, it will scale back to 1 x its size.
If you want to be able to zoom the image to a larger size, try settings this value to be higher than 1. e.g.
scrollViewForImage.maximumZoomScale = 3;

Resources