Setting Shape of View Controllers In Swift UIscrollview - ios

I am trying to create a menu that uses scrollviews to swipe between 5 view controllers that are shaped like a T, my problem is that currently my viewcontrollers are shaped like a + sign. I was wondering based on the code below how I could set the left and right view controllers to be aligned to form a T shape instead of a + shape. Just to clarify, the code works as such: The snapcontainerviewcontroller sets up a vertical scrollvew view with three view controllers, top bottom and middle, and then this scrollview view is sandwiched in a horizontal scroll view that contains a left and a right viewcontroller.
AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
// Override point for customization after application launch.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let left = storyboard.instantiateViewController(withIdentifier: "left")
let middle = storyboard.instantiateViewController(withIdentifier: "middle")
let right = storyboard.instantiateViewController(withIdentifier: "right")
let top = storyboard.instantiateViewController(withIdentifier: "top")
let bottom = storyboard.instantiateViewController(withIdentifier: "bottom")
let snapContainer = SnapContainerViewController.containerViewWith(left,
middleVC: middle,
rightVC: right,
topVC: top,
bottomVC: bottom)
self.window?.rootViewController = snapContainer
self.window?.makeKeyAndVisible()
return true
}`
SnapContainerViewController:
class SnapContainerViewController: UIViewController, UIScrollViewDelegate,UIGestureRecognizerDelegate {
var topVc: UIViewController?
var leftVc: UIViewController!
var middleVc: UIViewController!
var rightVc: UIViewController!
var bottomVc: UIViewController?
var directionLockDisabled: Bool!
var horizontalViews = [UIViewController]()
var veritcalViews = [UIViewController]()
var initialContentOffset = CGPoint() // scrollView initial offset
var middleVertScrollVc: VerticalScrollViewController!
var scrollView: UIScrollView!
var delegate: SnapContainerViewControllerDelegate?
let player = MPMusicPlayerController.applicationMusicPlayer()
class func containerViewWith(_ leftVC: UIViewController,
middleVC: UIViewController,
rightVC: UIViewController,
topVC: UIViewController?=nil,
bottomVC: UIViewController?=nil,
directionLockDisabled: Bool?=false) -> SnapContainerViewController {
let container = SnapContainerViewController()
container.directionLockDisabled = directionLockDisabled
container.topVc = topVC
container.leftVc = leftVC
container.middleVc = middleVC
container.rightVc = rightVC
container.bottomVc = bottomVC
return container
}
override func viewDidLoad() {
super.viewDidLoad()
setupVerticalScrollView()
setupHorizontalScrollView()
scrollView.delaysContentTouches = false
scrollView.bounces = false
//scrollView.canCancelContentTouches = false
scrollView.isPagingEnabled = true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func setupVerticalScrollView() {
middleVertScrollVc = VerticalScrollViewController.verticalScrollVcWith(topVc: topVc,
middleVc: middleVc,
bottomVc: bottomVc)
delegate = middleVertScrollVc
}
func setupHorizontalScrollView() {
scrollView = UIScrollView()
scrollView.isPagingEnabled = true
scrollView.showsHorizontalScrollIndicator = false
scrollView.bounces = false
//self.view.bounds.origin.x
let view = (
x: CGFloat(0) ,
y: CGFloat(0),
width: self.view.bounds.width,
height: self.view.bounds.height
)
scrollView.frame = CGRect(x: view.x,
y: view.y,
width: view.width,
height: view.height
)
self.view.addSubview(scrollView)
let scrollWidth = 3 * view.width
let scrollHeight = view.height
scrollView.contentSize = CGSize(width: scrollWidth, height: scrollHeight)
leftVc.view.frame = CGRect(x: 0,
y: 0,
width: view.width,
height: view.height
)
middleVertScrollVc.view.frame = CGRect(x: view.width,
y: 0,
width: view.width,
height: view.height
)
rightVc.view.frame = CGRect(x: 2 * view.width,
y: 0,
width: view.width,
height: view.height
)
addChildViewController(leftVc)
addChildViewController(middleVertScrollVc)
addChildViewController(rightVc)
scrollView.addSubview(leftVc.view)
scrollView.addSubview(middleVertScrollVc.view)
scrollView.addSubview(rightVc.view)
leftVc.didMove(toParentViewController: self)
middleVertScrollVc.didMove(toParentViewController: self)
rightVc.didMove(toParentViewController: self)
scrollView.contentOffset.x = middleVertScrollVc.view.frame.origin.x
//scrollView.contentOffset.y = (topVc?.view.frame.origin.y)!
scrollView.delegate = self
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.initialContentOffset = scrollView.contentOffset
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if delegate != nil && !delegate!.outerScrollViewShouldScroll() && !directionLockDisabled {
let newOffset = CGPoint(x: self.initialContentOffset.x, y: self.initialContentOffset.y)
// Setting the new offset to the scrollView makes it behave like a proper
// directional lock, that allows you to scroll in only one direction at any given time
self.scrollView!.setContentOffset(newOffset, animated: false)
}
}
}
VerticalScrollViewController:
class VerticalScrollViewController: UIViewController, SnapContainerViewControllerDelegate {
var topVc: UIViewController!
var middleVc: UIViewController!
var bottomVc: UIViewController!
var scrollView: UIScrollView!
class func verticalScrollVcWith(topVc: UIViewController?=nil, middleVc: UIViewController,bottomVc: UIViewController?=nil) -> VerticalScrollViewController {
let middleScrollVc = VerticalScrollViewController()
middleScrollVc.topVc = topVc
middleScrollVc.middleVc = middleVc
middleScrollVc.bottomVc = bottomVc
return middleScrollVc
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view:
setupScrollView()
scrollView.isPagingEnabled = true
}
func setupScrollView() {
scrollView = UIScrollView()
scrollView.isPagingEnabled = true
scrollView.showsVerticalScrollIndicator = false
scrollView.bounces = false
//scrollView.isScrollEnabled = false
let view = (
x: CGFloat(0),
y: CGFloat(0),
width: self.view.bounds.width,
height: self.view.bounds.height
)
scrollView.frame = CGRect(x: view.x, y: view.y, width: view.width, height: view.height)
self.view.addSubview(scrollView)
let scrollWidth: CGFloat = view.width
var scrollHeight: CGFloat
scrollHeight = 3 * view.height
topVc.view.frame = CGRect(x: 0, y: 0, width: view.width, height: view.height)
middleVc.view.frame = CGRect(x: 0, y: view.height, width: view.width, height: view.height)
bottomVc.view.frame = CGRect(x: 0, y: 2 * view.height, width: view.width, height: view.height)
addChildViewController(topVc)
addChildViewController(middleVc)
addChildViewController(bottomVc)
scrollView.addSubview(topVc.view)
scrollView.addSubview(middleVc.view)
scrollView.addSubview(bottomVc.view)
topVc.didMove(toParentViewController: self)
middleVc.didMove(toParentViewController: self)
bottomVc.didMove(toParentViewController: self)
print("1st case!")
//scrollView.contentOffset.y = middleVc.view.frame.origin.y
scrollView.contentOffset.y = topVc.view.frame.origin.y
scrollView.contentSize = CGSize(width: scrollWidth, height: scrollHeight)
scrollView.delaysContentTouches = false
//scrollView.canCancelContentTouches = false
}
// MARK: - SnapContainerViewControllerDelegate Methods
/**
*/
func outerScrollViewShouldScroll() -> Bool {
if scrollView.contentOffset.y < middleVc.view.frame.origin.y || scrollView.contentOffset.y > middleVc.view.frame.origin.y {
return false
} else {
return true
}
}
}

You're outerScrollViewShouldScroll method is not correct. You're only letting it scroll when the contentOffset is equal to the middleVc. You should change to allow scrolling only when contentOffset.y is equal to topVc's origin.y
Replace
if scrollView.contentOffset.y < middleVc.view.frame.origin.y || scrollView.contentOffset.y > middleVc.view.frame.origin.y {
return false
} else {
return true
}
With this:
return scrollView.contentOffset.y == topVc.view.frame.origin.y

Related

How do you pass a gesture between subviews in UIKit?

I've got a ViewController with three subviews. I'm trying to get them to detect touches in their bounds from a starting point outside their bounds without the user lifting their finger (ie the user dragging into the view). I thought hitTest would do this but it only works for separate taps. I assume this is probably passing a gesture through instead but I've not found out how to implement this.
class SuperViewController: UIViewController {
var view01 = UIView(frame: CGRect(x: 0, y: 0, width: 1000,
height: 800))
var view02 = UIView(frame: CGRect(x: 0, y: 0, width: 600,
height: 400))
let view03 = UIView(frame: CGRect(x: 0, y: 0, width: 300,
height: 200))
override func viewDidLoad() {
super.viewDidLoad()
self.view = TestView()
view01.backgroundColor = .orange
view02.backgroundColor = .blue
view03.backgroundColor = .green
self.view.addSubview(view01)
self.view.addSubview(view02)
self.view.addSubview(view03)
}
}
Which produces this
And then I've subclassed UIView for the SuperViewController's view.
class TestView: UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard self.isUserInteractionEnabled, !isHidden, alpha > 0.01 else {return nil}
if self.point(inside: point, with: event) {
for subview in subviews.reversed() {
let hitView = subview.hitTest(point, with: event)
if hitView != nil {
hitView?.backgroundColor = .red
return hitView
}
}
return self
}
return nil
}
}
So each one turns red when the user taps. But ideally I want them to each respond with one drag from the top left corner of the screen to the other.
You can accomplish this with a UIPanGestureRecognizer.
Here's an example below:
class ViewController: UIViewController {
var view01 = UIView(frame: CGRect(x: 0, y: 0, width: 1000,
height: 800))
var view02 = UIView(frame: CGRect(x: 0, y: 0, width: 600,
height: 400))
let view03 = UIView(frame: CGRect(x: 0, y: 0, width: 300,
height: 200))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view01.backgroundColor = .orange
view02.backgroundColor = .blue
view03.backgroundColor = .green
self.view.addSubview(view01)
self.view.addSubview(view02)
self.view.addSubview(view03)
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
self.view.addGestureRecognizer(gestureRecognizer)
}
#objc
private func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
guard let view = gestureRecognizer.view else {
return
}
let translation = gestureRecognizer.translation(in: view)
for subview in view.subviews.reversed() {
if let hitView = subview.hitTest(translation, with: nil) {
hitView.backgroundColor = .red
return
}
}
}
}

Zoom on UIView contained in UIScrollView

I have some trouble handling zoom on UIScrollView that contains many subviews. I already saw many answers on SO, but none of them helped me.
So, basically what I'm doing is simple : I have a class called UIFreeView :
import UIKit
class UIFreeView: UIView, UIScrollViewDelegate {
var mainUIView: UIView!
var scrollView: UIScrollView!
var arrayOfView: [UIView]?
override init(frame: CGRect) {
super.init(frame: frame)
self.setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupView() {
// MainUiView
self.mainUIView = UIView(frame: self.frame)
self.addSubview(mainUIView)
// ScrollView
self.scrollView = UIScrollView(frame: self.frame)
self.scrollView.delegate = self
self.addSubview(self.scrollView)
}
func reloadViews(postArray:[Post]?) {
if let postArray = postArray {
print("UIFreeView::reloadVIew.postArraySize = \(postArray.count)")
let size: CGFloat = 80.0
let margin: CGFloat = 20.0
scrollView.contentSize.width = (size * CGFloat(postArray.count))+(margin*CGFloat(postArray.count))
scrollView.contentSize.height = (size * CGFloat(postArray.count))+(margin*CGFloat(postArray.count))
for item in postArray {
let view = buildPostView(item)
self.scrollView.addSubview(view)
}
}
}
fileprivate func buildPostView(_ item:Post) -> UIView {
// Const
let size: CGFloat = 80.0
let margin: CGFloat = 5.0
// Var
let view = UIView()
let textView = UITextView()
let backgroundImageView = UIImageView()
// Setup view
let x = CGFloat(UInt64.random(lower: UInt64(0), upper: UInt64(self.scrollView.contentSize.width)))
let y = CGFloat(UInt64.random(lower: UInt64(0), upper: UInt64(self.scrollView.contentSize.height)))
view.frame = CGRect(x: x,
y: y,
width: size,
height: size)
// Setup background view
backgroundImageView.frame = CGRect(x: 0,
y: 0,
width: view.frame.size.width,
height: view.frame.size.height)
var bgName = ""
if (item.isFromCurrentUser) {
bgName = "post-it-orange"
} else {
bgName = "post-it-white"
}
backgroundImageView.contentMode = .scaleAspectFit
backgroundImageView.image = UIImage(named: bgName)
view.addSubview(backgroundImageView)
// Setup text view
textView.frame = CGRect(x: margin,
y: margin,
width: view.frame.size.width - margin*2,
height: view.frame.size.height - margin*2)
textView.backgroundColor = UIColor.clear
textView.text = item.content
textView.isEditable = false
textView.isSelectable = false
textView.isUserInteractionEnabled = false
view.addSubview(textView)
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
view.addGestureRecognizer(gestureRecognizer)
return view
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.scrollView
}
func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
let translation = gestureRecognizer.translation(in: self.scrollView)
// note: 'view' is optional and need to be unwrapped
gestureRecognizer.view!.center = CGPoint(x: gestureRecognizer.view!.center.x + translation.x, y: gestureRecognizer.view!.center.y + translation.y)
gestureRecognizer.setTranslation(CGPoint.zero, in: self.scrollView)
}
}
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
This class is working perfectly, I can scroll through all my views, but I can't zoom-in and zoom-out in order to see less/more views on my screen.
I think the solution is simple, but I can't seem to find a real solution for my problem ..
Thanks !

View does not stick on top (does not change position)

I am trying to stick the UIView on top while scrolling. Tried using max(x:T, y:T) method as suggested here on stackOverflow but it does not work. I manage to detect when the scrollView should be re-positioned but updating frame does not have any affect.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate{
#IBOutlet var objectView: UIView!
#IBOutlet var scrollView: UIScrollView!
//var originalOffsetY : CGFloat!
//var originalOffestX : CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let size = CGSize.init(width: self.view.frame.width, height: self.view.frame.height*2)
scrollView.contentSize = size
scrollView.backgroundColor = UIColor.blueColor()
objectView.backgroundColor = UIColor.whiteColor()
scrollView.delegate = self
scrollView.addSubview(objectView)
}
// override func viewWillAppear(animated: Bool) {
// originalOffsetY = objectView.frame.origin.y
// originalOffestX = objectView.frame.origin.x
// }
func scrollViewDidScroll(scrollView: UIScrollView) {
print("ScrollView \(scrollView.contentOffset.y)")
print("ObjectView \(objectView.frame.origin.y)")
let location = CGPointMake(0, scrollView.contentOffset.y)
let size = objectView.frame.size
if scrollView.contentOffset.y >= objectView.frame.origin.y {
objectView.frame = CGRect.init(origin: location, size: size)
print("Detected \(objectView.frame)")
}
// var newRect = objectView.frame
// newRect.origin.y = max(originalOffsetY!, scrollView.contentOffset.y)
// objectView.frame = newRect
}
}
The condition is matched successfully as can be seen here in Logs . But the view remains unchanged. I require the objectView to scroll a bit.. from around y=270 to 0 .. but not beyond it.
You need to keep track of the original position of the view within the scroll view, and calculate using that value, here's a very simplified example:
class StickyScrollViewController: UIViewController {
var stickyView = UIView(frame: CGRect(x: 0, y: 100, width: 300, height: 100))
var originalStickyOrigin: CGPoint = CGPoint(x: 0, y: 100)
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var nextYOffset = max(originalStickyOrigin.y, scrollView.contentOffset.y)
stickyView.frame = CGRect(x: 0, y: nextYOffset, width: 300, height: 100)
}
}

Swift UIScrollView snap to subview width without pagingEnabled

How can i implement UIScrollView when swiping snap to its subviews width. I need it to behave like pagingEnabled but i cant enable paging because i need my entire view can be swipe to scroll. if i do pagingEnable its impossible because scrollview bounds will be change to subviews width.
is there any possible way to do this.
please check the image for more details
import UIKit
class ViewController: UIViewController{
var navigationScroller: UIScrollView!
var contentScroller: UIScrollView!
var navContainer: UIView!
var contentContainer: UIView!
var selfWidth:CGFloat?
var navigationLabels = ["EVENTS", "MEMBERS", "SECTORS", "ORGANIZATIONS", "SEARCH", "EVENTS", "MEMBERS"]
private var buttonsTextFontAndSize: UIFont = UIFont(name: "HelveticaNeue-Light", size: 14)!
override func viewDidLoad() {
super.viewDidLoad()
selfWidth = self.view.frame.width
let frameWidth = self.view.frame.width
let frameHeight = self.view.frame.height
//let navscrollPosition = CGFloat( (frameWidth/2) - (75.0/2) )
navContainer = UIView(frame: CGRectMake(0.0, 75.0, frameWidth, 40.0))
navContainer.backgroundColor = UIColor(red:0, green:0.302, blue:0.522, alpha:1)
navigationScroller = UIScrollView(frame: CGRectMake(0.0, 0.0, frameWidth, 40.0))
navigationScroller.backgroundColor = UIColor.clearColor()
navigationScroller.pagingEnabled = false
navigationScroller.showsHorizontalScrollIndicator = false
navigationScroller.showsVerticalScrollIndicator = false
navigationScroller.clipsToBounds = false
navigationScroller.contentInset = UIEdgeInsetsZero
//navigationScroller.userInteractionEnabled = false
//navigationScroller.
addNavigationLabels(navigationScroller)
self.view.addSubview(navContainer)
navContainer.addSubview(navigationScroller)
navigationScroller.contentSize = CGSize(width: 150.0 * CGFloat(navigationLabels.count),height: 40.0)
navigationScroller.contentOffset = CGPoint(x: 170.0, y:0.0)
contentContainer = UIView(frame: CGRectMake(0.0, 115.0, frameWidth, frameHeight-115.0))
contentContainer.backgroundColor = UIColor.clearColor()
contentScroller = UIScrollView(frame: CGRectMake(0.0, 0.0, frameWidth, frameHeight-115.0))
contentScroller.backgroundColor = UIColor.clearColor()
contentScroller.pagingEnabled = true
contentScroller.showsHorizontalScrollIndicator = false
contentScroller.showsVerticalScrollIndicator = false
contentScroller.clipsToBounds = true
contentScroller.contentInset = UIEdgeInsetsZero
//contentScroller.addSubview(navContainer)
addContents(contentScroller)
self.view.addSubview(contentContainer)
contentContainer.addSubview(contentScroller)
contentScroller.contentSize = CGSize(width: frameWidth * CGFloat(navigationLabels.count),
height: frameHeight-115.0)
//contentScroller.delegate = self
navigationScroller.delegate = self
}
//MARK: -View Appeared function
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: -Adding navigation labels fron navigation labels array
private func addNavigationLabels(navScrollView:UIScrollView){
var buttonsXPosition: CGFloat = 0
var buttonNumber = 0
for navLabel in navigationLabels {
var navButton: UIButton!
let red = CGFloat(buttonNumber) - 0.9
let frameWidth = self.view.frame.width
navButton = UIButton(frame: CGRectMake(buttonsXPosition, 0, frameWidth/3, 40.0))
navButton.titleLabel!.font = buttonsTextFontAndSize
navButton.contentHorizontalAlignment = .Center
navButton.backgroundColor = UIColor(red:red , green:0.114, blue:0.286, alpha:1)
navButton.setTitle(navLabel, forState: UIControlState.Normal)
navButton.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
navScrollView.addSubview(navButton)
buttonsXPosition = frameWidth/3 + buttonsXPosition
buttonNumber++
}
}
func buttonAction(sender:UIButton!){
print("pressed")
}
// MARK: -Adding navigation labels fron navigation labels array
private func addContents(contentScroller:UIScrollView){
var buttonsXPosition: CGFloat = 0
var buttonNumber = 0
let frameWidth = self.view.frame.width
let frameHeight = self.view.frame.height
for navLabel in navigationLabels {
var navButton: UIButton!
navButton = UIButton(frame: CGRectMake(buttonsXPosition, 40.0, frameWidth, frameHeight-155))
navButton.titleLabel!.font = buttonsTextFontAndSize
navButton.contentHorizontalAlignment = .Center
navButton.backgroundColor = UIColor.darkGrayColor()
navButton.setTitle(navLabel, forState: UIControlState.Normal)
contentScroller.addSubview(navButton)
buttonsXPosition = frameWidth + buttonsXPosition
buttonNumber++
}
}
}
app view
You can implement UIScrollViewDelegate's method scrollViewWillEndDragging:withVelocity:targetContentOffset: and modify the offset at it will finish decelerating to match the width that you wish.
Something like this:
class ScrollSample: NSObject, UIScrollViewDelegate {
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let targetOffset = targetContentOffset.memory.x
// Round the offset to be a multiple of scrollview width
let roundedOffset = round(targetOffset / scrollView.frame.width) * scrollView.frame.width
targetContentOffset.memory = CGPoint(x: roundedOffset, y: 0)
}
}

How to create a Scroll View with a page control using swift? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I am trying to create a Page View controller with numbers of view. I want a simple code sample that will use UIPageViewController.
import UIKit
class DummyVC: UIViewController, UIScrollViewDelegate {
let scrollView = UIScrollView(frame: CGRect(x:0, y:0, width:320,height: 300))
var colors:[UIColor] = [UIColor.red, UIColor.blue, UIColor.green, UIColor.yellow]
var frame: CGRect = CGRect(x:0, y:0, width:0, height:0)
var pageControl : UIPageControl = UIPageControl(frame: CGRect(x:50,y: 300, width:200, height:50))
override func viewDidLoad() {
super.viewDidLoad()
configurePageControl()
scrollView.delegate = self
scrollView.isPagingEnabled = true
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.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.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)
}
}
For lazy coder this is the Swift 3 implementation based on That lazy iOS Guy 웃's answer
import UIKit
class ViewController: UIViewController,UIScrollViewDelegate {
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 320, height: 300))
var colors:[UIColor] = [UIColor.red, UIColor.blue, UIColor.green, UIColor.yellow]
var frame: CGRect = CGRect(x: 0, y: 0, width: 0, height: 0)
var pageControl : UIPageControl = UIPageControl(frame:CGRect(x: 50, y: 300, width: 200, height: 50))
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
configurePageControl()
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.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)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Swift 3 - Horizontal image scroll
import UIKit
class pageenabled: UIViewController,UIScrollViewDelegate
{
let imagelist = ["img1.jpg", "photo1.jpg", "photo3.jpg", "photo4.jpg", "photo5.jpg"]
var scrollView = UIScrollView()
var pageControl : UIPageControl = UIPageControl(frame:CGRect(x: 50, y: 300, width: 200, height: 50))
var yPosition:CGFloat = 0
var scrollViewContentSize:CGFloat=0;
override func viewDidLoad() {
super.viewDidLoad()
scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 300))
configurePageControl()
scrollView.delegate = self
self.view.addSubview(scrollView)
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
self.scrollView.isPagingEnabled = true
let myImage:UIImage = UIImage(named: imagelist[i])!
let myImageView:UIImageView = UIImageView()
myImageView.image = myImage
myImageView.contentMode = UIViewContentMode.scaleAspectFit
myImageView.frame = frame
scrollView.addSubview(myImageView)
}
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)
// Do any additional setup after loading the view.
}
func configurePageControl() {
// The total number of pages that are available is based on how many available colors we have.
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.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)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
In Swift 3.0
craeate iboutlets through story board for scrollview and pagecontroller.
#IBOutlet weak var imgScrollView: UIScrollView!
#IBOutlet weak var imgPageController: UIPageControl!
var sliderImagesArray = NSMutableArray()
in viewdidload method write this code
sliderImagesArray = ["https://images.unsplash.com/photo-1432679963831-2dab49187847?w=1080","https://images.unsplash.com/photo-1447746249824-4be4e1b76d66?w=1080", "https://images.unsplash.com/photo-1463595373836-6e0b0a8ee322?w=1080"]
imgScrollView.delegate = self
for i in 0..<sliderImagesArray.count {
var imageView : UIImageView
let xOrigin = self.imgScrollView.frame.size.width * CGFloat(i)
imageView = UIImageView(frame: CGRect(x: xOrigin, y: 0, width: self.imgScrollView.frame.size.width, height: self.imgScrollView.frame.size.height))
imageView.isUserInteractionEnabled = true
let urlStr = sliderImagesArray.object(at: i)
print(imgScrollView,imageView, urlStr)
imageView.sd_setImage(with: URL(string: urlStr as! String), placeholderImage: UIImage(named: "placeholder.png"))
imageView .contentMode = UIViewContentMode.scaleToFill
self.imgScrollView.addSubview(imageView)
}
self.imgScrollView.isPagingEnabled = true
self.imgScrollView.bounces = false
self.imgScrollView.showsVerticalScrollIndicator = false
self.imgScrollView.showsHorizontalScrollIndicator = false
self.imgScrollView.contentSize = CGSize(width:
self.imgScrollView.frame.size.width * CGFloat(sliderImagesArray.count), height: self.imgScrollView.frame.size.height)
imgPageController.addTarget(self, action: #selector(self.changePage(sender:)), for: UIControlEvents.valueChanged)
self.imgPageController.numberOfPages = sliderImagesArray.count
self.imgPageController.currentPage = 0
self.imgPageController.tintColor = UIColor.red
self.imgPageController.pageIndicatorTintColor = UIColor.black
self.imgPageController.currentPageIndicatorTintColor = UIColor.blue
after that implement scrollview delegate methods
func changePage(sender: AnyObject) -> () {
let x = CGFloat(imgPageController.currentPage) * imgScrollView.frame.size.width
imgScrollView.setContentOffset(CGPoint(x: x,y :0), animated: true)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(imgScrollView.contentOffset.x / imgScrollView.frame.size.width)
imgPageController.currentPage = Int(pageNumber)
}
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var imageViewBottomConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewLeadingConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTopConstraint: NSLayoutConstraint!
#IBOutlet weak var imageViewTrailingConstraint: NSLayoutConstraint!
extension ZoomedPhotoViewController: UIScrollViewDelegate {
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
}
private func updateMinZoomScaleForSize(size: CGSize) {
let widthScale = size.width / imageView.bounds.width
let heightScale = size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
scrollView.minimumZoomScale = minScale
scrollView.zoomScale = minScale
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
updateMinZoomScaleForSize(view.bounds.size)
}
private func updateConstraintsForSize(size: CGSize) {
let yOffset = max(0, (size.height - imageView.frame.height) / 2)
imageViewTopConstraint.constant = yOffset
imageViewBottomConstraint.constant = yOffset
let xOffset = max(0, (size.width - imageView.frame.width) / 2)
imageViewLeadingConstraint.constant = xOffset
imageViewTrailingConstraint.constant = xOffset
view.layoutIfNeeded()
}
func scrollViewDidZoom(scrollView: UIScrollView) {
updateConstraintsForSize(view.bounds.size)
}
import UIKit
public class PhotoCommentViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var nameTextField: UITextField!
public var photoName: String!
override public func viewDidLoad() {
super.viewDidLoad()
if let photoName = photoName {
self.imageView.image = UIImage(named: photoName)
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let cell = sender as? UICollectionViewCell,
indexPath = collectionView?.indexPathForCell(cell),
photoCommentViewController = segue.destinationViewController as? PhotoCommentViewController {
photoCommentViewController.photoName = "photo\(indexPath.row + 1)"
}
}
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(PhotoCommentViewController.keyboardWillShow(_:)),
name: UIKeyboardWillShowNotification,
object: nil
)
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: #selector(PhotoCommentViewController.keyboardWillHide(_:)),
name: UIKeyboardWillHideNotification,
object: nil
)
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func adjustInsetForKeyboardShow(show: Bool, notification: NSNotification) {
guard let value = notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue else { return }
let keyboardFrame = value.CGRectValue()
let adjustmentHeight = (CGRectGetHeight(keyboardFrame) + 20) * (show ? 1 : -1)
scrollView.contentInset.bottom += adjustmentHeight
scrollView.scrollIndicatorInsets.bottom += adjustmentHeight
}
func keyboardWillShow(notification: NSNotification) {
adjustInsetForKeyboardShow(true, notification: notification)
}
func keyboardWillHide(notification: NSNotification) {
adjustInsetForKeyboardShow(false, notification: notification)
}
#IBAction func hideKeyboard(sender: AnyObject) {
nameTextField.endEditing(true)
}
public var photoIndex: Int!
import UIKit
class ManagePageViewController: UIPageViewController {
var photos = ["photo1", "photo2", "photo3", "photo4", "photo5"]
var currentIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
// 1
if let viewController = viewPhotoCommentController(currentIndex ?? 0) {
let viewControllers = [viewController]
// 2
setViewControllers(
viewControllers,
direction: .Forward,
animated: false,
completion: nil
)
}
}
func viewPhotoCommentController(index: Int) -> PhotoCommentViewController? {
if let storyboard = storyboard,
page = storyboard.instantiateViewControllerWithIdentifier("PhotoCommentViewController")
as? PhotoCommentViewController {
page.photoName = photos[index]
page.photoIndex = index
return page
}
return nil
}
}

Resources