How to have a shared background on a UIScrollView handling multiple ViewControllers? - ios

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.

Related

systemLayoutSizeFitting not returning proper size of view

I'm setting a view controller's view as my UITableView's header.
var headerView = CommunityPostDetailTableHeaderViewController()
override func viewDidLoad() {
// other stuffs
headerView.view.frame = CGRect(x: 0, y: 0, width: self.tableView.frame.size.width, height: 100)
headerView.delegate = self
self.tableView.tableHeaderView = headerView.view
}
And using this bit of code to resize it according to the size of view.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let headerView = tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFitting(CGSize(width: tableView.bounds.width, height: 0)).height
var headerFrame = headerView.frame
// Comparison necessary to avoid infinite loop
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
tableView.tableHeaderView = headerView
}
}
}
I'm using this technique for two of my table views.
tableview is presented directly from a view controller like so :
let playerController = VideoDetailController()
playerController.modalPresentationStyle = .fullScreen
playerController.video = video
self.present(playerController, animated: true, completion: nil)
Working fine in all iOS devices.
the other is presented by embedding inside a navigation controller :
let communityPostDetailVC = CommunityPostDetailViewController()
communityPostDetailVC.delegate = self
if let indexpath = indexpath {
communityPostDetailVC.communityPost = datasource[indexpath.row]
communityPostDetailVC.indexpath = indexpath
}
let navigationController = UINavigationController(rootViewController: communityPostDetailVC)
navigationController.modalPresentationStyle = .fullScreen
self.present(navigationController, animated: true)
Not resizing properly on iPhone 5/5s/SE(1st gen)/6/6s/7/8/SE(2nd gen).
I can't figure out why it is not working on smaller phones. You can see blank space in the comparison attachment below. In smaller SE the space is even more.
Any suggestions/ideas are welcome. I'm clueless at this point.
PS: I've nested view controller's. the headerView is a view controller holding another view controller's view. The FB logo and the pink label underneath is part of the nested view controller. Other than that everything else is in headerView's view controller's view.
you are using fullscreen , but you image is a fixed size image . pink colour view also fixed size.
maybe its making a problem .
its actually not an answer. a suggestion for you. you may review again your code. hope you will find .
happy coding

Custom TabBar layout for UITabBarViewController

Please refer to this Answer.
I am trying to do the same thing, however I want to do this in a Tab Bar App where the Now Playing bar is above the Tab Bar in all the scenes of the app.
Update:
I want to have a view at the bottom of the screen (above the tab bar) and under the content views of the different tabs (not above them). In addition, I want to have the ability to remove this view at a certain point making the main view take the whole screen.
I can do this using the mentioned Answer by changing the constraints of the nowPlaying view programmatically.
Using UITabBarViewController subclass it is possible:
Ex:
class DashBoardViewController: UITabBarController {
let nowPlayingBar:UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .blue
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
initView()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
nowPlayingBar.frame = tabBar.frame
}
override func viewDidAppear(_ animated: Bool) {
var newSafeArea = UIEdgeInsets()
// Adjust the safe area to accommodate
// the height of the bottom views.
newSafeArea.bottom += nowPlayingBar.bounds.size.height
// Adjust the safe area insets of the
// embedded child view controller.
self.childViewControllers.forEach({$0.additionalSafeAreaInsets = newSafeArea})
}
private func initView() {
nowPlayingBar.frame = tabBar.frame
view.addSubview(nowPlayingBar)
}
}
You'll add your view/container to your app window, you'd do something like
guard let window = (UIApplication.shared.delegate as? AppDelegate)?.window
else { return } // check if there's a window
let containerHeight: CGFloat = 50 // height for the view where you wish to add the music player
let containerFrame = CGRect(x:0, y: window.frame.maxY - (tabBar.frame.height + containerHeight), width: window.frame.width, height: containerHeight)
// most important part here is the y axis in some sense, you will add the height of the tabBar and the container, then subtract it from window.frame.maxY
let container = UIView(frame: containerFrame)
// now you have the container do whatever you want with it
window.addSubView(container) // finally add the container to window as a subview

Navigation Bar on Scrollview bartint not on top

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

Views that are loaded in scroll view not sizing correctly

