How to add padding/Marging to ViewController - ios

I am using SJSegmentedViewController and loading two view controllers in SegmentController, I want to add padding 20 px to both of these controllers but I have tried but not able to achieve it,
If anyone knows how to Customise SJSegmentedViewController, please refer attached screenshot here.
override func viewDidLoad() {
super.viewDidLoad()
let headerViewController = storyboard
.instantiateViewController(withIdentifier: "HeaderViewController1")
let firstViewController = storyboard
.instantiateViewController(withIdentifier: "FirstTableViewController")
firstViewController.title = "First"
let secondViewController = storyboard
.instantiateViewController(withIdentifier: "SecondViewController")
secondViewController.title = "Second"
let segmentController = SJSegmentedViewController()
segmentController.headerViewController = headerViewController
segmentController.segmentControllers = [firstViewController,
secondViewController]
segmentController.headerViewHeight = 300.0
navigationController?.pushViewController(segmentController, animated: true)
}

Based on the implementation of SJContentView, I found that that library is not using a collection view to implement the paginated scroll which contains all view controllers. It's directly using a scroll view. The two function which handles the layout of the view controllers
func addContentView(_ view: UIView, frame: CGRect)
func updateContentControllersFrame(_ frame: CGRect)
do not provide support to add padding in between two views of two adjacent view controllers.
There are two ways, if you want to continue with SJSegmentedViewController
Add padding on your view controller's view rather wishing to have them in between views in the scroll view. Here the usable width of the screen will be reduced.
Create an issue and ask for help.

#user1374 Can you please try the following approach?

Related

SwipeNavigationController framework from GitHub how to implement

