I'm developing an animated column bar chart and i having some trouble.
The bars show up with an scale animation. At the beginning all columns have 1 point size and will scale till a predefined height.
The point is: I want to draw a gradient into the columns (They are subclasses of UIView) and want the scale animation to recalculate the gradient.
Until now, i have drawn the gradient, but when the column scale, the gradient does not scale with it.
As the view have 1 point height, the gradient is show as 1 color only.
Can someone give me a north to solve this issue?
Solved the problem!
i was using scale instead of changing the view's bounds..
Was
view.transform = CGAffineTransformMakeScale(1.0, scaleY.floatValue);
Must be
view.bounds = CGRectMake(view.bounds.origin.x, view.bounds.origin.y * scaleY.floatValue, view.bounds.size.width, view.bounds.size.height * scaleY.floatValue);
Where scaleY was calculated before and is a NSNumber that contains the Y scale factor.
It's not necessary to set
view.contentMode = UIViewContentModeRedraw;
Thank you DarkDusk for the help.
Try setting the contentMode:
myView.contentMode = UIViewContentModeRedraw;
This will force a redraw on every size change.
Related
I am building a custom UIView that you can rotate and resize. I can resize the UIView by dragging the corners of the UIView. I calculate how much I have dragged then change the frame of the UIView accordingly.
However, I am running into problems once I added a rotation gesture recognizer to the view. If I rotate or apply a transform to the view, I no longer know how to calculate drag distance and change the frame of the view. How could I calculate the width and height change between my new view and the original view when things are put at an added angle or if they have some other transform, like a translation transform?
I thought of possibilities to set the view's transform back to .identity, change the size of the view, then re-apply its transform, but I'm not sure how to actually go about implementing this.
After applying transform you can not use frame
You have two options
1) First Calculate everything using center of your view
2) As you know apply identity and change frame
for point 2 I have added example that might helpful to you
let transform = imageView.transform
imageView.transform = CGAffineTransform.identity
var rect: CGRect = imageView.frame
rect = // Change Rect here
imageView.frame = rect // Assign it
imageView.transform = transform // Apply Transform
I am testing a UIView using a UISlider as in the example images below:
I have a custom UIView with a yellow background that draws the gray square, the drawRect method is like so:
-(void)drawRect:(CGRect)rect{
NSLog(#"Draw rect called");
UIBezierPath* squarePath = [UIBezierPath bezierPathWithRect: CGRectMake(10, 10, 100, 100)];
[UIColor.grayColor setFill];
[squarePath fill];
}
And the method for my slide changing value:
- (IBAction)changeValue:(id)sender {
CGAffineTransform transform = CGAffineTransformScale(CGAffineTransformIdentity, self.slider.value, self.slider.value);
self.tableView.transform = transform;
[self.tableView setNeedsDisplay];
}
I dont understand why the square is getting larger. I've noticed that drawRect is called every time the slider is moved. If this happens then why is the square size changing? Shouldn't it remain the same size and just the frame grow with the square in the top left corner?
My second question is, how would I change the code so just the frame grows and the drawing size stays the same? I ask this because actually I want the drawing size to change dynamically using my own code in drawRect.
Any pointers would be really appreciated! thanks!
The reason why the size of the square changes is because you've transformed it. Transformations don't just affect the frame of a view; they will affect the content. The square is getting drawn into its context at its constant size (100x100) and then the transform is stretching it before it gets rendered.
The reason why it's not expanding to the right and down is because by default the anchor point of a transform is the center of the bounds. Thus it'll scale from the center outwards. From the documentation:
The origin of the transform is the value of the center property ...
Transformations aren't intended to be used to simply scale the width and height of your frame. The frame property is for that. Simply store the view's frame in a variable, change its width and height, then set it back. In your drawRect: code you can check the dimensions of the rectangle that's given to you and make your square's width/height a percentage of that.
I'm trying to scale a view Horizontally but i'm not getting the results i expected.
view.bounds = CGRectMake(view.bounds.origin.x, view.bounds.origin.y , view.bounds.size.width * scaleX, view.bounds.size.height );
view.center = CGPointMake(view.bounds.origin.x, view.center.y);
As you can see at the code above, i want to scale the view just to the right side. This is why i changed the center of the view.
The problem is that the view stills scaling to both sides!
I did the same logic to scale another UIView vertically and got the result i expected.
Just found the problem.
when setting certer, the new point must be relative to frame, not bounds.
so, i get the code:
view.center = CGPointMake(-view.frame.origin.x, view.center.y);
Hope it helps somebody..
Thx for help
If the origin of your view's frame is in the top-left (which is the default), increasing the width of your view should scale it to the right only.
This should work:
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width * scaleX, view.frame.size.height);
You do not need to adjust the origin/center point to scale only to the right.
Try using an affine transform instead:
view.transform = CGAffineTransformMakeScale(scaleX, 1)
And then setting the center.
I have a round image that I want to "squish" vertically so that it looks more like a horizontal line, then expand it back to the original shape. I thought this would work by setting the layer's anchor point to the center and then animating the frame via UIViewAnimation with the height of the frame = 1.
[self.imageToSquish.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
CGRect newFrame = CGRectMake(self.imageToSquish.frame.origin.x, self.imageToSquish.frame.origin.y, self.imageToSquish.frame.size.width, 1 );
[UIView animateWithDuration:3
animations:^{self.imageToSquish.frame = newFrame;}
completion:nil];
But the image shrinks toward the top instead of around the center.
You’re giving it a frame that has its origin—at the top left—in the same position as it started. You probably want to do something more like this, adding half the image’s height:
CGRect newFrame = CGRectMake(self.imageToSquish.frame.origin.x, self.imageToSquish.frame.origin.y + self.imageToSquish.frame.size.height / 2, self.imageToSquish.frame.size.width, 1);
Alternatively—and more efficiently—you could set the image view’s transform property to, say, CGAffineTransformMakeScale(1, 0.01) instead of messing with its frame. That’ll be centered on the middle of the image, and you can easily undo it by setting the transform to CGAffineTransformIdentity.
I have a UIImageView add to a UIView as a subview. When I apply a transformation on the UIView's layer the UIImageView gets blurry. Why is that? How can this problem be resolved?
view.layer.position = newPosition;
I apply only this transformation.
Edit:
I've tested it and if I apply other transformations like these:
view.layer.transform = newTransform;
view.layer.zPosition = newZPosition;
then the blurry doesn't appear, only if I change the layer position.
Use
blurryDialog.frame = CGRectIntegral(blurryDialog.frame);
To set the frame coordinates to integer values
I found the answer. When you set the position of a layer or a view then the origin of it can be float values and this causes the blurry thing.
So the solution is to set also the frame's origin after you set the position. You just have to set the frame's position to integer values. On the UI this change won't be seen, but the image will not be blurry.