I have 3 views that I'm loading into a scroll view so users can swipe through the app to change views (similar to Snapchat or Tinder navigation). However, I added a horizontally and vertically centered label to one of the nibs and it appears as though the size is much wider than my screen. I have the nib frames set to the size of the device screen.
How can I make the subviews match the frame of the view (full screen)?
Here's what I've got in the viewDidLoad for the view controller with a full screen scroll view in it, as well of a screenshot of the result:
#IBOutlet weak var scrollViewOfViews: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let settingsVC = UIViewController(nibName: "SettingsViewController", bundle: nil)
let friendsFeedVC = UIViewController(nibName: "FriendsFeedViewController", bundle: nil)
let notificationsVC = UIViewController(nibName: "NotificationsViewController", bundle: nil)
let screenSize = UIScreen.mainScreen().bounds
settingsVC.view.frame = screenSize
friendsFeedVC.view.frame = screenSize
notificationsVC.view.frame = screenSize
self.addChildViewController(settingsVC)
self.scrollViewOfViews.addSubview(settingsVC.view)
settingsVC.didMoveToParentViewController(self)
self.addChildViewController(friendsFeedVC)
self.scrollViewOfViews.addSubview(friendsFeedVC.view)
friendsFeedVC.didMoveToParentViewController(self)
self.addChildViewController(notificationsVC)
self.scrollViewOfViews.addSubview(notificationsVC.view)
notificationsVC.didMoveToParentViewController(self)
var friendsFeedFrame = friendsFeedVC.view.frame
friendsFeedFrame.origin.x = self.view.frame.width
friendsFeedVC.view.frame = friendsFeedFrame
var notificationsFrame = notificationsVC.view.frame
notificationsFrame.origin.x = self.view.frame.width * 2
notificationsVC.view.frame = notificationsFrame
self.scrollViewOfViews.contentSize = CGSize(width: self.view.frame.width * 3, height: self.view.frame.size.height)
// start scrollview page on middle view
var startFrame = scrollViewOfViews.frame
startFrame.origin.x = self.view.frame.width
startFrame.origin.y = 0
scrollViewOfViews.scrollRectToVisible(startFrame, animated: false)
}
The result for the friendsFeedVC with a centered Label:
"You should not initialize UI geometry-related things in viewDidLoad, because the geometry of your view is not set at this point and the results will be unpredictable"
"viewWillAppear: is the correct place to do these things, at this point the geometry is set so getting and setting geometry-related properties makes sense."
Or you can set them in viewDidLayoutSubviews
Try to place the codes that set frame of views in viewWillAppear or viewDidLayoutSubviews
Ref: Why am I having to manually set my view's frame in viewDidLoad?

ScrollView on an iOS app in Swift

I have a ViewController and my View is too large, so I'm trying to implement a simple ScrollView but I don't know how to do. I Tried to do Embed in >> ScrollView but it doesn't work.
Add Scrollview in the xib or storyboard file of your VC. Create the view seperately and add it as a subview inside the scrollview. Or you could simply drag it inside the scrollview. Set content size of scrollview to be equal to that view's size. If you still need help, use this tutorial. http://www.raywenderlich.com/76436/use-uiscrollview-scroll-zoom-content-swift
If you need wide screen so here is example how you can make three times wider that usual one.
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let view1: View1 = View1(nibName: "View1", bundle: nil)
addChildViewController(view1)
scrollView.addSubview(view1.view)
view1.didMoveToParentViewController(self)
let view2: View2 = View2(nibName: "View2", bundle: nil)
addChildViewController(view2)
scrollView.addSubview(view2.view)
view2.didMoveToParentViewController(self)
var view2Frame: CGRect = view2.view.frame
view2Frame.origin.x = view.frame.width
view2.view.frame = view2Frame
let view3: View3 = View3(nibName: "View3", bundle: nil)
addChildViewController(view3)
scrollView.addSubview(view3.view)
view3.didMoveToParentViewController(self)
var view3Frame: CGRect = view3.view.frame
view3Frame.origin.x = view.frame.width * 2
view3.view.frame = view3Frame
self.scrollView.contentSize.width = view.frame.width * 3
}
So basically you create scrollView and add here three views and each view has it's new origin point. You can enable or disable paging in storyboard. And that is it!

Resources