How to have a smooth edges after rotating the UIView - ios

I am rotating a view by some angle by after rotating I am not getting the smooth edge of the view. Please check the attached image. Is there any way to have a smooth edge of UIView?
I have used the following statement for this purpose.
CGContextRotateCTM(currentContext, RADIANS(-5));

It helps a lot if you set shouldRasterize = true for the layer of your view.
yourView.layer.shouldRasterize = true
When the value of this property is true, the layer is rendered as a
bitmap in its local coordinate space and then composited to the
destination with any other content. Shadow effects and any filters in
the filters property are rasterized and included in the bitmap.
However, the current opacity of the layer is not rasterized. If the
rasterized bitmap requires scaling during compositing, the filters in
the minificationFilter and magnificationFilter properties are applied
as needed.

Try enabling anti-aliasing before rotating:
CGContextSetShouldAntialias(currentContext, true);

set 1 pixel transparent border. This will helps you magically.

Related

Drawing rounded rectangle with transparency in Skia

I'm trying to draw a rounded rectangle with transparency with the library Skia.
I get a perfect result if i'm using overlapping without transparency.
But when i'm using transparency, i get this:
That's what i get when i do not overlap:
Even if i modify the radius of the inner rectancle, there're still some overlaps/gabs.
My questitons:
What is the correct way to caluclate the radius of the inner rectangle, when i can accept some missplaced pixels?
Is there another way?
You can use saveLayerAlpha before drawing and then restore after drawing. This allows you to draw multiple paths, shapes, etc with a "global" alpha applied to the layer.

iOS: How to fill a rectangle except in one area?

I've used the CGContext based routine to fill a rectangle, but this time I actually want to fill all of a rectangle EXCEPT one part of it. I know this is possible in other drawing systems for other platofrm but can it be done with core graphics on iOS?
Both borderWidth and cornerRadius are animatable properties. So you could just animate them directly (using CABasicAnimation). In that rendering, you'd go from no border and no corners to having a border and corners in an animated way.
If you want to animate the rectangular tracing of the border, you'd need to use a CAShapeLayer (because the end of its path is animatable) and provide the illusion that way.

iOS Understanding Layer Masking

I am having some difficulty understanding on how layer masking works. Right now, I have a UIView with UILabels on it. I picture two layers - one with the UIView in the back and one for the labels on top. If I mask the UIView layer, the labels will be affected by the mask too.
The UILabels are children of the parent UIView, so I can understand a parent mask affecting the children as well.
However, when I look at it in terms of layers, it doesn't seem to make sense. Why does masking the deepest layer affect those on top?
Think of layers as sheets of paper. Think of the view's layer as a big sheet of white paper. As you figured out, the labels' layers are children of the view's layers. To relate, think of the labels' layers being strips of paper glued onto the big view's layer-sheet.
Let's say you wish to mask the layer with a circle. To translate that into our little analogy, you wish to cover the big view's layer-sheet with Harry Potter's invisibility cloak, with a circle shaped hole in it.
To do that, you'd cut the invisibility cloak to the same size as that of your view's layer-sheet.
cloakLayer.frame = bigViewLayer.frame;
Then, you'd carefully cut out a circle from it.
cloakLayer.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(0, 0) radius:15.0 startAngle:0.0 endAngle:2 * M_PI clockwise:YES];
cloakLayer.fillColor = [UIColor blackColor].CGColor; // the hole
Then, you'd paste this cloak-with-a-hole onto your big view's layer-sheet, carefully aligning the edges.
bigViewLayer.mask = cloakLayer;
What's gonna go invisible? Anything on the sheet (because the cloak was cut to the sheet's dimensions) that doesn't fall into the circle you removed from the cloak. That's the mask property.
Let's talk about the masksToBounds property.
Let's say while pasting the strips of label layer-sheets onto the big view's layer-sheet, you decided to place only half of the strip on the sheet, and made the rest hang off the edge(s).
Let's say you set masksToBounds to YES. What the gods of decoupage would do now is neatly cut off the parts of your labels' strips that are not within the edges of the big view's layer-sheet. That's the masksToBounds property.
Let's talk about borders. This is simple. Just pick a sharpie of borderColor whose nib is borderWidth points wide, and carefully draw on the edges of the view's layer-sheet. That's it.
I hope you get things now and can make your own analogies for other properties of the wonderful CALayer.
As you said, the UIView is the parent, and the UILabels are the children. When it comes time to update the screen, the UIView starts with a blank canvas. It draws itself into the canvas, and then has the children draw themselves into the canvas. When the children are drawing, they are subject to constraints imposed by the parent, e.g. clipping and masking.
iOS CALayer.mask
[CALayer]
[iOS CALayer.masksToBounds]
CALayer has a mask property which is CALayer, which applies mask's alpha channel to mask parent's layer.
layer + mask = masked layer

