How to Create Right Angle View in Swift

UIKit Swift 5: Set UIView Rotation Angle

If I understand correctly, you want:

func rotate(view: UIView, to angle: Double) {
UIView.animate(withDuration: 0.5) {
view.transform = CGAffineTransform(rotationAngle: angle)
}
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
let newRad = deg2rad(newHeading.trueHeading)
rotate(view: compassImageView, to: newRad)
compassRad = newRad
}

Or it might be -newRad, depending on which way these angles go, which I could never remember :)

Rotate UIView around its center keeping its size

You're probably hitting a problem with Autolayout. You probably have constraints on the rotated view pinning it to the edges of the superview. When the transform is applied, Autolayout is updating the view's size to still fit within the superview.

You can experiment with different constraints (e.g. pinning the centre of the view to the centre of another view, and pinning the width and height to constant values) or turn Autolayout off for the rotated view, or, if these don't work or don't suit your needs, use a container view which is laid out under Autolayout, and add your rotating view to this, without using Autolayout.

This can only be done in code - you can make individual views subject to Autolayout or not by setting translatesAutoresizingMasksIntoConstraints to NO (Autolayout on) or YES (Autolayout off). You'll need to set the appropriate autoresizing masks if you switch a view from one to the other.

Triangle UIView - Swift

Updated for Swift 3:

class TriangleView : UIView {

override init(frame: CGRect) {
super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

override func draw(_ rect: CGRect) {

guard let context = UIGraphicsGetCurrentContext() else { return }

context.beginPath()
context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.closePath()

context.setFillColor(red: 1.0, green: 0.5, blue: 0.0, alpha: 0.60)
context.fillPath()
}
}


Swift 2:

import UIKit

class TriangleView : UIView {

override init(frame: CGRect) {
super.init(frame: frame)
}

required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}

override func drawRect(rect: CGRect) {

var ctx : CGContextRef = UIGraphicsGetCurrentContext()

CGContextBeginPath(ctx)
CGContextMoveToPoint(ctx, CGRectGetMinX(rect), CGRectGetMaxY(rect))
CGContextAddLineToPoint(ctx, CGRectGetMaxX(rect), CGRectGetMaxY(rect))
CGContextAddLineToPoint(ctx, (CGRectGetMaxX(rect)/2.0), CGRectGetMinY(rect))
CGContextClosePath(ctx)

CGContextSetRGBFillColor(ctx, 1.0, 0.5, 0.0, 0.60);
CGContextFillPath(ctx);
}
}

This will start from MinX, MaxY;

Draw a line from the start to MaxX, MaxY;

Draw a line from MaxX,MaxY to MaxX/2, MinY;

Then close the path to the start location.


The next part sets the color you want to use. In this example 255,127,0, Alpha 0.6
Then will fill the path you just drew above with the set color.

Then in your View Controller

Swift 3:

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()

let triangle = TriangleView(frame: CGRect(x: 10, y: 20, width: 25 , height: 30))
triangle.backgroundColor = .white
view.addSubview(triangle)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}


Swift 2:

class ViewController: UIViewController {

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.

let triangle = TriangleView(frame: CGRectMake(10, 20, 25, 30))
triangle.backgroundColor = .whiteColor()
view.addSubview(triangle)
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

However, this is going to cause the same problem as the frame of this view is still going to be a rectangle. UIKit works with rectangles, you would have to use another framework, like Sprite Kit.

get line to remain a perfect 90 degrees when create

The problem is this line:

bezier.addLine(to: secondTouch!)

This causes the line to follow the position of the touch, wherever it is. Instead, drop a perpendicular to the horizontal (I presume that is what you mean by 90 degrees) and add the line to that point on the horizontal. In other words, use the x component of secondTouch, but use as the y component the y component of startTouch.

bezier.addLine(to: CGPoint(x:secondTouch!.x, y:startTouch!.y)

How to rotate image in Swift?

This is an extension of UIImage that targets Swift 4.0 and can rotate just the image without the need for a UIImageView. Tested successfully that the image was rotated, and not just had its exif data changed.

import UIKit

extension UIImage {
func rotate(radians: CGFloat) -> UIImage {
let rotatedSize = CGRect(origin: .zero, size: size)
.applying(CGAffineTransform(rotationAngle: CGFloat(radians)))
.integral.size
UIGraphicsBeginImageContext(rotatedSize)
if let context = UIGraphicsGetCurrentContext() {
let origin = CGPoint(x: rotatedSize.width / 2.0,
y: rotatedSize.height / 2.0)
context.translateBy(x: origin.x, y: origin.y)
context.rotate(by: radians)
draw(in: CGRect(x: -origin.y, y: -origin.x,
width: size.width, height: size.height))
let rotatedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

return rotatedImage ?? self
}

return self
}
}

To perform a 180 degree rotation, you can call it like this:

let rotatedImage = image.rotate(radians: .pi)

If for whatever reason it fails to rotate, the original image will then be returned.

Smooth only top angles and imageview in Swift

I've tried the code you've posted. For whatever reason when I enter your constraints and recreate your view hierarch, the auto layout engine does not call viewDidLayoutSubviews after it does it's second pass. I could force it to but calling self.view.layoutIfNeeded() from viewWillAppear. For example:

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let rectShape = CAShapeLayer()
rectShape.frame = self.imageView.bounds
rectShape.path = UIBezierPath(roundedRect: self.imageView.bounds, byRoundingCorners: [.TopRight, .TopLeft], cornerRadii: CGSize(width: 10, height: 10)).CGPath
self.imageView.layer.backgroundColor = UIColor.greenColor().CGColor
self.imageView.layer.mask = rectShape
}

override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.view.layoutIfNeeded()
}

Results in:

Sample Image

With both corners rounded.

I would say a better, more elegant solution that avoids this auto layout glitch is to just set the corner radius of the image view container, as it seems like that what you're doing anyways. For example:

override func viewDidLoad() {
super.viewDidLoad()
self.imageView.clipsToBounds = true
self.imageContainerView.layer.cornerRadius = 10.0
self.imageContainerView.layer.masksToBounds = true
}

You can also do this from viewDidLoad because it doesn't depend on any of your views' frames being set.

Sample Image

Swift - How to create a view with a shape cropped in it

The easiest way to do this would be to create a png image with partly transparent white around the outside and a clear circle in the middle. Then stack 2 image views on top of each other, with the masking image on top, and set its "opaque" flag to false.

You could also do this by creating a CAShapeLayer and set it up to use a translucent white color, then install a shape that is the square with the hole cut out of it shape. You'd install that shape layer on top of your image view's layer.

The most general-purpose way to do that would be to create a custom subclass of UIImageView and have the init method of your subclass create and install the shape layer. I just created a gist yesterday that illustrated creating a custom subclass of UIImageView. Here is the link: ImageViewWithGradient gist

That gist creates a gradient layer. It would be a simple matter to adapt it to create a shape layer instead, and if you modified the layoutSubviews method you could make it adapt the view and path if the image view gets resized.

EDIT:

Ok, I took the extra step of creating a playground that creates a cropping image view. You can find that at ImageViewWithMask on github

The resulting image for my playground looks like this:

Image with circular mask



Related Topics



Leave a reply



Submit