I have a very very simple project set up that allows you to click a "browse photo" button. The user then selects a photo from their photo gallery, and it's displayed on a programmatically created UIImageView.
Works like a charm. However - I am missing key functionality that is required.
I need the user to be able to scale the image (via pinching and dragging) after it is displayed within the UIImageView. allowsEditing = true, lets the user crop before. I need similar functionality, however, allowing them to edit once it's on the main UI.
Help is appreciated. Please and thank you!!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var imageViewLayer: CALayer{
return imageView.layer
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
imageViewLayer.contents = UIImage(named: "ss3.jpg")?.CGImage
imageViewLayer.contentsGravity = kCAGravityResizeAspect
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func newGesture(sender: AnyObject) {
imageViewLayer.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
}
I did something similar a while back. I added the image to UIImageView's layer property, added gesture recognizer to the view and implemented the gesture call backs modifying the layer property and not the view. Adding the image to the UIImageView's layer did the trick. As a side note, I would like to add that every UIView is supported by CALayer class. It has a lot of methods and properties which help to dynamically change the view, which in your case will be done by gestures.
As an alternative, you can also use CALayer's hitTest method instead of implementing the call backs for gesture recognizers.
EDIT- Sample Code
You could do some thing like this:
#IBOutlet weak var imageView: UIImageView!
var imageViewLayer: CALayer{
return imageView.layer
}
In the viewDidLoad, set up the image
imageViewLayer.contents = UIImage(named: "CoreDataDemoApp")?.CGImage
imageViewLayer.contentsGravity = kCAGravityResizeAspect
Add pinch gesture to the imageview in storyboard (or programmatically) and in it's call back you could do something like this:
#IBAction func pinchGestureRecognized(sender: AnyObject) {
imageViewLayer.transform = CATransform3DMakeScale(sender.scale, sender.scale, 1)
}
Again this is just to give you an idea of how it could work and it is not the complete code. Hope this helps!
This is another way of doing it:
Stackoverflow link to related question
Related
I am trying to display a new image based on a user tapping the image view. I have added a UITapGestureRecognizer on top of the UIImageView which has been defined a "displayPhoto" and connected it as an outlet to the view controller.
#IBOutlet weak var displayPhoto: UIImageView!
#IBAction func changeImage(_ sender: UITapGestureRecognizer) {
displayPhoto.image = UIImage(named: "myimage")
}
The sent action is listed as follows:
sent actions
When I run the app and click on the image, nothing happens. I've even tried to make the first line of the IBAction function a fatal error but nothing happens. What am I missing?
Thanks in advance for any help.
The full view and connection
Tap Gesture Recognizer Window
Firstly you try; clean your project
command+option+shift+K
The first case cannot be empty
You should add a picture.
override func viewDidLoad() {
super.viewDidLoad()
displayPhoto.image = UIImage(named: "firsCase")
}
i have dragged a container view from storyboard and set it black in background colour. but it didn't change the background colour.
class ViewController: UIViewController {
#IBOutlet weak var container: UIView!
override func viewDidLoad() {
super.viewDidLoad()
container.layer.backgroundColor = UIColor.blackColor().CGColor
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
How did you set the background color?
A container view is actually just a normal view, that is linked to a viewController. This means you can set the background the same way as you would for any other NSView or UIView. This is all the code I needed to add to my NSViewController class (not the ViewController inside the container, just the ViewController for the window).
#IBOutlet weak var containerView: NSView!
override func viewDidLoad() {
//other code in your viewDidLoad
containerView.wantsLayer = true
}
override func awakeFromNib() {
super.awakeFromNib()
containerView.layer?.backgroundColor = NSColor.black.cgColor
}
make sure to connect the IBOutlet if you have not already.
If you set the layers background color in viewDidLoad, the layer may not exist yet, (I don't know why). Accessing the layer in awakeFromNib has always worked for me, while accessing it in the viewDidLoad can be unreliable.
If you are working on IOS, most of this is not applicable, and this should be all you need
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
containerView.layer?.backgroundColor = UIColor.black.cgColor
}
I work less on IOS, so I have not ran into any issues with that, but that could be from lack of attempts. On OSX setting the background color in viewDidLoad will work about 50% of the time so there might still be an issue that I have not ran into.
If neither works, try unwrapping the layer rather than leaving it an optional (replacing the ? with a !) this will at least crash your program and probably tell you that layer is nil, if this is the case you should be figuring out why the layer is nil.
Also if the ViewController connected to the container view is a custom class, you don't have to bother with the IBOutlets, just call the view "view" in that custom class.
Sorry this got a bit long, but hope this helped
I am trying to create a custom shape NSButton. In particular I am trying to make a round button, using a custom image. I've found a tutorial on the creation of custom UIButton and tried to adapt it to NSButton. But there's a huge problem. clipsToBounds seems to be iOS only(
Here's my code:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var mainButton: NSButton!
var size = 32
override func viewDidLoad() {
super.viewDidLoad()
configureButton()
// Do any additional setup after loading the view.
}
func configureButton()
{
mainButton.wantsLayer = true
mainButton.layerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay
mainButton.layer?.cornerRadius = 0.5 * mainButton.bounds.size.width
mainButton.layer?.borderColor = NSColor(red:0.0/255.0, green:122.0/255.0, blue:255.0/255.0, alpha:1).CGColor as CGColorRef
mainButton.layer?.borderWidth = 2.0
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
}
What am I doing wrong? How can I make a circular NSButton? Can you suggest anything on replacing clipsToBounds?
Because here is what I was able to get so far:
NSButton is a subclass of NSView, so all methods in NSView, such as drawRect(_:), are also available in NSButton.
So create a new Button.swift which you draw your custom layout
import Cocoa
class Button: NSButton {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
// Drawing code here.
let path = NSBezierPath(ovalIn: dirtyRect)
NSColor.green.setFill()
path.fill()
}
}
Great Tutorial Here. It is iOS , but quite similar!
Don't play around with corner radius. A circle doesn't have corners. To make the button appear as a circle, mask the button's layer to a circle.
You are setting the radius based upon the width of the button. By the look of your screenshot, the button is not a square when you start, so rounding the corners cannot create a circle.
So I have been trying to do this for a a while, that I need to to do is be able to change the image view that a container view embeds. Is this possible?
I wasn't sure if it was, so I thought that maybe I could just make an embedded view for all of the different views and have them all on top of each other - then just bring the one that the user has chosen to the view to the top.
I'm pretty sure the second way would work, but it would probably slow down the app and isn't very tidy.
I would prefer to use the first way and just be able to choose which view controller the view controller embeds.
I know that stack overflow likes to see that the OP has made an attempt at solving the problem, but I am asking more here if it is possible to do the first way - if it is, how would I go about doing it. If it isn't would my second option be feasible?
Thanks
One way is as shown below.
import UIKit
class ViewController: UIViewController {
var imgNumber = 0
var images = ["image0","image1","image2"]
#IBAction func btn(sender: UIButton) {
imgNumber += 1
if (imgNumber > 2) {
imgNumber = 0
}
imageToBeDisplayed.image = UIImage(named: images[imgNumber])
}
#IBOutlet weak var imageToBeDisplayed: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageToBeDisplayed.image = UIImage(named: images[0])
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
So I created a scroll view and put an image view in it. I initialized the scroll view as a variable and wrote the following code in my ViewController and yet, the image won't scroll.
What's wrong?
Later on I'm also going to need to put several buttons into this scroll view so if I'm missing something here, it'd be great if you could address it for buttons as well.
My code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
ScrollView.scrollEnabled = true
}
#IBOutlet weak var ScrollView: UIScrollView!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Try explicitly setting the content size like so:
self.scrollView.contentSize = CGSize(width:somethingBigger, height: somethingBigger);
To answer your follow-up question...Make height of the scrollView equal to that of the screen. Then it won't scroll vertically. Programmatic stuff overwrites storyboard stuff.