iOS animate clipToBounds, masksToBounds, or similar

I have an image view that starts out cropping it's image with clipsToBounds and content mode set as "scale aspect fill", and I want it to "enlarge" the image to the whole image. If clipsToBounds=NO was an animatable property, that would be exactly what I want, which it does not seem to be. Is there a way to animate that?
If not, another way would be resizing the view so it is the same width-height ratio as the image's size, while keeping it no smaller than the image view was to begin with (i.e. minimal increate to height or width, no decrease to either). I'm not sure the best approach to doing this, considering the image could be much bigger or smaller than the image view, and the image's width-height ratio could be just about anything (but it will usually be an iOS device camera photo).
UPDATE 1: It seems like layer.masksToBounds would work, the documentation says that it is animatable, but my code does not seem to work:
CABasicAnimation *layerAnim = [CABasicAnimation animationWithKeyPath:#"masksToBounds"];
layerAnim.fromValue = #(YES);
layerAnim.toValue = #(NO);
layerAnim.removedOnCompletion = YES;
layerAnim.duration = 1.0;
[_imageView.layer addAnimation:layerAnim forKey:#"masksToBounds"];
I am running this layer animation at the same time as a UIView block animation that is changing the frame and transform of the image view, if that matters.
UPDATE 2: I did not have this core animation in the UIView animation block, which according to the documentation, it should be. I have moved the above code into the animation block, but it is still not animating (change happens instantly). I'm beginning to think that "animatable" simply means it can be placed in an animation, not that it will actively animate over time.
So you don't want your image to grow, but you want it to be clipped at first, and then the outer pixels are exposed?
You can do that using Core Animation and a layer mask.
Here's what you do:
Set the image view's clipsToBounds to FALSE, so the image would fully display if you let it.
Create a CAShapeLayer that's the size of the whole image. Create a rectangular bezier path that's the size of the initial image. Install that bezier path's CGPath as the path of the shape layer.
Set the shape layer's fill color to an opaque color
Then install the shape layer as the mask of your image view's layer. That will cause the image to be clipped to the shape of the shape layer.
Now, if you change the path that's installed in the shape layer to a rectangle that's the full size of the image, the system will animate the change for you.
As of March 21st 2019, it seems like the masksToBounds documentation is just wrong. masksToBounds does not seem to be animatable. I have tried animating masksToBounds with CABasicAnimation and CAKeyframeAnimations and it doesn't seem to work.

Make an EAGLView transparent?

It's possible to place in a UIViewController object an EAGLView object and make the background of EAGLView transparent in order to view what is behind?
Thanks.
-UPDATE----
I've tried which appears in this post. But still the layer of the EAGLView appears like a black square. :(
Any idea why this is not working for me?
openGLView.opaque = NO
Also pay attention on correct opacity in alpha channel of OpenGL framebuffer.
And pay attention on Tark answer about performance drop.
There is no such thing as an EAGLView, but it is definitely possible to have a CAEAGLLayer with a transparent background on top of UIKit content. It is not recommended however, from the docs:
Because an OpenGL ES rendering surface is presented to the user using Core Animation, any effects and animations you apply to the layer affect the 3D content you render. However, for best performance, do the following:
Set the layer’s opaque attribute to TRUE.
Set the layer bounds to match the dimensions of the display.
Make sure the layer is not transformed.
Avoid drawing other layers on top of the CAEAGLLayer object. If you must draw other, non OpenGL content, you might find the performance cost acceptable if you place transparent 2D content on top of the GL content and also make sure that the OpenGL content is opaque and not transformed.
When drawing landscape content on a portrait display, you should rotate the content yourself rather than using the CAEAGLLayer transform to rotate it.

Resources