I'm working on a project, where I have multiple views on a scrollview.
I can scroll through them horizontally. It works nice!
But I've got a problem with the navigationbars in each views I added to the scrollview.
They are on it (as you can see from the screenshot), but the navigationbar on the top is not filling out everything from the top.
There's this white space, I don't want to have. I would like to have this space in the same blue as the navigationbar has.
Now my question, how can I achieve this?
I added the views with following code to the scrollview:
class ScrollViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let profilView = self.storyboard?.instantiateViewController(withIdentifier: "profilController") as! UIViewController
self.addChildViewController(profilView)
self.scrollView.addSubview(profilView.view)
profilView.didMove(toParentViewController: self)
profilView.view.frame = scrollView.bounds
let testViewTwo = self.storyboard?.instantiateViewController(withIdentifier: "chatController") as! UIViewController
self.addChildViewController(testViewTwo)
self.scrollView.addSubview(testViewTwo.view)
testViewTwo.didMove(toParentViewController: self)
testViewTwo.view.frame = scrollView.bounds
var frame:CGRect = testViewTwo.view.frame
frame.origin.x = self.view.frame.width
testViewTwo.view.frame = frame
self.scrollView.contentSize = CGSize(width: self.view.frame.width * 2, height: self.view.frame.height)
//startposition
//self.scrollView.contentOffset = CGPoint(x: (self.view.frame.width) * 1, y: self.view.frame.height)
}
Thanks for your help!
Set the Navigation Bar Height to 64 and place it "behind" the Status Bar.
Navigation Bar
Related
I’m new in Swift and I tried making UIScrollView that shows view controllers.
Every thing perfect just at iPhone 11 Pro Max the next screen show a little bit on the side:
the orange strip is the next screen
My Code:
//MARK: - outlets
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var scrollView: UIScrollView!
//MARK: - properties
var viewControllers: [String] = ["ComputerViewController", "AttactViewController", "DefenceViewController", "OfflineViewController"]
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
//MARK: - life cyrcles
override func viewDidLoad() {
super.viewDidLoad()
for index in 0..<viewControllers.count {
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
let view = UIView(frame: frame)
let storyboard = UIStoryboard(name: "Menu", bundle: nil)
var controller: UIViewController = storyboard.instantiateViewController(withIdentifier: viewControllers[index]) as UIViewController
view.addSubview(controller.view)
self.scrollView.addSubview(view)
}
scrollView.contentSize = CGSize(width: scrollView.frame.size.width * CGFloat(viewControllers.count), height: scrollView.frame.size.height)
scrollView.delegate = self
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pageControl.currentPage = Int(pageNumber)
}
thanks for helping...
A couple of observations:
You should avoid referencing frame in viewDidLoad. At this point, the frame is not known.
You should avoid hard-coding the size and placement of the subviews at all. There can be a variety of events that change the view’s size later on (e.g. rotations, split view multitasking, etc.). Use constraints.
With scroll views, there are two layout guides, one for its frame and another for its contentSize. So set the size of the subviews using the frameLayoutGuide and the placement of these subviews relative to the contentLayoutGuide.
When you add a view controller’s view as a subview, make sure you call addChild(_:) and didMove(toParent:) calls for view controller containment. See “Implementing a Container View Controller” section of the view controller documentation.
If you want to add paging behavior, just set isPagingEnabled of the scroll view.
Pulling that all together:
override func viewDidLoad() {
super.viewDidLoad()
addChildViews()
}
override func viewDidLoad() {
super.viewDidLoad()
var anchor = scrollView.contentLayoutGuide.leadingAnchor
for identifier in viewControllers {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let child = storyboard.instantiateViewController(withIdentifier: identifier)
addChild(child) // containment call
child.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(child.view)
child.didMove(toParent: self) // containment call
NSLayoutConstraint.activate([
// define size of child view (relative to `frameLayoutGuide`)
child.view.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor),
child.view.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),
// define placement of child view (relative to `contentLayoutGuide`)
child.view.leadingAnchor.constraint(equalTo: anchor),
child.view.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
child.view.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
])
anchor = child.view.trailingAnchor
}
anchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor).isActive = true
scrollView.isPagingEnabled = true
}
I’ve eliminated the property frame as that’s not needed anymore (and is just a source of confusion with the view controller’s view’s property of the same name). I’ve also eliminated the container view as it didn’t add much to the overall solution (and only adds a layer of constraints to add).
But the key is to use constraints to dictate the size and position of the subviews within the scroll view and to use view controller containment API.
I would like to have a horizontal scroll layout which displays images. It works fine if setup 0, 0, 0 and 0 the constraints of the UIScrollView. The problem is exactly when I change the constraints to make margins surrounded the UIScrollView. This is what happens:
First image in the UIScrollView
Second image in the UIScrollView
Third image in the UIScrollView
As you can see, each time you scroll, more off-center the current page is.
I have tried to subtract trailing and leading constrains constants to the width of the scrollLayout, play with frames and bouds but without success.
If I run this example in a smaller display like iphone 5S, the problem is more pointed.
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var pageController: UIPageControl!
#IBOutlet weak var scrollView: UIScrollView!
let imagesArray = ["b_1", "b_2", "b_3", "b_4", "b_5"]
override func viewDidLoad() {
super.viewDidLoad()
self.scrollView.isPagingEnabled = true
self.pageController.numberOfPages = imagesArray.count
self.pageController.pageIndicatorTintColor = UIColor.blue
self.pageController.currentPageIndicatorTintColor = UIColor.gray
for i in 0...imagesArray.count - 1{
let imageView = UIImageView()
imageView.contentMode = .scaleToFill
imageView.image = UIImage(named: self.imagesArray[i])
let xPos = CGFloat(i)*self.view.bounds.size.width
imageView.frame = CGRect(x: xPos, y: 0, width: view.frame.size.width, height: self.scrollView.frame.size.height )
self.scrollView.contentSize.width = view.frame.size.width*CGFloat(i+1)
self.scrollView.addSubview(imageView)
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let page = scrollView.contentOffset.x/scrollView.frame.width
self.pageController.currentPage = Int(page)
}
}
So, I would like to know how to always obtain the current image centered.
Thank you
EDITED with Rajesh results and view debug:
I would recommend using a UICollectionView in place of a UIScrollView - otherwise you will be building a lot of the basics from scratch. You can use a collection view that centers the images, make sure paging is enabled and you should get the interface you're looking for. Make sure to adopt / conform to the UICollectionViewDelegate & UICollectionViewDelegateFlowLayout protocols with your view controller & set those delegates on your collection view. Hope that helps! Best of luck.
Sorry in advance, this is a long question but I wanted to explain as good as I can.
I need to implement a walkthrough(first time launch guide) for the project, which will only be shown to user for the first time they launch the app.
I've implemented it by creating a .xib file, where I was just creating a view for each item I need to implement for the walkthrough by creating objects referring to .xib model.
But now I'm required to implement it without using .xib files, where I need to do it via storyboard. This time I've inserted a scrollView, and then I put another view inside it with the objects I'm going to need such as (labels,imageViews,buttons etc.) But it doesn't work, even though I can create all the objects by copying the view right under the scrollView. When I try to expand the width of the scrollView with all the views created so I can do paging, it doesn't create each view next to each other but only shows me the last object(view) in the simulator as they add up vertically, and I can't do no paging.
Now I provide some sample code to show how I try to implement this:
import UIKit
class DenemeViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var repeatingView: UIView!
var viewArray = [UIView]()
override func viewDidLoad() {
super.viewDidLoad()
let temporaryView = repeatingView
temporaryView?.backgroundColor = .black
viewArray.append(temporaryView!)
let temporaryViewTwo = repeatingView
temporaryViewTwo?.backgroundColor = .blue
viewArray.append(temporaryViewTwo!)
pageControl.numberOfPages = viewArray.count
pageControl.currentPage = 0
view.bringSubview(toFront: pageControl)
setupScrollView(items: viewArray)
}
func setupScrollView(items: [UIView]) {
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(items.count), height: view.frame.height)
scrollView.isPagingEnabled = true
for i in 0..<items.count {
items[i].frame = CGRect(x: view.frame.width * CGFloat(i), y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(items[i])
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
pageControl.currentPage = Int(pageIndex)
}
}
As you can see I first create two different views in viewDidLoad by referring to "repeatingView" which is the outlet of the view inside scrollView on the storyboard. Then I return them in an array and try to implement scrollView's subviews with views.
I was expecting to see the scrollView starting with the view with black background and as I do the paging through right then the view with blue background should appear.
When I run this what I see is only the blue view, and I'm unable to do any paging or scrolling.
I want to make 1 UIScrollView that has inside of it 1 background which can be used by multiple ViewControllers. When the user scrolls to the next ViewController, the background should scroll with it. This is my code:
override func viewDidLoad() {
super.viewDidLoad()
let leftViewController: StartLeftViewController = StartLeftViewController(nibName: "StartLeftViewController", bundle: nil)
self.addChildViewController(leftViewController)
self.theScrollView.addSubview(leftViewController.view)
leftViewController.didMove(toParentViewController: self)
let middleViewController: StartMiddleViewController = StartMiddleViewController(nibName: "StartMiddleViewController", bundle: nil)
self.addChildViewController(middleViewController)
self.theScrollView.addSubview(middleViewController.view)
middleViewController.didMove(toParentViewController: self)
let rightViewController: StartRightViewController = StartRightViewController(nibName: "StartRightViewController", bundle: nil)
self.addChildViewController(rightViewController)
self.theScrollView.addSubview(rightViewController.view)
rightViewController.didMove(toParentViewController: self)
var middleFrame : CGRect = middleViewController.view.frame
middleFrame.origin.x = self.view.frame.width
middleViewController.view.frame = middleFrame
var thirdFrame : CGRect = rightViewController.view.frame
thirdFrame.origin.x = 2 * self.view.frame.width
rightViewController.view.frame = thirdFrame
self.theScrollView.contentSize = CGSize(width: self.view.frame.width * 3, height: self.view.frame.height)
theScrollView.contentOffset.x = view.frame.width
}
I already tried setting a background in the middleViewController which has an width of 3x, but I got problems adding elements to left/right ViewController causing the elements hiding behind the background. Thank you.
In your storyboard you can place three Container Views into your scroll view, one after each other horizontally, and connect each of them with Embed segue to your corresponding view controllers.
I am adding my intro screens in a scrollview.So I have to scroll horizontally only.I have set constraints for scrollview(top, bottom.leading, trailing).I have added subviews like the following
for i in 0..<self.arrIntro.count{
let view = IntroScreenView.instanceFromNib()
let x = CGFloat(i) * self.scrollIntro.frame.size.width
view.frame = CGRect(x: x, y: 0, width: self.scrollIntro.frame.size.width, height: self.scrollIntro.frame.size.height)
print(view,self.scrollIntro)
view.imgIntro.image = UIImage(named: "image-1")//UIImage(contentsOfFile: self.arrIntro[i]["Link"] as! String)
print(self.arrIntro[i]["Link"] as! String)
self.scrollIntro.addSubview(view)
}
self.scrollIntro.contentSize = CGSize(width: (CGFloat(self.arrIntro.count) * self.scrollIntro.frame.size.width ) , height: self.scrollIntro.frame.size.height)
but my scrollview is vertically scrolling little bit.How should I avoid this.Any autolayout issue?
You're not adding any constraints to your views. Add height and width constraints to each item, constraints between the views and constraints from the views to the scroll view. Note that the constraints between the Su views and the scroll view will set the content size for you.
Scroll view scrolls vertically, when contentSize.height is greater than the scrollView height.
Just make sure, your contentSize.height is not greater than the scrollView.frame.size.height.
One reason, that I could guess is that, you might be setting contentSize a point after which the frames of the scroll view changes. You should move setting you contentSize in viewDidLayoutSubviews()
Sample : This code makes vertical scroll
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.contentSize = CGSize(width: self.scrollView.bounds.width*5, height: self.scrollView.frame.height)
}
}
And this does not
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet var scrollView: UIScrollView!
override func viewDidLayoutSubviews() {
scrollView.contentSize = CGSize(width: self.scrollView.bounds.width*5, height: self.scrollView.frame.height)
}
}