UIImageView Animation Playground - swift

import UIKit
import PlaygroundSupport
import XCPlayground
//main window
let view = UIView(frame: CGRect(x:0, y: 0, width: 480, height: 320))
//array of images
let animationPictures: [UIImage] =
[
UIImage(named: "first.png")!,
UIImage(named: "second.png")!
]
var animationBkg = UIImageView()
animationBkg.animationImages = animationPictures;
animationBkg.animationDuration = 0.5
animationBkg.startAnimating()
Here is the code I currently have. the goal is to have these two images playing one after another as an animation, but it isn't working. In the preview of my code, all it has is a black square.

let animationPictures: [UIImage] =
[
UIImage(named: "first.png")!,
UIImage(named: "second.png")!
]
//animation
var animationView = UIImageView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(480), height: CGFloat(320)))
animationView.animationImages = animationPictures
animationView.animationDuration = 1.5
animationView.animationRepeatCount = 0
animationView.startAnimating()
view.addSubview(animationView)
I found a solution to my own problem. Thanks for the help

Related

issue with animation in swift playground

I'm totally new to animations with swift and I started this concept by using playground here's my code below I have no "idea" why it doesn't work.
import UIKit
import PlaygroundSupport
let liveViewFrame = CGRect(x: 0, y: 0, width: 500, height: 500)
let liveView = UIView(frame: liveViewFrame)
liveView.backgroundColor = .white
PlaygroundPage.current.liveView = liveView
let smallFrame = CGRect(x: 0, y: 0, width: 100, height: 100)
let square = UIView(frame: smallFrame)
square.backgroundColor = .purple
liveView.addSubview(square)
UIView.animate(withDuration: 3.0) {
liveView.backgroundColor = .blue
}
This piece of code is working fine

Custom UIImageView Border

I'm trying to make a border like this:
With this code:
self.slot1.layer.cornerRadius = self.slot1.bounds.height / 2
self.slot1.layer.borderWidth = 1.5
self.slot1.layer.borderColor = UIColor.orange.cgColor
It produces:
How can i add a "spacing" between the border and the actual image?
You can achieve this using below extension
extension UIImage {
func imageWithInsets(insets: UIEdgeInsets) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: self.size.width + insets.left + insets.right,
height: self.size.height + insets.top + insets.bottom), false, self.scale)
let _ = UIGraphicsGetCurrentContext()
let origin = CGPoint(x: insets.left, y: insets.top)
self.draw(at: origin)
let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageWithInsets
}
}
Use below code to add space between image and border, i add here 20 you can give your own space
self.slot1.layer.cornerRadius = self.slot1.bounds.height / 2
self.slot1.layer.borderWidth = 1.5
self.slot1.layer.borderColor = UIColor.orange.cgColor
let image = self.slot1.image?.imageWithInsets(insets: UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20))
self.slot1.image = image
Hope this help!
Instead of trying to make space in between, take one UIView inside that put your UIImageView. UIImageView should have less width and height, then add corner radius to both but add border color to UIVIew only.
Your UI should be like this :
Run in playground
import PlaygroundSupport
import UIKit
let iv = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 200, height: 200))
PlaygroundPage.current.liveView = iv
iv.backgroundColor = .blue
iv.layer.cornerRadius = 100
iv.layer.borderColor = UIColor.red.cgColor
iv.layer.borderWidth = 5
iv.layer.sublayers?.count
let layer2 = CAShapeLayer()
let newFrame = iv.bounds.insetBy(dx: 7, dy: 7)
layer2.path = UIBezierPath(roundedRect: newFrame, cornerRadius: newFrame.height / 2).cgPath
layer2.frame = iv.bounds
layer2.lineWidth = 5
layer2.strokeColor = UIColor.yellow.cgColor
layer2.fillColor = UIColor.clear.cgColor
iv.layer.addSublayer(layer2)

Circular crop for photos from photo library when using UIImagePickerController

