I followed a tutorial: https://www.youtube.com/watch?v=1_daE3IL_1s that teaches you how to make a snap-chat like menu in swift 3, where every time you swipe a new subview is put on the screen, but it is the only one and you need to swipe another time to get the next view. This tutorial was made in swift 2, but when I updated to swift 3 the scrollview is now acting like normal scroll view where it scrolls fluently. is there any way to fix this?
code for main view controller:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let V1: View1 = View1(nibName: "View1", bundle: nil)
let V2: View2 = View2(nibName: "View2", bundle: nil)
let V3: View3 = View3(nibName: "View3", bundle: nil)
V1.didMove(toParentViewController: self)
self.addChildViewController(V1)
self.scrollView.addSubview(V1.view)
V2.didMove(toParentViewController: self)
self.addChildViewController(V2)
self.scrollView.addSubview(V2.view)
V3.didMove(toParentViewController: self)
self.addChildViewController(V3)
self.scrollView.addSubview(V3.view)
var V2Frame: CGRect = V2.view.frame
V2Frame.origin.x = self.view.frame.width
V2.view.frame = V2Frame
var V3Frame: CGRect = V3.view.frame
V3Frame.origin.x = 2 * self.view.frame.width
V3.view.frame = V3Frame
self.scrollView.contentSize = CGSize(width: self.view.frame.width*3 , height: self.view.frame.size.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Enable paging:
override func viewDidLoad() {
super.viewDidLoad()
scrollView.isPagingEnabled = true
// ...
}
Related
I'm trying to update text of a label after a scroll event. I have a print command that prints the correct value but the label is not updating.
Here's my code
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)") // this prints correct value
self.signalLabel.text = signalText[Int(x/w)] // this does not update
}
what's the deal?
Here's the complete view controller code. This view is called from a button click on the initial view controller. This view contains a UIScrollView and UIPageControl. The UIScrollView contains two images that can be scrolled back and forth. I want to update the label text based on image that is shown.
import UIKit
class SignalOneViewController: UIViewController, UIScrollViewDelegate {
// MARK: Properties
#IBOutlet weak var signalScrollView: UIScrollView!
#IBOutlet weak var signalPageControl: UIPageControl!
#IBOutlet weak var signalLabel: UILabel!
// MARK: - Button Actions
#IBAction func signalOneButton(_ sender: Any) {
print("signal one button clicked")
performSegue(withIdentifier: "SignalOneSegue", sender: self)
}
#IBAction func onCancelButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
let signalImages = ["signal1a.png", "signal1b.png"]
let signalText = ["Ready for play", "Untimed down"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidLayoutSubviews() {
self.loadScrollView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadScrollView() {
let pageCount : CGFloat = CGFloat(signalImages.count)
signalLabel.text = signalText[0]
signalScrollView.backgroundColor = UIColor.clear
signalScrollView.delegate = self
signalScrollView.isPagingEnabled = true
signalScrollView.contentSize = CGSize(width: signalScrollView.frame.size.width * pageCount, height: signalScrollView.frame.size.height)
signalScrollView.showsHorizontalScrollIndicator = false
signalScrollView.showsVerticalScrollIndicator = false
signalPageControl.numberOfPages = Int(pageCount)
signalPageControl.pageIndicatorTintColor = UIColor.lightGray
signalPageControl.currentPageIndicatorTintColor = UIColor.blue
signalPageControl.addTarget(self, action: #selector(self.pageChanged), for: .valueChanged)
for i in 0..<Int(pageCount) {
print(self.signalScrollView.frame.size.width)
let image = UIImageView(frame: CGRect(x: self.signalScrollView.frame.size.width * CGFloat(i), y: 0, width: self.signalScrollView.frame.size.width, height: self.signalScrollView.frame.size.height))
image.image = UIImage(named: signalImages[i])!
image.contentMode = UIViewContentMode.scaleAspectFit
self.signalScrollView.addSubview(image)
}
}
//MARK: UIScrollView Delegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let viewWidth: CGFloat = scrollView.frame.size.width
// content offset - tells by how much the scroll view has scrolled.
let pageNumber = floor((scrollView.contentOffset.x - viewWidth / 50) / viewWidth) + 1
signalPageControl.currentPage = Int(pageNumber)
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let x = scrollView.contentOffset.x
let w = scrollView.bounds.size.width
let p = Int(x/w)
print("page \(p)")
self.signalLabel.text = signalText[p]
print(">>> \(signalText[Int(x/w)])")
}
//MARK: page tag action
#objc func pageChanged() {
let pageNumber = signalPageControl.currentPage
var frame = signalScrollView.frame
frame.origin.x = frame.size.width * CGFloat(pageNumber)
frame.origin.y = 0
signalScrollView.scrollRectToVisible(frame, animated: true)
}
}
Make sure signalLabe IBOutlet is attached to your label in storyboard or xib
Similar to what we see with the Snapchat application.
This is the code I've been working with from multiple videos I've looked at on Youtube.
I find this error at the end the last line of code.
Currently, It's stating expected expression.
Thanks for your input!
import UIKit
class ViewController: UIViewController {
override var navigationController: UINavigationController {
weak var scrollView: UIScrollView!
func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let vc0 = ViewController0(nibName: "ViewController0", bundle: nil)
self.addChildViewController(vc0)
scrollView.addSubview(vc0.view)
vc0.didMove(toParentViewController: self)
let vc1 = ViewController1(nibName: "ViewController1", bundle: nil)
var frame1 = vc1.view.frame
frame1.origin.x = vc1.view.frame.size.width
vc1.view.frame = frame1
self.addChildViewController(vc1)
scrollView.addSubview(vc1.view)
vc1.didMove(toParentViewController: self)
let vc2 = ViewController2(nibName: "ViewController2", bundle: nil)
let frame2 = vc2.view.frame
frame1.origin.x = vc2.view.frame.size.width
vc2.view.frame = frame2
self.addChildViewController(vc2)
scrollView.addSubview(vc2.view)
vc2.didMove(toParentViewController: self)
let vc3 = ViewController3(nibName: "ViewController3", bundle: nil)
var frame3 = vc3.view.frame
frame3.origin.x = vc3.view.frame.size.width
vc3.view.frame = frame3
self.addChildViewController(vc3)
scrollView.addSubview(vc3.view)
vc3.didMove(toParentViewController: self)
scrollView.contentSize = CGSizeMake.self.view.frame.size.width * 4, self.view.frame.size.height - 66)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I want to create the slide to unlock animation like it is there on the iPhone lock screen. I want the user to swipe right so that another view comes to the front. How should I make this? I have tried this, and here is my code:-
import UIKit
class PageViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setUpScrollView()
}
func setUpScrollView () {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let aViewController = storyboard.instantiateViewControllerWithIdentifier("Hello") as! HelloViewController;
let bViewController = storyboard.instantiateViewControllerWithIdentifier("Home") as! HomeViewController;
let viewControllers = [bViewController, aViewController]
scrollView.pagingEnabled = true
scrollView.contentSize.height = 600
var contentSizeWidth = CGFloat(2) * self.view.frame.width
scrollView.contentSize.width = contentSizeWidth
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.scrollsToTop = false
scrollView.delegate = self
// add all views to scrollView
for (index, vc) in enumerate(viewControllers) {
var frame = self.view.frame
frame.origin.x = frame.width * CGFloat(index)
frame.origin.y = 0
vc.view.frame = frame
self.addChildViewController(vc)
self.scrollView.addSubview(vc.view)
vc.didMoveToParentViewController(self)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The problem that I face is, that the view on the left is cropped somehow. To make you visualise this, the view with the slide to unlock label appears when the iOS simulator boots up. But when I swipe right, the scrollView works perfectly, just the second view is cropped (it is on the extreme left, occupying less than half of the screen that it should ideally fully occupy. Please help me out here. Thanks in advance.
I want to code a reader in swift.
I use a pageViewController for this. To enable ZoomIN/ZoomOut in use a UIscrollView, my idea is to put inside this scrollView the pageViewController.
Effectively, it works. But my problem is only in the position on screen, the pageview controller is cropped.
My code:
class RootViewController: UIViewController,
UIPageViewControllerDelegate,
UIPageViewControllerDataSource,
UIScrollViewDelegate
{
#IBOutlet weak var scrollView: UIScrollView!
var isLandscape:Bool = Bool()
var pageData:[String] = []
var pageViewController:UIPageViewController = UIPageViewController()
//MARK: ViewDid/Should methods
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
loadData() // Load the images URL
// Set up the pageViewController
pageViewController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.PageCurl, navigationOrientation: UIPageViewControllerNavigationOrientation.Horizontal, options: nil)
pageViewController.delegate = self
pageViewController.dataSource = self
var startingViewController:DataViewController = self.viewControllerAtIndex(0) as DataViewController
var viewControllers = [startingViewController] as NSArray
pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
self.addChildViewController(pageViewController)
self.contentView.addSubview(pageViewController.view)
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
var pageViewRect:CGRect = self.view.bounds
pageViewRect = CGRectInset(pageViewRect, 10.0, 20.0)
self.view.frame = pageViewRect
self.pageViewController.didMoveToParentViewController(self)
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 2.5
scrollView.zoomScale = 1
scrollView.setZoomScale(1.0, animated:false)
}
}
func viewForZoomingInScrollView(scrollView:UIScrollView) -> UIView {
// Return the view that you want to zoom
return pageViewController.view
}
Screenshot:
Can somebody can help me to fix this.
Thanks.
So I am trying to create a fade in animation for a UI Image that is in a page view scroller after a button is clicked in the main view controller. This is my main storyboard.
class MainWorkoutViewController: UIViewController {
// Outlet used in storyboard
#IBOutlet var scrollView: UIScrollView?;
override func viewDidLoad() {
super.viewDidLoad();
func scrollViewDidEndDragging(MainWorkoutViewController: UIScrollView,
withVelocity: CGPoint,
targetContentOffset : UnsafeMutablePointer<CGPoint>){
}
// 1) Create the three views used in the swipe container view
var AVc :AViewController = AViewController(nibName: "AViewController", bundle: nil);
var BVc :BViewController = BViewController(nibName: "BViewController", bundle: nil);
var CVc :CViewController = CViewController(nibName: "CViewController", bundle: nil);
// 2) Add in each view to the container view hierarchy
// Add them in opposite order since the view hieracrhy is a stack
self.addChildViewController(CVc);
self.scrollView!.addSubview(CVc.view);
CVc.didMoveToParentViewController(self);
self.addChildViewController(BVc);
self.scrollView!.addSubview(BVc.view);
BVc.didMoveToParentViewController(self);
self.addChildViewController(AVc);
self.scrollView!.addSubview(AVc.view);
AVc.didMoveToParentViewController(self);
// 3) Set up the frames of the view controllers to align
// with eachother inside the container view
var adminFrame :CGRect = BVc.view.frame;
adminFrame.origin.x = adminFrame.width;
AVc.view.frame = adminFrame;
var BFrame :CGRect = AVc.view.frame;
BFrame.origin.x = 2*BFrame.width;
CVc.view.frame = BFrame;
// 4) Finally set the size of the scroll view that contains the frames
var scrollWidth: CGFloat = 3 * self.view.frame.width
var scrollHeight: CGFloat = self.view.frame.size.height
self.scrollView!.contentSize = CGSizeMake(scrollWidth, scrollHeight)
var frame: CGRect = self.view.frame
frame.origin.x = frame.size.width * CGFloat(1);
frame.origin.y = 0;
self.scrollView!.scrollRectToVisible(frame, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
self.tabBarController?.selectedIndex = 2
}
}
This is the .swift file for the first Viewcontroller that I have, which contains the image I want to fade in when the screen loads.
import UIKit
class AViewController: UIViewController {
#IBOutlet var Background: UIImageView!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
UIView.animateWithDuration(1.5, animations: {
self.Background.alpha = 1.0
})
}
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
}
I looked around for a way to do it and that is why I have the animatedWithDuration, but instead all I am getting is the screen swiping up from the bottom of the phone. Any ideas?
Try setting the alpha to 0.0 before the UIView.animateWithDuration function.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.background.alpha = 0.0
UIView.animateWithDuration(1.5, animations: {
self.background.alpha = 1.0
})
}
Please note that viewDidAppear is not called after you have scrolled to a view in the scrollview. It is called when the view is added to the view hierarchy. You have to manually write the code for making the label appear using scrollView delegate functions if you want to make it appear when you scroll with your fingers or scroll automatically later.
You can do a cross dissolve animation instead of scrolling by doing
CATransaction.flush()
self.scrollView.contentOffset = CGPointMake(self.view.frame.width,0)
UIView.transitionWithView(self.scrollView, duration: 1.0, options:
.TransitionCrossDissolve, animations: { () -> Void in
}) { (finished) -> Void in
}
Either use CATransactionFlush or put the code inside viewDidAppear.
Remove the scrollView.scrollRectToVisible code.