ScrollView paging - ios

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.

Related

UIScrollView paging layout on iPad and iPhone

I am making an universal demo xcode project which is a UIScrollView contains two pages, scroll left and right to go back and forth.
My questions is iPad and iPhone's layout is not the same.
I created 3 view controllers in storyboard as below:
ViewController has the UIScrollView.
AViewController contains an UILabel in the center("Good morning...").
BViewController contains an UILabel in the center("Good night...").
The constraints of the UILabels are:
Here is the code of ViewController:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let story = UIStoryboard(name: "Main", bundle: nil)
let vc1 = story.instantiateViewController(withIdentifier: "AViewController")
let vc2 = story.instantiateViewController(withIdentifier: "BViewController")
vc1.view.backgroundColor = UIColor.green
vc2.view.backgroundColor = UIColor.red
addContentView([vc1, vc2])
scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width * 2, height: scrollView.frame.height)
}
func addContentView(_ viewControllers: [UIViewController]) {
viewControllers.enumerated().forEach {
addChildViewController($1)
$1.view.frame = CGRect(x: UIScreen.main.bounds.width * CGFloat($0), y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
scrollView.addSubview($1.view)
didMove(toParentViewController: $1)
}
}
}
If I choose View as iPhone 8 then the layout works correct in iPhone 8 like this: (Swipe then from green to red)
But for iPad:
The labels are not centered!!.
If I choose View as iPad ... ,then for iPhone it doesn't layout correct.
Here is the view hierarchy, it's obvious the layout is correct but for some reason the green view is larger than screen size and covered by the red one.
Thanks for any help.
The code is here: https://github.com/williamhqs/TestLayout
The embedded view controller views have translatesAutoresizingMaskIntoConstraints = true by default which introduces bogus constraints:
Setting it to false will not let you just set the frame manually, so you will have to write the full layout. It's slightly more verbose, but autolayout will work for the embedded view controllers and you get rotation support as well:
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let story = UIStoryboard(name: "Main", bundle: nil)
let vc1 = story.instantiateViewController(withIdentifier: "AViewController")
let vc2 = story.instantiateViewController(withIdentifier: "BViewController")
vc1.view.backgroundColor = UIColor.green
vc2.view.backgroundColor = UIColor.red
addContentView([vc1, vc2])
}
func addContentView(_ viewControllers: [UIViewController]) {
var previousController: UIViewController? = nil
viewControllers.forEach {
addChildViewController($0)
$0.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview($0.view)
$0.view.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
$0.view.heightAnchor.constraint(equalTo: scrollView.heightAnchor).isActive = true
if let trailing = previousController?.view.trailingAnchor {
$0.view.leadingAnchor.constraint(equalTo: trailing).isActive = true
} else {
$0.view.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
}
$0.view.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
$0.view.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
didMove(toParentViewController: self)
previousController = $0
}
previousController?.view.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
}
Scroll view works as expected for all devices, regardless of the Xcode View as setting:

How do make a UIScrollview only show one subview at a time

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
// ...
}

How to fix current page does not display true? [Swift]

Why my current page in Page Control does not show correct output?
Page 1 and Page 2 display in one dot? Images here:
http://i.stack.imgur.com/498ap.png, http://i.stack.imgur.com/41kdg.png
Last page is page 6 display in dot 5th, doesn't last dot? Image: http://i.stack.imgur.com/NP9u1.png
My code here:
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
let totalPages = 6
let sampleBGColors: Array<UIColor> = [UIColor.redColor(), UIColor.yellowColor(), UIColor.greenColor(), UIColor.magentaColor(), UIColor.orangeColor(), UIColor.lightGrayColor()] #IBOutlet weak var scrollView: UIScrollView!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
configureScrollView()
configurePageControl()
}
func configureScrollView() {
// Enable paging.
scrollView.pagingEnabled = true
// Set the following flag values.
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.scrollsToTop = false
// Set the scrollview content size.
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * CGFloat(totalPages), scrollView.frame.size.height)
// Set self as the delegate of the scrollview.
scrollView.delegate = self
// Load the TestView view from the TestView.xib file and configure it properly.
for i in 0 ..< totalPages {
// Load the TestView view.
let testView = NSBundle.mainBundle().loadNibNamed("TestView", owner: self, options: nil)[0] as! UIView
// Set its frame and the background color.
testView.frame = CGRectMake(CGFloat(i) * scrollView.frame.size.width, scrollView.frame.origin.y, scrollView.frame.size.width, scrollView.frame.size.height)
testView.backgroundColor = sampleBGColors[i]
// Set the proper message to the test view's label.
let label = testView.viewWithTag(1) as! UILabel
label.text = "Page #\(i + 1)"
// Add the test view as a subview to the scrollview.
scrollView.addSubview(testView)
}
}
func configurePageControl() {
// Set the total pages to the page control.
pageControl.numberOfPages = totalPages
// Set the initial page.
pageControl.currentPage = 0
}
// MARK: UIScrollViewDelegate method implementation
func scrollViewDidScroll(scrollView: UIScrollView) {
// Calculate the new page index depending on the content offset.
let currentPage = floor(scrollView.contentOffset.x / UIScreen.mainScreen().bounds.size.width);
// Set the new page index to the page control.
pageControl.currentPage = Int(currentPage)
}
// MARK: IBAction method implementation
#IBAction func changePage(sender: AnyObject) {
// Calculate the frame that should scroll to based on the page control current page.
var newFrame = scrollView.frame
newFrame.origin.x = newFrame.size.width * CGFloat(pageControl.currentPage)
scrollView.scrollRectToVisible(newFrame, animated: true)
}
Please help me! Thank you.
Sorry for my English is bad.
Change the pageControl.currentPage in UIScrollViewDelegate's implemention scrollViewDidEndScrollingAnimation and scrollViewDidEndDecelerating, and I improved the calculation with scrollView's width, not screen's width:
// MARK: UIScrollViewDelegate method implementation
func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
// Calculate the new page index depending on the content offset.
let currentPage = floor(scrollView.contentOffset.x / scrollView.bounds.size.width)
// Set the new page index to the page control.
pageControl.currentPage = Int(currentPage)
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView){
scrollViewDidEndScrollingAnimation(scrollView)
}

UIPageviewController inside a UIScrollView

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.

Swift Fade In Animation for Background Animation between A Single View to a PageView Controller

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.

Resources