I am trying to change the square crop tool to circular one for the images selected from Photo Library in Swift 4. I tried many old codes available in here with no luck. Can somebody please help me.
There are mainly 2 issues in this code.
It doesn't hide the already existing square cropping area.
It shows the choose and cancel buttons under the old overlay, so cant tap on it.
Any help would be appreciated.
My code:
private func hideDefaultEditOverlay(view: UIView)
{
for subview in view.subviews
{
if let cropOverlay = NSClassFromString("PLCropOverlayCropView")
{
if subview.isKind(of: cropOverlay) {
subview.isHidden = true
break
}
else {
hideDefaultEditOverlay(view: subview)
}
}
}
}
private func addCircleOverlayToImageViewer(viewController: UIViewController) {
let circleColor = UIColor.clear
let maskColor = UIColor.black.withAlphaComponent(0.8)
let screenHeight = UIScreen.main.bounds.size.height
let screenWidth = UIScreen.main.bounds.size.width
hideDefaultEditOverlay(view: viewController.view)
let circleLayer = CAShapeLayer()
let circlePath = UIBezierPath(ovalIn: CGRect(x: 0, y: screenHeight - screenWidth, width: screenWidth, height: screenWidth))
circlePath.usesEvenOddFillRule = true
circleLayer.path = circlePath.cgPath
circleLayer.fillColor = circleColor.cgColor
let maskPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight), cornerRadius: 0)
maskPath.append(circlePath)
maskPath.usesEvenOddFillRule = true
let maskLayer = CAShapeLayer()
maskLayer.path = maskPath.cgPath
maskLayer.fillRule = kCAFillRuleEvenOdd
maskLayer.fillColor = maskColor.cgColor
viewController.view.layer.addSublayer(maskLayer)
// Move and Scale label
let label = UILabel(frame: CGRect(x: 0, y: 20, width: view.frame.width, height: 50))
label.text = "Move and Scale"
label.textAlignment = .center
label.textColor = UIColor.white
viewController.view.addSubview(label)
}

How to apply an inverse text mask in Swift?