so my question today is how can I add a view similar to Snapchat where you use gestures to swipe to other views: left, top, bottom, right. I'm trying to use this framework but I'm not sure how to really implement it as they haven't provided a sample project. The layout of my app is I have a signup/login view controller, from there I want it to go to another view (blue) and that's the view that I want to have the different gestures mentioned above. `import UIKit
import SwipeNavigationController
class BlueViewController: UIViewController {
let orangeVC = OrangeView()
let pinkVC = PinkView()
let greenVC = GreenView()
let purpleVC = PurpleView()
override func viewDidLoad() {
let swipeNavigationController = SwipeNavigationController(centerViewController: self)
swipeNavigationController.topViewController = self.pinkVC
swipeNavigationController.bottomViewController = self.purpleVC
swipeNavigationController.leftViewController = self.greenVC
swipeNavigationController.rightViewController = self.orangeVC
view.backgroundColor = UIColor.facebookBlueColor
}
}'
I'm also not using storyboards for this project.
The SwipeNavigationController is a UIViewController and can be pushed onto a stack or presented the same as any other UIViewController. Wherever you are creating and presenting BlueViewController, you should instead create the SwipeNavigationController as the top level object that contains BlueViewController and all of the direction view controllers. BlueViewController and all of the other directions should not know anything about the SwipeViewController. BlueViewController and all of the other directions should not know anything about each other. The SwipeNavigationController is the top level view controller, all of the view controllers associated with a direction are child view controllers of it. I'm assuming that you have a navigation controller somewhere in your flow that pushes the SwipeNavigationController. In that case, you would have something like this in whatever method you want to trigger the push. I've called it nextTapped, but I'm sure it'll be something different in your code:
func nextTapped() {
let swipeNavigationController = SwipeNavigationController(centerViewController: BlueViewController())
swipeNavigationController.topViewController = PinkViewController()
swipeNavigationController.bottomViewController = PurpleViewController()
swipeNavigationController.leftViewController = GreenViewController()
swipeNavigationController.rightViewController = OrangeViewController()
navigationController?.pushViewController(swipeNavigationController, animated: true)
}
And then remove everything from viewDidLoad in BlueViewController except for the line that sets the background color. This creates the SwipeNavigationController with all of the directional view controllers, keeping the BlueViewController as the center and then pushes it onto your view controller stack. If you don't have a UINavigationController in the view controller that is displayed before the SwipeNavigationController, you can present it modally by replacing the last line with this:
present(swipeNavigationController, animated: true, completion: nil)

add subview over UITableView

First of, I am noob to Swift programming.
I am trying to show a custom view over a UITableView.
I am facing two major issues :
a) The subview does not appear correctly firstly. ref image below :
and after few moments actual view is loaded :
b) After the UITableView is scrolled, the view is not coming over the current top scroll position of UITableView
Following is the code to add subview :
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! AdPopupWithCrossViewController
vaAdPopupViewController.adID = adID
vaAdPopupViewController.tableView = self.tableView
if let message = parseJSON["adv_text"] as? String{
vaAdPopupViewController.message = message
}
let navigationBarFrame: CGRect = (self.navigationController?.view.frame)!
let frameSize = CGRect(x: navigationBarFrame.minX, y: navigationBarFrame.minY, width: navigationBarFrame.width, height: (navigationBarFrame.height - (self.navigationController?.navigationBar.frame.size.height)!))
vaAdPopupViewController.view.frame = frameSize
self.tableView.addSubview(vaAdPopupViewController.view)
vaAdPopupViewController.view.tag = 1000
self.addChildViewController(vaAdPopupViewController)
vaAdPopupViewController.didMove(toParentViewController: self)
also in AdPopupWithCrossViewController :
override func viewDidLoad() {
self.view.superview?.layoutIfNeeded()
self.view.layoutIfNeeded()
super.viewDidLoad()
}
Please guide me how to resolve this issue.
Thank You.
You probably want to either create a Present Modally Segue or use present() via code.
You've already created your AdPopupWithCrossViewController. Set its background color to be translucent. Then you can present it like this:
let vaAdPopupViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AdPopupWithCrossViewController") as! ModalOverTableViewController
vaAdPopupViewController.modalPresentationStyle = .overCurrentContext
self.present(vaAdPopupViewController, animated: true, completion: nil)
Then, your little "X" button can remove the ad with:
#IBAction func closeTapped(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
You can try out the various options on .modalPresentationStyle and .modalTransitionStyle, as well as setting animated to true or false, to get the appearance / behavior you desire.
As Dan says, you should add your popup as a subview of the view controller's view, not of the table view. A Table view's view hierarchy is private and you should not be trying to mess with it.
Note that you can't do this with a table view controller. This has always bugged me, but it's a fact: A UITableViewController manages a single table view and nothing else. If you want a more complex view hierarchy you need to embed your table view controller in another view controller. I do this with a container view and an embed segue, which is very easy.
If you do that then you can add your new view controller's content to the parent view controller's content view, not to the table view controller's view (or to the table view itself)

Toggle ViewController Views

I am learning iOS with few sample projects. I have two view controllers in that first VC has few buttons and a mapview and the second VC has tableview showing a set of results. I have embed the both viewcontrollers in navigationViewController.By clicking a button from First VC i am able to show the tableview (using show segue) and able to go back to first VC through navigation. Now my query is I want to display the tableview (second VC) in place of one view object (map view) defined in firstVC rather than padding the tableview entirely in full screen. My problem is when showing another Viewcontroller i still want to see the few viewobjects from firstVC so I am trying to display the secondVC on top of mapview when i click on a button which triggers the segue.I have to use the single interface, so I need to load the tablview results from SecondVC into firstVC by replacing mapView's view with tableview.Please let me know your ideas if it is possible and any other ideas to achieve the same are most welcomed.
Sreekanth Gundlapalli,
All you need to do is to add the TableView controller's view as subview to your view Controller. In order to simplify the process I personally prefer using the ContainerView,
Step 1 : Add a ContainerView to your View Controller and add the auto layout constraints to it, because your tableView will be loaded inside this container view you donate have to apply any auto layout constraint to your tableView to keep it in place :)
ex :
Step 2 : Drag an IBOutlet to the container view.lets call it as containerView :)
Step 3 : Now its up to you to have two view controller 1 for loading map and 1 for loading tableView, or you will have map view as your view controller subview and you will either hide it or remove it and add container view but I personally prefer having code clean n neat so I prefer having two different VCs
so lets create 2 VCs lets call them as viewController1 & viewController2 Savy ??
Step 4 :
lets write a method which actually loads VC and adds its view as subview to your ViewController
func changeEmbededVC(for status : Int) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if status == 0 {
mehereButton.tag = 1
let vc = storyboard.instantiateViewController(withIdentifier: "viewController1")
vc.willMove(toParentViewController: self)
containerView.addSubview(vc.view)
self.addChildViewController(vc)
vc.didMove(toParentViewController: self)
}
else {
mehereButton.tag = 0
let vc = storyboard.instantiateViewController(withIdentifier: "viewController2")
vc.willMove(toParentViewController: self)
containerView.addSubview(vc.view)
self.addChildViewController(vc)
vc.didMove(toParentViewController: self)
}
}
I believe code is pretty self explanatory :D now what is mehereButton.tag = 1 ?? Simple you want to toggle view on button press don't you :D hence I have created a IBOutlet for mehereButton and changing its tag :)
now finally in IBAction of mehereButton
#IBAction func buttonTapped(_ sender: UIButton) {
self.changeEmbededVC(for: self.mehereButton.tag)
}
but we need to load one of the view by default isn't it :D
so change your viewDidAppear to
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.changeEmbededVC(for: 0)
}
Hope I answered your question In detail :P I know you can't neither up vote or accept answer as you don't have enough reputation :) but hope it will help somebody in future as well :)

How to approach to this design - iOS

My App is Navigation based Application for iPad.
First Screen is Home Screen. On Clicking button on Home Screen, it pushes to Map Screen. On the Map Screen, i have left Panel (view controller) over the map view controller which occupies 1/4 of the screen.
Left Panel is a View Controller which has Table View. On clicking cell, it should push new viewcontroller to left panel leaving the map view controller behind.
Push
Home Screen -------- Map Screen
|(Added over map screen) Push
|----- Left Panel (Table View) -------- Detail View
I can't use Split View Controller because there is a navigation in left panel as well as in Home Screen. Some times i need to animate/hide left panel. I can customise left panel.
How to implement this structure. Is it good to use Nested Navigation Controller or is there any library available. My App supports both Portrait and Landscape. I am using Swift.
I'm sorry, I don't know Swift as well. However, I think you have to declare a base layout:
you will have a MainViewController that will include a LeftPanelViewController and a FrontViewController. In the MainViewController nib, you will create the main layout using AutoLayout: add a UIView at the left of the screen and another UIView for the frontpage.
Then, link outlets and you will have the layout done! Then you have only to add/remove subviews to leftPanelView and to FrontView.
Now, I think that the right logic is that MainViewController is the NavigationController, so you have to implement the protocol of LeftPanelViewController and FrontViewController, so Main will know how and when add/remove subviews.
The important things is that no one object have to know the existence of MainViewController to preserve the logic. So you have to notify MainViewController for something, to use delegation pattern or something else as NSNotification (be aware, it could be much weight...)
I hope it will bel helpful. Bye
I would solve this by adding a ContainerView as your Left Panel. As you want to do pushes here, you can make the container view controller a navigation controller with the table view as its root view controller.
You'll still be able to animate/hide the container view just like any other view.
This extension for the UIViewController creates the side panel to the left.
private var temp_view:UIView?
private var temp_width:CGFloat?
private weak var temp_sidebar:UIViewController?
extension UIViewController {
func configureSideBar(StoryBoard:String,SideBarIdentifier:String,View:UIView){
var storyboard = UIStoryboard(name: StoryBoard, bundle: nil)
weak var sidebar = storyboard.instantiateViewControllerWithIdentifier(SideBarIdentifier) as? UIViewController
let width:CGFloat = 250//sidebar!.view.frame.size.width
let height = UIScreen.mainScreen().bounds.height
let frame = CGRectMake(0, 0, width, height)
temp_view = View
temp_width = width
temp_sidebar = sidebar
sidebar!.view.frame = frame
addChildViewController(sidebar!)
view.addSubview(sidebar!.view)
view.sendSubviewToBack(sidebar!.view)
toogleSideBarWithAnimation(0.2,Open:false)
}
func getSidebar() -> UIViewController?{
if let sdbar = temp_sidebar {
return sdbar
}
else {
println("Warning:You have tou configure sidebar first")
return nil
}
}
func toogleSideBarWithAnimation(Duration:NSTimeInterval,Open:Bool) {
if let view = temp_view {
UIView.animateWithDuration(Duration, delay: 0, options: UIViewAnimationOptions.TransitionFlipFromLeft, animations: {
var Frame = view.frame
if !Open{
Frame.origin.x = 0
}
else {
Frame.origin.x = temp_width!
}
view.frame = Frame
}, completion: { finished in
})
}
else {
println("Warning:You have tou configure sidebar first")
}
}
}
Let me explain how to use it.
First create a view controller scene and set the storyboard id. In this examples i used "sidebar"
Then add this instruction to the map view controller to the viewDidLoad like this
override func viewDidLoad() {
super.viewDidLoad()
self.configureSideBar("Main", SideBarIdentifier: "sidebar", View: Subview)
}
I suggest adding a UIView with all your view in it in the map view controller
To open and close it use this instruction
self.toogleSideBarWithAnimation(0.2,Open:OpenSidebar)

Is it possible to have embed segue/containing view in a scrollview with code?

On an iPhone project I'm using Xcode storyboard to embed a few containing views in a main scroll view. I've heard containing view is also an "embed segue". Now I don't necessarily have to embed other child controllers, I could have just created custom views and have the original child controllers' logic in those custom subviews. (I think I'm just going to do that after posting here, because it seems easier.) But I've already done the code and want to know how easy or hard it is to stay with it.
Because scroll view content is greater than the main screen bounds, it's harder to layout the container view in storyboard. I can think of three ways to solve it. I can either
Drag the scroll view up and down and put my container views there.
Just drag some view in the scroll view, and then resize the frame in the main controller's viewDidLoad. (And if I'm using auto layout then I would add auto layout there) But just seems to defy the advantage of having storyboard and embed segue in the first place. But it seems easier than #3 if I have to interact with child view controllers.
Forget storyboard and just write a Containing controller logic (as described in WWDC 2012 video Implementing UIViewController Containment) but this appears to be complicated.
Is there a way to create embed segue in Xcode, but NOT putting it in but to do something like a "manual segue" as with other view transitions? I wouldn't be able to see the layout in storyboard but at least it'll be easier than #3 and I don't have to drag up and down like #2 which seems silly.
I understand that the WWDC has an hour of video on it. But if you have watched any of their other videos it should become quite clear that time does not directly relate to complexity. This is how you use a container (or a child sub view controller) programmatically:
[self addChildViewController:child]; // 1
[self.view addSubview:child.view]; // 2
[child didMoveToParentViewController:self]; // 3
Pretty simple and only two extra lines of code compared to adding a subview. As you said, there are storyboard solutions but depending on your complexity, doing this through code may be easier. It really comes down to your preference though.
If you intend to animate adding the view, you should make the last call to didMoveToParentViewController in the completion block (i.e. after the animation has been completed).
Here are the helper functions I use to programmatically embed a child view controller in a view.
struct MyChildViewController {
static func embed(
viewControllerId: String,
storyboardName: String,
containerViewController: UIViewController,
containerView: UIView) -> UIViewController? {
guard let viewController = initViewController(viewControllerId, storyboardName: storyboardName)
else { return nil }
containerViewController.addChildViewController(viewController)
containerView.addSubview(viewController.view)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
MyConstraints.fillParent(
viewController.view, parentView: containerView, margin: 0, vertically: true)
MyConstraints.fillParent(
viewController.view, parentView: containerView, margin: 0, vertically: false)
viewController.didMoveToParentViewController(containerViewController)
return viewController
}
static func initViewController(viewControllerId: String, storyboardName: String) -> UIViewController? {
let storyboard = UIStoryboard(name: storyboardName, bundle: NSBundle.mainBundle())
return storyboard.instantiateViewControllerWithIdentifier(viewControllerId)
}
}
struct MyConstraints {
static func fillParent(view: UIView, parentView: UIView, margin: CGFloat = 0,
vertically: Bool) -> [NSLayoutConstraint] {
var marginFormat = ""
if margin != 0 {
marginFormat = "-\(margin)-"
}
var format = "|\(marginFormat)[view]\(marginFormat)|"
if vertically {
format = "V:" + format
}
let constraints = NSLayoutConstraint.constraintsWithVisualFormat(format,
options: [], metrics: nil,
views: ["view": view])
parentView.addConstraints(constraints)
return constraints
}
}
Usage:
let childWiewController = MyChildViewController.embed("MyViewControllerId", storyboardName: "MyStoryboardName", containerViewController: containerViewController, containerView: containerView)
Where:
"MyViewControllerId" - the storyboard ID of the child view controller that will be embedded.
"MyStoryboardName" - the name of the storyboard file with embedded view controller.
containerView - the view in your container view controller that will have the child view controller embedded.

Resources