Swift(iOS) problem: how can I insert UIImage array to subview? I wanted to make a horizontal scroll view in view controller with very little experience with swift. Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
configurePageControl()
var pictures:[UIImage] = [ ]
pictures.append(UIImage(named: "SOVERMENT1.jpg")!)
pictures.append(UIImage(named: "SOVERMENT2.jpg")!)
pictures.append(UIImage(named: "SOVERMENT3.jpg")!)
pictures.append(UIImage(named: "SOVERMENT4.jpg")!)
scrollView.delegate = self
self.view.addSubview(scrollView)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.pagingEnabled = true
var subView = UIView(frame: frame)
**subView.backgroundColor = [UIColor colorWithPatternImage : ]**
self.scrollView.addSubview(subView)
}
This is first problem. How can I insert pictures into subview.backgroundColor? I searched it for 1~2hours, but I couldn't find any answer.
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 4, self.scrollView.frame.size.height)
pageControl.addTarget(self, action: Selector("changePage:"), forControlEvents: UIControlEvents.ValueChanged)
}
func configurePageControl() {
** self.pageControl.numberOfPages = pictures.count **
self.pageControl.currentPage = 0
And here. Why array pictures cannot be counted?
Unless these are repeatable pattern images, I think you want to use a UIImageView. I also don't think you need to use a UIPageControl, because you're only using one UIViewController. You can say something like:
override func viewDidLoad() {
super.viewDidLoad()
var pictures:[UIImage] = [ ]
pictures.append(UIImage(named: "SOVERMENT1.jpg")!)
pictures.append(UIImage(named: "SOVERMENT2.jpg")!)
pictures.append(UIImage(named: "SOVERMENT3.jpg")!)
pictures.append(UIImage(named: "SOVERMENT4.jpg")!)
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(pictures.count), scrollView.frame.size.height)
for index in 0..<pictures.count {
var frame = CGRectZero
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
scrollView.pagingEnabled = true
var subView = UIImageView(frame: frame)
subView.image = pictures[index]
subView.contentMode = .ScaleAspectFit
self.scrollView.addSubview(subView)
}
}
You better use UICollectionView for such purposes
For setting the backgroundColor call the UIColor initializer:
for picture in pictures {
subView.backgroundColor = UIColor(patternImage: picture)
}
Related
I'm having a relatively simple UIViewController with a UIScrollView that's taking relatively half the screen and a UIImageView placed inside the UIScrollView that's the exact same size as the UIScrollView.
On top of the UIImageView there's a UIPageControl. The point is have a horizontal scrolling and present an image like a slider based on the amount of images in an array. The problem is that the scroll view is not scrolling and I don't know why.
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var pageControl: UIPageControl!
let imagelist = ["3.jpg", "1.jpg", "2.png", "4.png", "5.png"]
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
configurePageControl()
for i in stride(from: 0, to: imagelist.count, by: 1) {
var frame = CGRect.zero
frame.origin.x = self.scrollView.frame.size.width * CGFloat(i)
frame.origin.y = 0
frame.size = self.scrollView.frame.size
scrollView.isPagingEnabled = true
scrollView.isScrollEnabled = true
let myImage:UIImage = UIImage(named: imagelist[i])!
let bgColorFromImage = myImage.averageColor
imageView.image = myImage
imageView.contentMode = UIViewContentMode.scaleAspectFit
imageView.frame = frame
scrollView.backgroundColor = bgColorFromImage
scrollView.addSubview(imageView)
}
self.scrollView.contentSize = CGSize(width: self.scrollView.frame.size.width * CGFloat(imagelist.count), height: self.scrollView.frame.size.height)
pageControl.addTarget(self, action: #selector(changePage), for: UIControlEvents.valueChanged)
}
func configurePageControl() {
self.pageControl.numberOfPages = imagelist.count
self.pageControl.currentPage = 0
self.pageControl.tintColor = UIColor.red
self.pageControl.pageIndicatorTintColor = UIColor.black
self.pageControl.currentPageIndicatorTintColor = UIColor.green
self.imageView.addSubview(pageControl)
}
#objc func changePage() {
let x = CGFloat(pageControl.currentPage) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x: x,y :0), animated: true)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
}
This is what the UIStoryboard looks like:
Inside the for loop you use the same object of imageView , you only set the frame and the image
imageView.frame = frame
imageView.image = myImage
but you have to create a new instance of the UIImageView
//
Suppose you have a scrollView in IB with top , leading and trailing constraints to the superView , and a height of say 200 , you can add imageViews dynamically like this
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
for i in 0..<10 {
let f = CGRect(x: CGFloat(i) * scrollView.frame.width, y: 0, width: scrollView.frame.width, height: scrollView.frame.height)
let imgV = UIImageView(frame: f)
imgV.image = UIImage(named: "re-fuel.png")
scrollView.addSubview(imgV)
}
scrollView.contentSize = CGSize(width: CGFloat(10) * scrollView.frame.width, height: scrollView.frame.height)
}
}
Result
The problem is that the scroll view itself is positioned with autolayout. Once you do that, you cannot set the contentSize to make the scroll view scrollable. You must use internal constraints to configure the content size.
I am trying to make a page control associated with an image array. I had it setup correctly just changing the background color and load in the initial image, but when I scroll nothing further is shown. Here is my code:
var images: [UIImage] = [
UIImage(named: "slide1.png")!,
UIImage(named: "loginButton.png")!,
UIImage(named: "slide1.png")!,
UIImage(named: "slide1.png")!
]
func setPageViewinScroll() {
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.pagingEnabled = true
self.imageView.image = images[index]
let subview = UIView(frame: frame)
self.scrollView.addSubview(subview)
}
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * 4, self.scrollView.frame.size.height)
pageControl.addTarget(self, action: Selector("changePage:"), forControlEvents: UIControlEvents.ValueChanged)
}
func changePage(sender: AnyObject) -> () {
let x = CGFloat(pageControl.currentPage) * scrollView.frame.size.width
scrollView.setContentOffset(CGPointMake(x, 0), animated: true)
}
Does anyone know where I am going wrong here?
How about adding your UIImageview to UIScrollview instead of UIView like this code?
var imageOne:UIImageView!
var imageTwo:UIImageView!
var imageThree:UIImageView!
var imageFour:UIImageView!
func functionCalledFromViewDidLoad() {
scrollView.frame = CGRectMake(0, 0, self.view.frame.width,self.view.frame.height)
let scrollViewWidth = scrollView.frame.width
let scrollViewHeight = scrollView.frame.height
imageOne = UIImageView(frame: CGRectMake(0, 0,scrollViewWidth, scrollViewHeight))
imageTwo = UIImageView(frame: CGRectMake(scrollViewWidth*1, 0,scrollViewWidth, scrollViewHeight))
imageThree = UIImageView(frame: CGRectMake(scrollViewWidth*2, 0,scrollViewWidth, scrollViewHeight))
imageFour = UIImageView(frame: CGRectMake(scrollViewWidth*3, 0,scrollViewWidth, scrollViewHeight))
scrollView.addSubview(imageOne)
scrollView.addSubview(imageTwo)
scrollView.addSubview(imageThree)
scrollView.addSubview(imageFour)
}
override func viewDidLayoutSubviews() {
scrollView.contentSize = CGSizeMake(scrollView.frame.width * 4, scrollView.frame.height)
imageOne.frame.size.height = scrollView.frame.height
imageTwo.frame.size.height = scrollView.frame.height
imageThree.frame.size.height = scrollView.frame.height
imageFour.frame.size.height = scrollView.frame.height
}
You also seem to need to add this code.
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
// Test the offset and calculate the current page after scrolling ends
let pageWidth:CGFloat = CGRectGetWidth(scrollView.frame)
let currentPage = Int(floor((scrollView.contentOffset.x-pageWidth/2)/pageWidth)+1)
// Change the page indicator
self.pageControl.currentPage = Int(currentPage)
}
There is a very good tutorial related to this topic, here
You are setting the image on the imageView and not on the subView. I.o.w. You are adding the subview to each page, but not setting the image on it.
Change the subview code to the following
let subview = UIImageView(frame: frame)
subview.image = images[index]
self.scrollView.addSubview(subview)
I have a UIScrollView that I want to have paging functionality (think an initial splash screen). I want that content (a UILabel and a UIImageView) to be placed centrally in each paging view on the scrollView. My problem is is that it is always slightly off centre ().
Here is the complete code:
var splashScreenObjects = [SplashScreenObject]()
var imageViewArray = [UIImageView]()
var subtitleViewArray = [UILabel]()
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var pageControl: UIPageControl!
override func viewDidLoad() {
super.viewDidLoad()
createSplashScreenObjects()
configurePageControl()
configureScrollView()
}
func createSplashScreenObjects() {
let firstScreen: SplashScreenObject = SplashScreenObject(subtitle: "Medication reminders on your phone. Never miss your next dose", image: UIImage(named: "splashScreen1")!)
let secondScreen: SplashScreenObject = SplashScreenObject(subtitle: "Track how good you have been with your medication", image: UIImage(named: "splashScreen2")!)
let thirdScreen: SplashScreenObject = SplashScreenObject(subtitle: "The better you are with your medication, the more points you'll earn!", image: UIImage(named: "splashScreen3")!)
splashScreenObjects.append(firstScreen)
splashScreenObjects.append(secondScreen)
splashScreenObjects.append(thirdScreen)
}
func configureScrollView() {
self.scrollView.layoutIfNeeded()
self.scrollView.showsHorizontalScrollIndicator = false
self.scrollView.showsVerticalScrollIndicator = false
self.scrollView.pagingEnabled = true
self.scrollView.delegate = self
let width = view.frame.size.width
for index in 0..<splashScreenObjects.count {
let subtitle = UILabel(frame: CGRectMake((width * CGFloat(index)) + 25, self.scrollView.frame.size.height-75, width-50, 75))
subtitle.text = splashScreenObjects[index].subtitle
subtitle.textAlignment = NSTextAlignment.Center
subtitle.textColor = UIColor.whiteColor()
subtitle.font = UIFont(name:"Ubuntu", size: 16)
subtitle.numberOfLines = 2
subtitle.backgroundColor = UIColor.clearColor()
self.scrollView.addSubview(subtitle)
self.subtitleViewArray.append(subtitle)
subtitle.alpha = 0
let mainImage = UIImageView(frame: CGRectMake((width * CGFloat(index)), 50, width, self.scrollView.frame.size.height-150))
mainImage.image = splashScreenObjects[index].image
mainImage.contentMode = UIViewContentMode.ScaleAspectFit
self.scrollView.addSubview(mainImage)
self.imageViewArray.append(mainImage)
mainImage.alpha = 0
}
self.scrollView.contentSize = CGSizeMake(width * CGFloat(splashScreenObjects.count), self.scrollView.frame.size.height-50)
animateViews(Int(0))
}
func configurePageControl() {
self.pageControl.numberOfPages = splashScreenObjects.count
self.pageControl.currentPage = 0
self.view.addSubview(pageControl)
pageControl.addTarget(self, action: #selector(SplashViewController.changePage(_:)), forControlEvents: UIControlEvents.ValueChanged)
}
func changePage(sender: AnyObject) -> () {
let x = CGFloat(pageControl.currentPage) * self.view.frame.size.width
scrollView.setContentOffset(CGPointMake(x, 0), animated: true)
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / self.view.frame.size.width)
pageControl.currentPage = Int(pageNumber)
animateViews(Int(pageNumber))
}
func animateViews(pageNumber: Int) {
UIView.animateWithDuration(0.5, animations: {
self.imageViewArray[pageNumber].alpha = 1.0
self.subtitleViewArray[pageNumber].alpha = 1.0
})
}
Here are my auto layout constraints for the UIScrollView:
Your leading and trailing spaces are both -20, which means that the scroll view is 40 points wider than its superview. Change these to 0.
You should replace
self.scrollView.layoutIfNeeded()
to
self.view.layoutIfNeeded()
because layoutIfNeeded layout caller subviews, not itself. So, scrollView, when you add subtitle and mainImage on it, has wrong frame.
I am trying to implement a scroll view with page control to display images in iOS using Swift, to get an output like this:
The scroll view here is a part of another view controller.
I googled but got no help to get the required output.
Can anyone please help me?
The answer is a bit late. So, may be helpful for someone else:
Swift 3x:
First of all, give the delegation like this:
class YOUR_VIEW_CONTROLLER: UIViewController, UIScrollViewDelegate
Now connect the outlets of UIScrollView and UIPageControl like this:
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
NOTE:I'm using colours array. You can use image array instead.
var colors:[UIColor] = [UIColor.red, UIColor.blue, UIColor.green, UIColor.yellow]
var frame: CGRect = CGRect(x:0, y:0, width:0, height:0)
Now just copy and paste the below code in your class:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
configurePageControl()
self.view.bringSubview(toFront: pageControl)
scrollView.delegate = self
self.view.addSubview(scrollView)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
let subView = UIView(frame: frame)
subView.backgroundColor = colors[index]
self.scrollView.addSubview(subView)
}
self.scrollView.isPagingEnabled = true
self.scrollView.contentSize = CGSize(width:self.scrollView.frame.size.width * 4,height: self.scrollView.frame.size.height)
pageControl.addTarget(self, action: #selector(self.changePage(sender:)), for: UIControlEvents.valueChanged)
}
func configurePageControl() {
// The total number of pages that are available is based on how many available colors we have.
self.pageControl.layer.zPosition = 1
self.pageControl.numberOfPages = colors.count
self.pageControl.currentPage = 0
self.pageControl.tintColor = UIColor.red
self.pageControl.pageIndicatorTintColor = UIColor.black
self.pageControl.currentPageIndicatorTintColor = UIColor.green
self.view.addSubview(pageControl)
}
// MARK : TO CHANGE WHILE CLICKING ON PAGE CONTROL
func changePage(sender: AnyObject) -> () {
let x = CGFloat(pageControl.currentPage) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x:x, y:0), animated: true)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
}
Hoping you could give me some direction here. I have a scrollview setup with vertically paging. My problem is the views are larger than the screen (vertically). My desired effect is to have the view scroll to the bottom and then page to the next page. Like my image below is trying to depict.
I have tried setting the size of the scrollview and the content size to the size of the view which does offset the views correctly. I just can't scroll to see the bottom of the view, It just pages to the next view.
Thanks for any advice.
class ViewController: UIViewController {
let scrollView = UIScrollView() // Create the scrollView
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Set up and add scrollView to view
scrollView.frame = self.view.frame
self.scrollView.pagingEnabled = true
self.view.addSubview(scrollView)
//An array of UIColors to add to the views
let x : [UIColor] = [UIColor.blueColor(),UIColor.redColor(),UIColor.yellowColor()]
//For each UIColor add a view that is 100px larger then the height of the scrollView
for index in 0...x.count-1{
//
let subView = UIView(frame: CGRectMake(
0, //x offset
(self.scrollView.frame.height + 100) * CGFloat(index), //y offset
self.scrollView.frame.width, // width
(self.scrollView.frame.height + 100))) // height
subView.backgroundColor = x[index] //background Color
scrollView.addSubview(subView) // Add View
}
//
let c = (self.scrollView.frame.size.height + 100) * CGFloat(x.count)
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.width, c)
//Background Color
self.view.backgroundColor = UIColor.greenColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The best way I've found to do it is to use a nested scrollview for the content. Here is what my code ended up looking like.
class ViewController: UIViewController, UIScrollViewDelegate {
let scrollView = ScrollView() // Create the scrollView
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Set up and add scrollView to view
scrollView.frame = self.view.frame
self.scrollView.pagingEnabled = true
self.view.addSubview(scrollView)
self.scrollView.delegate = self
//An array of UIColors to add to the views
let x : [UIColor] = [UIColor.blueColor(),UIColor.redColor(),UIColor.yellowColor()]
//For each UIColor add a view that is 100px larger then the height of the scrollView
for index in 0...x.count-1{
//
let subView = UIScrollView(frame: CGRectMake(
0, //x offset
(self.scrollView.frame.height * CGFloat(index)), //y offset
self.scrollView.frame.width, // width
(self.scrollView.frame.height))) // height
//Set the size of the content view
let contentView = UIView(frame: CGRectMake(0, 0, self.view.frame.width, 1000))
subView.contentSize = CGSizeMake(self.view.frame.width, contentView.frame.height)
contentView.backgroundColor = x[index]
subView.addSubview(contentView)
scrollView.addSubview(subView) // Add View
}
//
let c = (self.scrollView.frame.size.height) * CGFloat(x.count)
self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.width, c)
//Background Color
self.view.backgroundColor = UIColor.greenColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
User4's answer, in objective-c:
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = self.view.frame;
scrollView.pagingEnabled = YES;
scrollView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:scrollView];
scrollView.delegate = self;
NSArray *x = #[[UIColor blueColor], [UIColor redColor]];
for (int i = 0; i < x.count; i++) {
UIView *subView = [[UIView alloc] initWithFrame:
CGRectMake(0,
(scrollView.frame.size.height) * i,
scrollView.frame.size.width,
scrollView.frame.size.height)
];
UISwitch *switchCtrl = [[UISwitch alloc] initWithFrame:CGRectMake(5, 5, 20, 20)];
subView.backgroundColor = x[i];
[subView addSubview:switchCtrl];
[scrollView addSubview:subView];
}
float c = (scrollView.frame.size.height) * x.count;
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, c);
self.view.backgroundColor = [UIColor greenColor];
A great tutorial by RayWenderlich.com does horizontal page scrolling. I've modified that code to allow for vertical page scrolling by adding a variable called "horizontalDirection". First follow his tutorial here:
http://www.raywenderlich.com/76436/use-uiscrollview-scroll-zoom-content-swift
After you have completed the section "Viewing Previous/Next Pages" replace your view controller with this: (You may need to tweak the size of your scrollview)
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var pageControl: UIPageControl!
var pageImages: [UIImage] = []
var pageViews: [UIImageView?] = []
let horizontalDirection = false
override func viewDidLoad() {
super.viewDidLoad()
// Set up the image you want to scroll & zoom and add it to the scroll view
pageImages = [UIImage(named: "photo1.png")!,
UIImage(named: "photo2.png")!,
UIImage(named: "photo3.png")!,
UIImage(named: "photo4.png")!,
UIImage(named: "photo5.png")!]
let pageCount = pageImages.count
// Set up the page control
pageControl.currentPage = 0
pageControl.numberOfPages = pageCount
// Set up the array to hold the views for each page
for _ in 0..<pageCount {
pageViews.append(nil)
}
// Set up the content size of the scroll view
let pagesScrollViewSize = scrollView.frame.size
if horizontalDirection {
scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width * CGFloat(pageImages.count), pagesScrollViewSize.height)
} else {
scrollView.contentSize = CGSizeMake(pagesScrollViewSize.width, CGFloat(pageImages.count) * pagesScrollViewSize.height)
}
// Load the initial set of pages that are on screen
loadVisiblePages()
}
func loadVisiblePages() {
// First, determine which page is currently visible
var pageSide = scrollView.frame.size.width
var page = Int(floor((scrollView.contentOffset.x * 2.0 + pageSide) / (pageSide * 2.0)))
if !horizontalDirection {
pageSide = scrollView.frame.size.height
page = Int(floor((scrollView.contentOffset.y * 2.0 + pageSide) / (pageSide * 2.0)))
}
// Update the page control
pageControl.currentPage = page
// Work out which pages you want to load
let firstPage = page - 1
let lastPage = page + 1
// Purge anything before the first page
for var index = 0; index < firstPage; ++index {
purgePage(index)
}
// Load pages in our range
for index in firstPage...lastPage {
loadPage(index)
}
// Purge anything after the last page
for var index = lastPage+1; index < pageImages.count; ++index {
purgePage(index)
}
}
func loadPage(page: Int) {
if page < 0 || page >= pageImages.count {
// If it's outside the range of what you have to display, then do nothing
return
}
// Load an individual page, first checking if you've already loaded it
if let pageView = pageViews[page] {
// Do nothing. The view is already loaded.
} else {
var frame = scrollView.bounds
if horizontalDirection {
frame.origin.x = frame.size.width * CGFloat(page)
frame.origin.y = 0.0
frame = CGRectInset(frame, 10.0, 0.0)
} else {
frame.origin.x = 0.0
frame.origin.y = frame.size.height * CGFloat(page)
}
let newPageView = UIImageView(image: pageImages[page])
newPageView.contentMode = .ScaleAspectFit
newPageView.frame = frame
scrollView.addSubview(newPageView)
pageViews[page] = newPageView
}
}
func purgePage(page: Int) {
if page < 0 || page >= pageImages.count {
// If it's outside the range of what you have to display, then do nothing
return
}
// Remove a page from the scroll view and reset the container array
if let pageView = pageViews[page] {
pageView.removeFromSuperview()
pageViews[page] = nil
}
}
func scrollViewDidScroll(scrollView: UIScrollView!) {
// Load the pages that are now on screen
loadVisiblePages()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}