My goal is to overlay two images (the first a photo from camera roll, the second a PNG of a cartoon ghost).
I've gotten far enough that I'm passing in a camera roll image and a selected ghost image to a view controller. But where I'm stuck is how to layer these images in a useable way.
I can flow in the original photo a couple of ways (either by starting with an image view or by programmatically creating one in a view), and I can add the ghost on top of it (I've mostly been doing this programmatically).
But I can only control the ghost's size and placement manually. I'd like it to come in centered on the original image and match either its height or width, depending on which is smaller as it can be horizontal or vertical.
After an evening of searching, I've come up blank. But surely there's got to be a way to grab the image view's coordinates and make that calculation, right?
Here's what I've got:
import UIKit
class TwoLayerViewController: UIViewController {
#IBOutlet weak var bottomLayerImage: UIImageView!
var originalPhoto: UIImage?
var chosenGhostPhoto: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
bottomLayerImage.image = originalPhoto
bottomLayerImage.contentMode = UIViewContentMode.ScaleAspectFit
var ghostView = UIImageView(frame:CGRectMake(bottomLayerImage.frame.origin.x, bottomLayerImage.frame.origin.y, 100, 100))
ghostView.image = chosenGhostPhoto
ghostView.backgroundColor = UIColor.grayColor()
bottomLayerImage.addSubview(ghostView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Try putting the top image not in an ImageView, but in a sublayer over the other one. Like this:
class YourImageView: UIImageView{
let containerLayer = CALayer()
func drawImageOnTop(img: UIImage){
let piclayer = CALayer()
let sz = originalPhoto?.size ?? CGSize(width: 0, height: 0)
piclayer.frame = CGRect(origin: self.layer.contentsRect.origin, size: sz)
piclayer.position = CGPoint(x: sz.width/2, y: sz.height/2)
piclayer.contentsGravity = .resizeAspect
piclayer.contents = img.cgImage
containerLayer.addSublayer(piclayer)
}
Related
I would like to have a horizontal scroll layout which displays images. It works fine if setup 0, 0, 0 and 0 the constraints of the UIScrollView. The problem is exactly when I change the constraints to make margins surrounded the UIScrollView. This is what happens:
First image in the UIScrollView
Second image in the UIScrollView
Third image in the UIScrollView
As you can see, each time you scroll, more off-center the current page is.
I have tried to subtract trailing and leading constrains constants to the width of the scrollLayout, play with frames and bouds but without success.
If I run this example in a smaller display like iphone 5S, the problem is more pointed.
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var pageController: UIPageControl!
#IBOutlet weak var scrollView: UIScrollView!
let imagesArray = ["b_1", "b_2", "b_3", "b_4", "b_5"]
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView.isPagingEnabled = true
self.pageController.numberOfPages = imagesArray.count
self.pageController.pageIndicatorTintColor = UIColor.blue
self.pageController.currentPageIndicatorTintColor = UIColor.gray
for i in 0...imagesArray.count - 1{
let imageView = UIImageView()
imageView.contentMode = .scaleToFill
imageView.image = UIImage(named: self.imagesArray[i])
let xPos = CGFloat(i)*self.view.bounds.size.width
imageView.frame = CGRect(x: xPos, y: 0, width: view.frame.size.width, height: self.scrollView.frame.size.height )
self.scrollView.contentSize.width = view.frame.size.width*CGFloat(i+1)
self.scrollView.addSubview(imageView)
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x/scrollView.frame.width
self.pageController.currentPage = Int(page)
}
}
So, I would like to know how to always obtain the current image centered.
Thank you
EDITED with Rajesh results and view debug:
I would recommend using a UICollectionView in place of a UIScrollView - otherwise you will be building a lot of the basics from scratch. You can use a collection view that centers the images, make sure paging is enabled and you should get the interface you're looking for. Make sure to adopt / conform to the UICollectionViewDelegate & UICollectionViewDelegateFlowLayout protocols with your view controller & set those delegates on your collection view. Hope that helps! Best of luck.
I am trying to add two custom interfaces that are UIViews to a UIScrollView in my mainStoryBoard.
both UIViews have an image inside them, the image's dimensions are equal to the view's dimensions.
This is the code I am using to add these views to my scrollView
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.myScrollView.frame = view.frame
for i in 0..<2{
let uiImage = UIImage(named: "\(i)")!
let view = Bundle.main.loadNibNamed("TestView", owner: self, options: nil)?.first as! UIView
view.setImage(uiImage)
let xpos = self.myScrollView.frame.width * CGFloat(i)
view.frame = CGRect(x: xpos, y: 0, width: self.myScrollView.frame.width, height: self.myScrollView.frame.height)
myScrollView.contentSize.width = self.myScrollView.frame.width * CGFloat((i + 1))
myScrollView.layer.cornerRadius = 20
myScrollView.layer.masksToBounds = true
myScrollView.addSubview(view)
}
}
}
In the TestView.swift, I have
func setImage(_ name:UIImage) -> Void{
testUIImage.image = name
testUIImage.contentMode = .scaleAspectFit
testUIImage.clipsToBounds = true
}
But when I run the app, the first View gets added fine, but when i scroll to the right, I can see that the second View is not in the Scrollview properly and there is a white space between the first and second View, almost like the space is an added view, that is pushing the second View to the right. I have paging enabled in the scrollViewer.
First Image In ScrollView
Second Image In ScrollView
As you can see, the second image is cut off on the leading edge.
This is the blank space between them:
enter image description here
I checked the width of both UIView frames, they are equal. I also checked the content size after the second iteration, it is equal to the size of both frames*2 , as it should be. But for some reason, a white black space is being added. And it only shows up after adding 2 or more subviews.
I have created two UIScrollViews ( One named scrollView and one named scrollLevel4 )
when I move scrollLevel4, I can get scrollView to move at the same speed using :-
func scrollViewDidScroll(_ scrollLevel4: UIScrollView) {
scrollView.contentOffset.x = scrollLevel4.contentOffset.x
}
However If I want to move scrollView at a different pace, not sure what to do, whenever I add anything to the end of line :
scrollView.contentOffset.x = scrollLevel4.contentOffset.x
it crashes, even a simple + 10, same pace, staggered offset, still crashes
also tried .scrollRectToVisible() method
Thoughts ?
Without seeing the error or your code it's hard to say for sure, but most likely you are setting the same delegate for both scrollViews. When you drag scrollLevel4, it triggers a scroll on scrollView, so you get an infinite loop and eventually a crash.
If you want to use the same delegate on both scrollViews, you'll need to check which one was passed before operating on them. Here's a basic working implementation. Open a new single view project and replace the code in ViewController.swift with:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
var imageView1: UIImageView!
var imageView2: UIImageView!
var scrollView1: UIScrollView!
var scrollView2: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
imageView1 = UIImageView(image: UIImage(named: "image.jpg"))
imageView2 = UIImageView(image: UIImage(named: "image.jpg"))
scrollView1 = UIScrollView(frame: CGRect(origin: CGPoint.zero, size: CGSize(width: 200, height: 200)))
scrollView1.contentSize = imageView1.bounds.size
scrollView1.addSubview(imageView1)
view.addSubview(scrollView1)
scrollView2 = UIScrollView(frame: CGRect(origin: CGPoint(x: 0, y: 210), size: CGSize(width: 200, height: 200)))
scrollView2.contentSize = imageView2.bounds.size
scrollView2.addSubview(imageView2)
view.addSubview(scrollView2)
scrollView2.delegate = self
scrollView1.delegate = self
}
func scrollViewDidScroll(_ scrolled: UIScrollView) {
// both scrollViews call this when scrolled, so determine which was scrolled before adjusting
if scrolled === scrollView1 {
scrollView2.contentOffset.x = scrolled.contentOffset.x + 100
} else if scrolled === scrollView2 {
scrollView1.contentOffset.x = scrolled.contentOffset.x - 100
}
}
}
Note that whatever modification you apply to the offset of one, you have to apply the exact inverse (or nothing at all) to the other. Otherwise you'll have an infinite loop of back and forth scrolling ending in a crash.
I'm trying to make a circular image in Swift, I've searched around and watched a couple YouTube videos. The solutions proposed are extremely easy, but when I used them I get an image formed as an eye instead of a circle, below is my view controller and a picture of the UI
var experimentIdentifier: String = ""
#IBOutlet weak var foregroundImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
foregroundImage.layer.cornerRadius = (foregroundImage.frame.size.width) / 2
foregroundImage.layer.masksToBounds = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
It's because your image is not a square.
See this problem in action:
Set the image to a width : height = 2 : 1 rectangle in storyboard
then run, the image will look like
but if the image is a square, like this in storyboard
click run, it'll be like
Enjoy coding!
Try This ,
let profileImageView = UIImageView()
profileImageView.frame = CGRectMake(150, 150, 60, 60)
profileImageView.layer.borderWidth = 1
profileImageView.layer.borderColor = UIColor.grayColor().CGColor
profileImageView.backgroundColor = UIColor.yellowColor()
profileImageView.layer.cornerRadius = 60/2
let image = UIImage(named: "yourImageName")
profileImageView.layer.cornerRadius = profileImageView.frame.size.height/2
profileImageView.clipsToBounds = true
Your image is not a square i guess. To make it square you have to make sure that height and width of the image are equals and then also add these two properties as well
foregroundImage.layer.cornerRadius = 0.5 * your image height
foregroundImage.layer.masksToBounds = true
foregroundImage.clipsToBounds = true
I hope this will help
make sure the image is a square then add this code
foregroundImage.layer.cornerRadius = side/2
foregroundImage.layer.masksToBounds = true
I'm a swift newbie. Any help is appreciated.
I have a stack of 10 images. I want the user to be able to swipe up and down to update the the image view to new images.
For example: the Image View starts of by displaying 1.jpg. Then the user gestures down on the Image View and it updates the image to 2.jpg then 3.jpg... etc. depending on how far the gesture is held (kind of like an animation). I am able to update the image by one increment using the following code:
#IBAction func down(sender: UISwipeGestureRecognizer) {
image.image = UIImage(named: "2.jpg")
}
How can I make this a continuous gesture?
The end result should look something like this: https://figure1.com/sections/blog/wp-content/uploads/2014/08/resized.gif
So let's start off first things first.
Based off the idea that this is distance dragged
1) We need a UIScrollView()
2) Set the Scrollview Frame to the frame of the screen
3) Allow use of scrollview delegate, so add UIScrollViewDelegate to the list of subclasses (At the top where it says ClassName: list, of, subclasses, here, separated, by, commas)
4) In your class (If you are in your View Controller class), add the delegate to the scrollview
5) Let's set the contentSize of the scrollView
6) Let's add the images to your view, using a loop
7) Before step 6, make sure that your images are named something with numbers, and the same name, such as Image1 Image2 Image3 so that we can loop through them.
8) Declare a UIImage array
9) I was gonna keep typing steps but here you go :P
class ViewController:UIViewController, UIScrollViewDelegate {
let scrollView = UIScrollView()
let images:[UIImage] = []
let imageView:UIImageView!
override func viewDidLoad() {
//Setting up stuff
for index in 0 ..< 10 {
//It's either %t, %i or %d (I don't recall which is which lol)
images.append(UIImage(named: String(format: "Image %i", index)))
}
imageView = UIImageView(frame: view.bounds)
imageView.contentMode = .ScaleAspectFit
imageView.image = images[0]
imageView.backgroundColor = UIColor.clearColor()
self.view.addSubview(imageView)
scrollView.frame = view.bounds
scrollView.delegate = self
scrollView.backGroundColor = UIColor.clearColor()
//Let's say every time the user drags to 1/10 of the screen, the picture will change
scrollView.contentSize = CGSize(width: self.view.frame.width, height: self.view.frame.height+(self.view.frame*(1/10)*CGFloat(images.count)))
self.view.addSubview(scrollView)
}
//Now let's add some UIScrollView delegates to be called whenever the user scrolls!
func scrollViewDidScroll(scrollView: UIScrollView) {
if(scrollView.contentOffSet.y > self.view.frame.height) {
//(1/10) because we are changing the scrollView every 1/10 of the screen
let pictureCount = scrollView.contentOffset.y/scrollView.frame.height*(1/10)
imageView.image = images[pictureCount]
}
}
}
Don't quote me off this, mainly because I pulled it out of the air, so if it has errors/bugs, I apologize, but feel free to comment and I will try to adjust what is needed.