I have created and initialized a scrollview that pulls from an array of images. So a user swipes past a photo, then another, and I need to delete the image based on the location of the current image I have created a for loop that deletes the image i-- in the array, but this crashes because I can't delete the i. Is there a way I can accomplish this? Thank you: here is my code
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
func scrollViewDidScroll(_ scrollView: UIScrollView) {
for i in 0..<imageArray.count {
if i >= 3 {
imageArray.remove(at: i - 2)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
Rather than using a UIScrollView, I would recommend using a UITableView or UICollectionView. It is very easy to manage the data model and then call table.reloadData().
You would track the scroll position with the ScrollViewDelegate method scrollViewDidScroll(_ scrollView) and force a reload once you've scrolled far enough.
Related
I'm new in Swift but I have some basic experience.
I have successfully created an animation with three images and they repeat themselves. But I would like the effect of this repetition to be like when you in attributes inspector of UIScrollView check paging enable.
Inside of options: UIView.AnimationOptions I tried different Constants but I can not find that suits me.
My question: Can I animate image array like you swipe images in scroll view with paging enable?
class ViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "forest")!, UIImage(named: "slika1")!, UIImage(named: "slika2")!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.miniView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
startAnimating()
}
func startAnimating() {
var newOffset = mainScrollView.contentOffset
newOffset.x = 0.0
newOffset.x += mainScrollView.frame.width * CGFloat(imageArray.count - 1)
UIView.animate(withDuration: Double(imageArray.count), delay: 5, options: [.repeat, .allowUserInteraction], animations: {
self.mainScrollView.contentOffset = newOffset
})
}
}
Ok, if i correctly understand what you want, this is the correct answer.
Animate page by page, with a 5 seconds delay with one animation and another.
You need to use Timer.scheduledTimer to trigger method that scroll to the next page. With that solution, you can check paging enable ON, so the user can change the page itself.
I hope it helps
class ViewController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
var currentPage = 0
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "forest")!, UIImage(named: "slika1")!, UIImage(named: "slika2")!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.miniView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(startAnimating), userInfo: nil, repeats: true)
}
#objc func startAnimating() {
//that line check if the current page is the last one, and set it to the first, otherwise, it increment the currentPage
self.currentPage = (self.currentPage == imageArray.count-1) ? 0 : self.currentPage+1
var newOffset = mainScrollView.contentOffset
newOffset.x = mainScrollView.frame.width * CGFloat(self.currentPage)
self.mainScrollView.setContentOffset(newOffset, animated: true)
}
}
I want to create an image gallery similar to this:
http://sweettutos.com/2015/04/13/how-to-make-a-horizontal-paging-uiscrollview-with-auto-layout-in-storyboards-swift/
Where each time the user swipes and the image changes and the label title changes.I have written the code and included the if statement, however, it does not work properly and it only changes as one value.
Here is my code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mainscrollview: UIScrollView!
var imageArray = [UIImage]()
#IBOutlet var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
mainscrollview.frame = view.frame
imageArray = [#imageLiteral(resourceName: "goku"), #imageLiteral(resourceName: "boruto"), #imageLiteral(resourceName: "tail"), #imageLiteral(resourceName: "sage"),#imageLiteral(resourceName: "tobi")]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainscrollview.frame.width,height: self.mainscrollview.frame.height)
mainscrollview.contentSize.width = mainscrollview.frame.width * CGFloat(i + 1)
mainscrollview.addSubview(imageView)
let gokuImage = UIImage(named: "goku")
let borutoImage = UIImage(named: "boruto")
if imageView.image == gokuImage{
label.text = "Goku"
}
if imageView.image == borutoImage{
label.text = "bor"
}
}
}
}
This is where the project is going wrong:
let gokuImage = UIImage(named: "Goku")
let borutoImage = UIImage(named: "boruto")
if imageView.image == gokuImage{
label.text = "Goku"
}
if imageView.image == borutoImage{
label.text = "bor"
}
I think this is because the if statement can not directly access the current image that is being displayed in the UIScroll view.
Here is the link to my project: http://www.mediafire.com/file/adkzcpvdtodlyl5/gallery_copy.zip
To achieve what you want to do, here is one of the option available which is fairly simple:
Your label is in your ScrollView, so it will scroll with your first image. You need to move it above your ScrollView, at the same hierarchy level as the ScrollView.
In order to change your label's text when you scroll, you can detect when your page has stopped decelerating. To do so:
(a) Add UIScrollViewDelegate to class ViewController: UIViewController,
(b) in viewDidLoad(), add 'mainscrollview.delegate = self',
(c) write the 'scrollViewDidEndDecelerating' method.
In the end, your code should look like this:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var mainscrollview: UIScrollView!
#IBOutlet var label: UILabel!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [#imageLiteral(resourceName: "goku"), #imageLiteral(resourceName: "boruto"), #imageLiteral(resourceName: "tail"), #imageLiteral(resourceName: "sage"),#imageLiteral(resourceName: "tobi")]
mainscrollview.frame = view.frame
mainscrollview.delegate = self
label.text = "Initial label value is Boruto"
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainscrollview.frame.width,height: self.mainscrollview.frame.height)
mainscrollview.contentSize.width = mainscrollview.frame.width * CGFloat(i + 1)
mainscrollview.addSubview(imageView)
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView){
// Test the offset and calculate the current page after scrolling ends
let pageWidth:CGFloat = mainscrollview.frame.width
let currentPage:CGFloat = floor((mainscrollview.contentOffset.x-pageWidth/2)/pageWidth)+1
// Change the text accordingly
if Int(currentPage) == 0{
label.text = "Boruto"
}else if Int(currentPage) == 1{
label.text = "Goku"
}else if Int(currentPage) == 2{
label.text = "Sage"
}else if Int(currentPage) == 3{
label.text = "Tail"
}else if Int(currentPage) == 4{
label.text = "Tobi"
}else{
label.text = "Other character"
}
}
}
The first thing you should do is remove the label from the scroll view and add it into the main view i.e the scrollview and the label should have sibling relationship rather than parent-child relationship.
Modify your ViewController accordingly
class ViewController: UIViewController, UIScrollViewDelegate {
// your other code
override func viewDidLoad() {
super.viewDidLoad()
mainscrollview.delegate = self
// your other code
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let imageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
switch imageNumber {
case 0:
label.text = "Goku"
case 1:
label.text = "Bor"
case 2:
label.text = "Tail"
case 3:
label.text = "Sage"
case 4:
label.text = "Tobi"
default:
label.text = "Unknown"
}
}
}
You use the UILabel from storyboards and UIImageView from the code. You add all the images to the scrollView, so that everyone follows one another, but you use your label only with the first image.
In other words, you need to add UILabel to the code and add it to each image. Instead of a lot of "if-cycle", I suggest you use an array of labels, just as you use the image.
var labelArray = [String]()
// in viewDidLoad add your label names
labelArray = ["goku", "boruto", "next word", "next word", "next word"]
// create UILabel
let yourLabel = UILabel(frame: CGRect(x: xPosition, y: self.mainscrollview.frame.height - 100, width: self.mainscrollview.frame.width, height: 40))
// add each labelName to each image
yourLabel.text = labelArray[i]
// add image and label to scrollView
mainscrollview.addSubview(imageView)
mainscrollview.addSubview(yourLabel)
How i can zoom array of images? Now i can zoom image as a .gif
My code:
class ScrollImageViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollImage: UIScrollView!
private var imageView: UIImageView!
var imagesArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.scrollImage.minimumZoomScale = 1.0
self.scrollImage.maximumZoomScale = 5.0
for i in 0..<imagesArray.count {
imageView = UIImageView()
imageView.sd_setImage(with: URL(string: imagesArray[i]))
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.scrollImage.frame.width, height: self.scrollImage.frame.height)
scrollImage.contentSize.width = scrollImage.frame.width * CGFloat(i + 1)
scrollImage.addSubview(imageView)
}
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}
I tried lesson from raywenderlich, but they did not help me :(
I want to get result like a AirBnB or example:
Scrolling once and zoom in, zoom out, scrolling twice - zoom in, zoom out and so on
You can check below framework
https://github.com/zvonicek/ImageSlideshow
It has a FullScreenSlideshowViewControllerclass which can be used for your purpose, also it can be customised.
I have made a scrollview, and made an array of images (which I will later add an option for the user to post images into that array and friends images will fill into that array) and want to have the user be able to see a photo and it tracks it.
I have created a for loop that added photos into the array, but when I created an if statement to take out an item in the array, I got an error because I would remove the image[i] from the array and I kinda know why this is happening, but want to fix it. So basically I need to take out an image in the array. Please help me out I'm still learning.
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
for i in 0..<imageArray.count {
if (i >= 2) {
imageArray.remove(at: (i - 2))
}
}
// 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.
}
}
Thank you fellow better programmers.
You can't remove an element from a array while traversing it so you had to use a temp array
class ViewController: UIViewController {
var imageArray = [UIImage]()
#IBOutlet weak var mainScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = view.frame
imageArray = [#imageLiteral(resourceName: "dubai6"), #imageLiteral(resourceName: "dubai2"), #imageLiteral(resourceName: "dubai7"), #imageLiteral(resourceName: "dubai4"), #imageLiteral(resourceName: "dubai3"), #imageLiteral(resourceName: "dubai5"), #imageLiteral(resourceName: "DigitalDrawingPreview"), #imageLiteral(resourceName: "denarus"), #imageLiteral(resourceName: "dubai1")]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFit
imageView.image = imageArray[i]
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.view.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
let tempArr = imageArray
for i in 0..<tempArr.count {
if (i >= 2) { // Breakpoint here
imageArray.remove(at: (i - 2))
}
}
// 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.
}
}
use step over to go through each line of for loop until it crashes and then print the value of i at that time by hovering cursor over it or type command at console po i and enter
I am trying to make an infinite loop image gallery app. I did it by setting up a UIScrollView inside which I inserted UIImageViews.
I am able to load 4 images and swipe between them, but the problem I have is how to implement the infinite scroll, so that after the last image, the first one appears and opposite.
As I am newbie in Swift, I don't know how to handle this problem nor where to start. I will appreciate any suggestion, example or link on how to solve this problem.
Thanks in advance!
Here is the peace of my code:
class FirstViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
let scrollViewWidth: CGFloat = self.scrollView.frame.width
let scrollViewHeight: CGFloat = self.scrollView.frame.height
let numPics: Int = 3
let imgOne = UIImageView()
let imgTwo = UIImageView()
let imgThree = UIImageView()
let imgFour = UIImageView()
var arrPics = [imgOne, imgTwo, imgThree, imgFour]
var arrSlide = ["slide1.png", "slide2.png", "slide3.png", "slide4.png"]
for i in 0...numPics {
arrPics[i] = UIImageView(frame: CGRectMake(0,scrollViewHeight * CGFloat(i),scrollViewWidth, scrollViewHeight))
arrPics[i].image = UIImage(named: arrSlide[i])
self.scrollView.addSubview(arrPics[i])
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.width, self.scrollView.frame.height*4)
}
Don't use a scroll view but either a table view or a collection view.
The delegates of both classes want a cell count from you. Then give the delegates an insane number of cells, a number so high that it is totally unlikely that any human being will ever scroll to reach the end. Something like 9999999 cells. This is no problem for such classes because in the background implementation they do not create really this high number of cells but only maximal the number of cells which could be visible at the same time on the screen. The cells in fact are reused. So when cells are falling out at the bottom those cells are going to be reused at the top and vice versa. As a last point is: set the starting point in the middle of such a high number, something like 5555555. I think that is the easiest solution if you are not going to implement a full image recycling algorithm like they did.
#IBOutlet weak var scrollView: UIScrollView!
var scrollViewHeight: CGFloat!
let numPics: Int = 4
override func viewDidLoad()
{
super.viewDidLoad()
scrollView.delegate = self
self.scrollView.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
let scrollViewWidth: CGFloat = self.scrollView.frame.width
scrollViewHeight = self.scrollView.frame.height
let imgOne = UIImageView()
let imgTwo = UIImageView()
let imgThree = UIImageView()
let imgFour = UIImageView()
let imgFive = UIImageView()
var arrPics = [imgOne, imgTwo, imgThree, imgFour,imgFive]
var arrSlide = ["slide1.jpeg", "slide1.jpeg", "slide1.jpeg", "slide1.jpeg","slide1.jpeg"]
for i in 0...numPics {
arrPics[i] = UIImageView(frame: CGRectMake(0,scrollViewHeight * CGFloat(i),scrollViewWidth, scrollViewHeight))
arrPics[i].image = UIImage(named: arrSlide[i])
self.scrollView.addSubview(arrPics[i])
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.width, self.scrollView.frame.height * CGFloat(numPics+1))
}
func scrollViewDidScroll(scrollView: UIScrollView)
{
scrollViewHeight = self.scrollView.frame.height
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.width, self.scrollView.frame.height * scrollViewHeight )
}
Using Timer you can use infinite scrolling like below
func showview() {
if(videosimageslider.isEmpty) {
// print("Empty Array")
} else {
// print("Not Empty ")
// print(videosimageslider.count)
for var index=0; index<videosimageslider.count; index++ {
if let url = NSURL(string: videosimageslider[index]) {
if let data = NSData(contentsOfURL: url){
if let imageUrl = UIImage(data: data) {
let myimageview:UIImageView = UIImageView()
// myimageview.image = imageUrl
let block: SDWebImageCompletionBlock! = {(image: UIImage!, error: NSError!, cacheType: SDImageCacheType, imageUrl: NSURL!) -> Void in
//println(self)
}
// let url = NSURL(string: "http://yikaobang-test.u.qiniudn.com/FnZTPYbldNXZi7cQ5EJHmKkRDTkj")
myimageview.sd_setImageWithURL(url, completed: block)
myimageview.frame.size.width = imagewidth
myimageview.frame.size.height = imageheight
myimageview.contentMode = UIViewContentMode.ScaleToFill
myimageview.frame.origin.x = xscrollpos
myimageview.frame.origin.y = 5
scrollview!.addSubview(myimageview)
xscrollpos += imagewidth
scrollviewcontentSize += imagewidth
scrollview.contentSize = CGSize(width: scrollviewcontentSize, height: imageheight)
}
}
}
}
scrollingTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "newStartScrolling", userInfo: nil, repeats: true)
scrollingTimer.fire()
}
}
// call the timer function //
func newStartScrolling() {
var currentOffset = scrollview.contentOffset
currentOffset = CGPointMake(currentOffset.x+3, currentOffset.y )
if(currentOffset.x < scrollview.contentSize.width - 500) {
scrollview.setContentOffset(currentOffset, animated: false)
currentOffset = CGPointMake(0, currentOffset.y )
//scrollview.contentSize = CGSize(width: 0, height: 0);
} else {
scrollingTimer.invalidate()
showview()
}
}
This is what will solve your problem, just adjust the controller to go in vertical slide view and load the resources at your will.
Link