I currently have an image set into my UIImageView the following way:
art_image.image = UIImage(named:(artworkPin.title!))
where art_image is the image View and artworkPin.title refers to the name of the image. However, I want to add a second image to the UIImageView if it exists I thought of programming it as
art_image.image = UIImage(named:(artworkPin.title + "1")?)
would this work? In this case I would name a second image the name of the first image but with a '1' on the end. Example: 'Photo.jpeg' and 'Photo1.jpeg' would both be in the image view if Photo1.jpeg existed.
Thanks for your help.
I came across a similar task myself once. What I did was, I created a UIScrollView with the frame of the UIImageView and its contentSize would be imageView.frame.size.width * numberOfImages.
let scrollView = UIScrollView(frame: view.bounds)
view.addSubview(scrollView)
scrollView.contentSize = CGSize(width: scrollView.bounds.size.width * CGFloat(numberOfImages), height: scrollView.bounds.size.height))
for i in 0...<numberOfImages.count-1 {
let imageView = UIImageView(frame: CGRect(x: scrollView.bounds.size.width * CGFloat(i), y: scrollView.bounds.origin.y, width: scrollView.bounds.size.width, height: scrollView.bounds.size.height))
imageView.image = UIImage(named: "artwork" + "\(i)")
scrollView.addSubview(imageView)
}
You can animate it to scroll with a Timer if you want.
scrollView.setContentOffset(scrollPoint, animated: true)
you can only show 1 image inside the imageivew at a time, so if you have the lines as follows:
art_image.image = UIImage(named:(artworkPin.title!))
art_image.image = UIImage(named:(artworkPin.title! + "1")?)
art_image would consist only of Photo1 provided such an image exists and that the artworkPin.title unwrapped is also not nil otherwise you could see some different results.
if you do want to add multiple images to an image view for the purpose of animation, you need to use the animationImages property of UIImageView which takes an array of UIImages for example
art_image.animationImages = [UIImage.init(named:"Photo")!,
UIImage.init(named:"Photo1")!]
Hope this helps
EDIT
var imagesListArray = [UIImage]()
for position in 1...5
{
if let image = UIImage.init(named: ("Photo\(position)"))
{
imagesListArray.append(image)
}
}
art_image.animationImages = imagesListArray
art_image.animationDuration = 3.0
art_image.startAnimating()
This would be a safer a way to add the images so it will ONLY add an image if it is not nil and adds Photo1, Photo2 ..... Photo5
With regards to your other questions:
If you want the user to be able to
What do you mean by animation?
I have added two more lines of code, and it gives this result:
art_image.animationDuration = 1.0
art_image.startAnimating()
It will give you something like this:
If you want the user to swipe, then you need to make some changes such as:
using a scrollview, collectionview for example is the easiest or using a gesture recognizer on swipe you need to change the image
EDIT
Have a look at this example. Imagine each button is your annotation so when I tap it, the image changes.
I have 3 images named Photo11.png, Photo21.png and Photo31.png and this is my code inside the button handler
#IBAction func buttonTapped(_ sender: UIButton)
{
if let image = UIImage.init(named: sender.currentTitle!+"1")
{
art_image.image = image
}
}
As you can see I am setting the image with the title of my button + "1" as so it displays either Photo11.png or Photo21.png etc
Related
I have an image slider where multiple images are added to a scrollview. Each is stored in an array of my custom data type (named Slide). I cycle through them like this:
for (index, slide) in slides.enumerated() {
let imageView = UIImageView()
imageView.image = UIImage(named: slide.image) //set the imageView with the imageName in this slide
imageView.contentMode = .scaleAspectFit
let xPos = self.view.frame.width * CGFloat(index) //calculate x depending upon slide index
imageView.frame = CGRect(x: xPos, y: -200, width: self.SVSlider.frame.width, height: self.SVSlider.frame.height)
SVSlider.contentSize.width = SVSlider.frame.width * CGFloat(index + 1) //add slide image to scrollview
SVSlider.addSubview(imageView)
//add tap function to slide
imageView.isUserInteractionEnabled = true
imageView.tag = index
let tapImage = UITapGestureRecognizer(target: self, action: #selector(slideAction(_:)))
imageView.addGestureRecognizer(tapImage)
}
Each slide image is attached to the method "slideAction", below:
#objc func slideAction(_ sender: UITapGestureRecognizer) {
let selName = slides[(sender.view?.tag)!].target
NSObject.perform(Selector(selName))
}
But the application throws an error when I click an image. By debugging I can see that the "tag" is correctly set to the slide index number. I want to perform the target action held in the slide object. (Currently the target is a String of the method name - ending with ':').
How can I get the "slideAction" to goto the method in the slide object?
Try this ,create target method in the custom class callMethodDirectly and call it
#objc func slideAction(_ sender: UITapGestureRecognizer) {
let selName = slides[(sender.view?.tag)!]
selName.callMethodDirectly()
}
class slide:NSObjcet
{
func callMethodDirectly()
{
// implement target code here
}
}
I am using UIImageWriteToSavedPhotosAlbum() to save images to the photo album of the device.
I have my images in an array and they are displayed on a PageControl.
A download icon on the navigationBar saves the image to Photos.
I am able to save the image to Photos but the image saved is incorrect i.e. the image at the particular index is not saved. This is how I am adding all images to the page-control....
func scrollImagesWhileViewChange() {
for i in arrayOfURLImages {
self.pageControl.size(forNumberOfPages: arrayOfURLImages.count)
let scrollViewWidth:CGFloat = self.scrollView.frame.width
let scrollViewHeight:CGFloat = self.scrollView.frame.height
let index = arrayOfURLImages.index(of: i)
let imageA = UIImageView(frame: CGRect(x: CGFloat(index!) * scrollViewWidth, y:0,width:scrollViewWidth, height:scrollViewHeight))
imageA.image = i
self.scrollView.addSubview(imageA)
self.imageToDownload = imageA
self.scrollView.contentSize = CGSize(width:self.scrollView.frame.width * CGFloat(arrayOfURLImages.count), height:self.scrollView.frame.height)
self.scrollView.delegate = self
self.pageControl.numberOfPages = arrayOfURLImages.count
self.pageControl.currentPage = 0
}
}
In the section self.imageToDownload = imageA , I am assigning the image to a UIImageView variable. And this is how I am saving to 'Photos'..
UIImageWriteToSavedPhotosAlbum(self.imageToDownload.image!, self, #selector(MyViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)
Here the first parameter should get the correct index. But I am not able to figure out how...
When you click download button you need to figure out the current index of page control and then on basis of current index fetch right image from arrayOfURLImages and then save to photo album.
Try this-
UIImageWriteToSavedPhotosAlbum(arrayOfURLImages[self.pageControl.currentPage], self, #selector(MyViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)
I am making an iMessage app with images for a keyboard app like custom emojis. I have setup outlets on my iMessage story board and connected the button. In my MessageViewController I have the code below in my IBOulet. I want to resize the image smaller but I can't seem to figure this one out. Any help is greatly appreciated!
#IBAction func button(_ sender: Any) {
label.text = "button pressed"
let layout = MSMessageTemplateLayout()
layout.image = UIImage(named: "270a.png")
let message = MSMessage()
message.layout = layout
activeConversation?.insert(message, completionHandler: nil)
}
When you add an image to message template you can request a width and height, but it will scale the image up or down (respecting the aspect ratio) to a size that it thinks is best.
If the image resource you have isn't the size you want, you can attempt to create a new image in memory, but MSMessageTemplateLayout will modify this as it sees fit.
let original = UIImage(named: "background")
// use CGContext to create new image in memory
// 10 x 10 is super small, so messages app will scale this up
let image = CGSize(width: 10, height: 10).image { context, frame in
original?.draw(in: frame, blendMode: .luminosity, alpha: 1)
}
let message = MSMessage()
let layout = MSMessageTemplateLayout()
layout.image = image
message.layout = layout
self.activeConversation?.insert(message, completionHandler: nil)
I like to use this extension to make it a little easier working with CGContext:
https://gist.github.com/mathewsanders/94ed8212587d72684291483905132790
I have this asset as the background of a view and its assigned to the background using the code described below.
The animation is to get the diagonal rows animate, so they move from left to right when the loading is happening.
Any pointers of how to get this done?
var view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.image = UIImage(assetIdentifier: "background-view")
view.layer.cornerRadius = 8.0
view.layer.masksToBounds = true
view.contentMode = .ScaleAspectFill
view.clipsToBounds = true
view.backgroundColor = UIColor.whiteColor()
return view
"background-view" is here
I guess the best would be to have all the images needed ( all the frames ) to create the animated image you want and then put these images in UIImageView's animationImages property.
For instance, if you get a loading bar gif loading_bar.gif, you can get all the different images in that gif ( c.f. this tutorial among others : http://www.macobserver.com/tmo/article/preview-extracting-frames-from-animated-gifs ).
Load all the images in your code ( in the assets folder for instance ) and then do something like :
func getAnimatedImages -> Array<UIImage>
{
var animatedImages = Array<UIImage>()
var allImagesLoaded = false
var i = 0
while !allImagesLoaded
{
if let image = UIImage(named: "background_" + String(i))
{
animatedImages.append(image)
i++
}
else
{
allImagesLoaded = true
}
}
return animatedImages
}
( if you called your images background_0, background_1, etc... )
and then
self.yourBackgroundImageView.animationImages = self.getAnimatedImages
self.yourBackgroundImageView.startAnimating()
I would use the method class func animatedImageNamed(_ name: String, duration duration: NSTimeInterval) -> UIImage?
From the Apple doc:
this method would attempt to load images from files with the names ‘image0’, ‘image1’ and so on all the way up to ‘image1024’. All images included in the animated image should share the same size and scale.
If you create an animated image you can assign it to your UIImageView and it will animate automatically.
As for the image creation #Randy had a pretty good idea :)
I'm trying to have the ability to remove the subview the user chooses with three taps.
The problem I'm having is I can only get it to remove in the order the subviews were created. I have played around with 'viewWithTag' but can't figure out how to get it to do what I want.
Can I achieve what I want with the 'tapGesture' removing the subview from the location I tapped?
I'm a noob (as the kids say), so any help is much appreciated!
Thanks!
#IBAction func unwindToParent(segue:UIStoryboardSegue){
var source = segue.sourceViewController as PropViewController
var propImage = UIImage(named: name as String!)
clipView = UIImageView(image: propImage!)
clipView.frame = CGRectMake(0, 0, 200.0, 200.0)
clipView.center = CGPoint (x: view.bounds.size.width/2, y: view.bounds.size.height/2)
clipView.contentMode = UIViewContentMode.ScaleAspectFit
clipView.userInteractionEnabled = true
clipView.multipleTouchEnabled = true
clipView.layer.cornerRadius = 10.0
setTag = tagCounter
tagCounter++
clipView.tag = setTag
addPinchGestureRecognizer(clipView)
addPanGestureRecognizer(clipView)
addRotationGestureRecognizer(clipView)
addTapGestureRecognizer(clipView)
view.addSubview(clipView)
view.bringSubviewToFront(clipView)
let recognizer = UITapGestureRecognizer(target: self, action:Selector("Trash:"))
recognizer.numberOfTapsRequired = 3
recognizer.delegate = self
clipView.addGestureRecognizer(recognizer)
}
func Trash(gesture: UITapGestureRecognizer){
clipView.viewWithTag(setTag)?.removeFromSuperview()
}
The gesture recogniser has a view property - that will be the tapped view.
Never use tags for anything.
Theres probably a half dozen ways I can see this being done.
The 'simplest' is probably getting the location of the tap
tap.locationInSubview
And then checking if any of the views contain that point
uiViewObject.containtsPoint()
If it contains the point remove it
Or you could add gestures to each view and, as suggested by jrturton, uses the taps view source as the view to remove.