I am trying programmatically create a layer with transparent text. Everything I try doesn't seem to work. My end goal is to create an inner shadow on text.
Instead of a circle as in the code below I want text.
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = .white
// MASK
let blackSquare = UIView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
blackSquare.backgroundColor = .black
view.addSubview(blackSquare)
let maskLayer = CAShapeLayer()
// Create a path with the rectangle in it.
let path = CGMutablePath()
path.addArc(center: CGPoint(x: 100, y: 100), radius: 50, startAngle: 0.0, endAngle: 2.0 * .pi, clockwise: false)
path.addRect(CGRect(x: 0, y: 0, width: blackSquare.frame.width, height: blackSquare.frame.height))
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.path = path;
maskLayer.fillRule = kCAFillRuleEvenOdd
blackSquare.layer.mask = maskLayer
maskLayer.masksToBounds = false
maskLayer.shadowRadius = 4
maskLayer.shadowOpacity = 0.5
maskLayer.shadowOffset = CGSize(width: 5, height: 5)
view.addSubview(blackSquare)
I'm also able to use text as a mask but I'm unable to invert the mask. Any help is appreciated.
EDIT:
I figured it out based on Rob's answer as suggested by Josh. Here's my playground code.
import Foundation
import UIKit
import PlaygroundSupport
// view
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = .black
// button
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
button.setTitle("120", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNextCondensed-UltraLight", size: 200)
view.addSubview(button)
addInnerShadow(button: button)
func addInnerShadow(button: UIButton) {
// text
let text = button.titleLabel!.text!
// get context
UIGraphicsBeginImageContextWithOptions(button.bounds.size, true, 0)
let context = UIGraphicsGetCurrentContext()
context?.scaleBy(x: 1, y: -1)
context?.translateBy(x: 0, y: -button.bounds.size.height)
let font = button.titleLabel!.font!
// draw the text
let attributes = [
NSAttributedStringKey.font: font,
NSAttributedStringKey.foregroundColor: UIColor.white
]
let size = text.size(withAttributes: attributes)
let point = CGPoint(x: (button.bounds.size.width - size.width) / 2.0, y: (button.bounds.size.height - size.height) / 2.0)
text.draw(at: point, withAttributes: attributes)
// capture the image and end context
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// create image mask
let cgimage = image?.cgImage!
let bytesPerRow = cgimage?.bytesPerRow
let dataProvider = cgimage?.dataProvider!
let bitsPerPixel = cgimage?.bitsPerPixel
let width = cgimage?.width
let height = cgimage?.height
let bitsPerComponent = cgimage?.bitsPerComponent
let mask = CGImage(maskWidth: width!, height: height!, bitsPerComponent: bitsPerComponent!, bitsPerPixel: bitsPerPixel!, bytesPerRow: bytesPerRow!, provider: dataProvider!, decode: nil, shouldInterpolate: false)
// create background
UIGraphicsBeginImageContextWithOptions(button.bounds.size, false, 0)
UIGraphicsGetCurrentContext()!.clip(to: button.bounds, mask: mask!)
view.backgroundColor!.setFill()
UIBezierPath(rect: button.bounds).fill()
let background = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let backgroundView = UIImageView(image: background)
// add shadows
backgroundView.layer.shadowOffset = CGSize(width: 2, height: 2)
backgroundView.layer.shadowRadius = 2
backgroundView.layer.shadowOpacity = 0.75
button.addSubview(backgroundView)
}
PlaygroundPage.current.liveView = view
Whilst not exactly the same, please refer to the answer provided here by Rob who answered a similar question:
How do I style a button to have transparent text?
This should get you started at the very least...
Stumbled on a possible solution that I've updated to proper syntax:
func mask(withRect rect: CGRect, inverse: Bool = false) {
let path = UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.append(UIBezierPath(rect: self.view.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.cgPath
self.view.layer.mask = maskLayer
}
You'll obviously need to pick parts out to see if it works for you.

MacOS - How do I programatically position image views next to each other?

Inside the main view of my MacOS app, I am trying to layout a bunch of image views next to each other.
The logic I am using is that the first sub view has its leadingAnchor set as the leadingAnchor of the main view, and every subsequent sub view has its leadingAnchor set as the trailingAnchor of the previous sub view.
let imgWidth :CGFloat = 100, imgHeight :CGFloat = 100
var leadingAnchor = self.view.leadingAnchor
for /*loop logic*/ {
let img: NSImage = funcToGetImage()
var imgView = NSImageView(frame: NSRect(origin: .zero, size: img.size))
imgView.image = img
self.view.addSubview(imgView)
imgView.widthAnchor.constraint(equalToConstant: imgWidth).isActive = true
imgView.heightAnchor.constraint(equalToConstant: imgHeight).isActive = true
imgView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
leadingAnchor = imgView.trailingAnchor
}
However I see only one image, and not a bunch of them positioned next to each other as I expected.
Am new to Swift/Xcode/MacOs development. What am I missing?
Edit:
If I replace the lines
var imgView = NSImageView(frame: NSRect(origin: .zero, size: img.size))
imgView.image = img
with
imgView = NSImageView(image: img)
I don't see anything at all.
Edit2:
Replacing
var imgView = NSImageView(frame: NSRect(origin: .zero, size: img.size))
with
var imgView = NSImageView(frame: NSRect(origin: CGPoint(x: x, y: 0), size: img.size))
x += 100
did the trick.
Based on El Tomato's comment, I replaced
var imgView = NSImageView(frame: NSRect(origin: .zero, size: img.size))
with
var imgView = NSImageView(frame: NSRect(origin: CGPoint(x: x, y: 0), size: img.size))
x += 100
That did the trick.