How to implement video controller like YouTube with rotation to landscape - ios

I want to implement controller like YouTube. Where Top part of controller plays video and bottom remains static. And when user rotate device only Top gets rotates.
I tried to implement it with this code:
#IBOutlet weak var myView: UIView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(self.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
#objc func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
UIView.animate(withDuration: 0.9, animations: {
self.myView.transform = CGAffineTransform(rotationAngle: CGFloat.pi/2)
let rect = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)
self.myView.frame = rect
})
}
}
And I have this result:
Problem is controller still in portrait orientation and status bar at wrong side.
I think that there is better implementation for this thing.
Please, help

This is a simple solution for your problem,
import UIKit
class ViewController: UIViewController {
let RotatingView :UIView = UIView()
let TextLabel :UILabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.RotatingView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: (self.view.frame.size.height/3))
self.RotatingView.backgroundColor = UIColor.black
self.TextLabel.text = "Rotating View"
self.TextLabel.textColor = UIColor.white
self.TextLabel.textAlignment = .center
self.TextLabel.frame = CGRect(x: 0, y: self.RotatingView.frame.size.height/2, width: self.RotatingView.frame.width, height: 20)
self.RotatingView.addSubview(self.TextLabel)
self.view.addSubview(self.RotatingView)
NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func rotated(){
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
self.RotatingView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: (self.view.frame.size.height))
self.TextLabel.frame = CGRect(x: 0, y: self.RotatingView.frame.size.height/2, width: self.RotatingView.frame.width, height: 20)
default:
self.RotatingView.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: (self.view.frame.size.height/3))
self.TextLabel.frame = CGRect(x: 0, y: self.RotatingView.frame.size.height/2, width: self.RotatingView.frame.width, height: 20)
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.setNeedsStatusBarAppearanceUpdate()
}
override var prefersStatusBarHidden : Bool {
return false
}
}

Related

UISegmented Control Inner view should call API after view has been shown

I have a 'UISegmentedControl' which is programatically added in the view controller named SegmentControllForRides. (i added UISegmentedControl programatically because segment items will be changed some time 2 or 3.UISegmentedControl have three items. items names are ["Request","Upcoming", "Past"]. Each segment will show a viewController.view and hide the others. Each view controller have an API call. My problem is when first the SegmentControllForRides shows it calls the all three (child) viewcontroller API's( i think because views are hidden but loaded in controller thats why API calls goes to server). Each view controller has a UITableView and in UITableViewCell there is a UICollectionView. I tried to call (again) API when view is shown, in that case API call goes but UICollectionView got messed. It shows data of the other cell. For this i tried to
DispatchQueue.main.async {
reloadCollectionView()
}
but this does not help.
I want to call API when child view is shown (not on the SegmentControllForRides load). It is also necessary because first controller API response have the effect of the second controller API call. So Kindly guide me how to call API after the view shown.
I will try provide any further detail.
Here is my class.
import UIKit
class SegmentControllForRides: UIViewController {
// MARK: - Variables
var controller: UIViewController!
var requestedRideViewController: RequestedRideViewController!
var upcomingRideViewController: UpcomingRideViewController!
var myRideViewControllerUpcoming: UIViewController!
var myRideViewControllerPast: UIViewController!
var segmentControll: UISegmentedControl!
var sideMenuOpen = false
// MARK: - Outlets
// MARK: - Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
configure()
}
override func viewWillDisappear(_ animated: Bool) {
if sideMenuOpen {
openCloseSideMenu()
}
}
// MARK: - Actions & Events
#IBAction func segmentControllChanged(_ sender: UISegmentedControl) {
if UserDefaults.standard.bool(forKey: User.isAppUsingAsPassenger) {
switch segmentControll.selectedSegmentIndex {
case 0:
print("segment 1")
myRideViewControllerUpcoming.view.isHidden = false
myRideViewControllerUpcoming.didMove(toParent: self)
myRideViewControllerPast.view.isHidden = true
case 1:
print("segment 2")
myRideViewControllerUpcoming.view.isHidden = true
myRideViewControllerPast.view.isHidden = false
myRideViewControllerPast.didMove(toParent: self)
default:
break
}
} else {
switch segmentControll.selectedSegmentIndex {
case 0:
print("segment 1")
requestedRideViewController.view.isHidden = false
requestedRideViewController.didMove(toParent: self)
upcomingRideViewController.view.isHidden = true
myRideViewControllerPast.view.isHidden = true
case 1:
print("segment 2")
requestedRideViewController.view.isHidden = true
upcomingRideViewController.view.isHidden = false
// upcomingRideViewController.getUpcomingRide()
upcomingRideViewController.didMove(toParent: self)
myRideViewControllerPast.view.isHidden = true
// let myClass : UpcomingRideViewController = self.children[1] as! UpcomingRideViewController
// myClass.myRideTableView.reloadData()
// myClass.getUpcomingRide()
// myClass.viewWillAppear(false)
case 2:
print("Segment 3")
requestedRideViewController.view.isHidden = true
upcomingRideViewController.view.isHidden = true
myRideViewControllerPast.view.isHidden = false
myRideViewControllerPast.didMove(toParent: self)
default:
break
}
}
}
#IBAction func sideMenuClicked(_ sender: UIBarButtonItem) {
openCloseSideMenu()
}
#objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
if gesture.direction == .right {
print("Swipe Right")
if !sideMenuOpen {
openCloseSideMenu()
}
} else if gesture.direction == .left {
print("Swipe Left")
if sideMenuOpen {
openCloseSideMenu()
}
}
}
// MARK: - Helper Methods
private func configure() {
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
swipeLeft.direction = .left
self.view.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(handleGesture))
swipeRight.direction = .right
self.view.addGestureRecognizer(swipeRight)
controller = storyboard!.instantiateViewController(withIdentifier: "SideMenuViewController")
if UserDefaults.standard.bool(forKey: User.isAppUsingAsPassenger) {
let segmentItems = ["Upcoming", "Past"]
segmentControll = UISegmentedControl(items: segmentItems)
segmentControll.frame = CGRect(x:0 ,y: 0, width: view.frame.width, height: 30)
segmentControll.addTarget(self, action: #selector(segmentControllChanged), for: .valueChanged)
segmentControll.selectedSegmentIndex = 0
segmentControll.backgroundColor = .rideelyGray
if #available(iOS 13.0, *) {
segmentControll.selectedSegmentTintColor = .rideelyYellow
} else {
// Fallback on earlier versions
}
view.addSubview(segmentControll)
myRideViewControllerUpcoming = storyboard!.instantiateViewController(withIdentifier: "MyRideViewController")
addChild(myRideViewControllerUpcoming)
myRideViewControllerUpcoming.view.frame = CGRect(x: 0, y: 30, width: view.frame.width, height: view.frame.height - 30) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(myRideViewControllerUpcoming.view)
myRideViewControllerUpcoming.didMove(toParent: self)
myRideViewControllerUpcoming.view.frame = CGRect(x: 0 - self.view.frame.width, y: 30, width: view.frame.width, height: view.frame.height - 30)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.myRideViewControllerUpcoming.view.frame = CGRect(x: 0, y: 30, width: self.view.frame.width, height: self.view.frame.height - 30)
}, completion:nil)
myRideViewControllerUpcoming.view.isHidden = false
myRideViewControllerPast = storyboard!.instantiateViewController(withIdentifier: "MyRideViewController")
addChild(myRideViewControllerPast)
myRideViewControllerPast.view.frame = CGRect(x: 0, y: 30, width: view.frame.width, height: view.frame.height - 30) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(myRideViewControllerPast.view)
myRideViewControllerPast.didMove(toParent: self)
myRideViewControllerPast.view.frame = CGRect(x: 0 - self.view.frame.width, y: 30, width: view.frame.width, height: view.frame.height - 30)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.myRideViewControllerPast.view.frame = CGRect(x: 0, y: 30, width: self.view.frame.width, height: self.view.frame.height - 30)
}, completion:nil)
myRideViewControllerPast.view.isHidden = true
} else {
let segmentItems = ["Request","Upcoming", "Past"]
segmentControll = UISegmentedControl(items: segmentItems)
segmentControll.frame = CGRect(x:0 ,y: 0, width: view.frame.width, height: 30)
segmentControll.addTarget(self, action: #selector(segmentControllChanged), for: .valueChanged)
segmentControll.selectedSegmentIndex = 0
segmentControll.backgroundColor = .rideelyGray
if #available(iOS 13.0, *) {
segmentControll.selectedSegmentTintColor = .rideelyYellow
} else {
// Fallback on earlier versions
}
view.addSubview(segmentControll)
requestedRideViewController = (storyboard!.instantiateViewController(withIdentifier: "RequestedRideViewController") as! RequestedRideViewController)
addChild(requestedRideViewController)
requestedRideViewController.view.frame = CGRect(x: 0, y: 30, width: view.frame.width, height: view.frame.height) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(requestedRideViewController.view)
requestedRideViewController.didMove(toParent: self)
requestedRideViewController.view.frame = CGRect(x: 0 - self.view.frame.width, y: 30, width: view.frame.width, height: view.frame.height)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.requestedRideViewController.view.frame = CGRect(x: 0, y: 30, width: self.view.frame.width, height: self.view.frame.height - 30)
}, completion:nil)
requestedRideViewController.view.isHidden = false
upcomingRideViewController = (storyboard!.instantiateViewController(withIdentifier: "UpcomingRideViewController") as! UpcomingRideViewController)
addChild(upcomingRideViewController)
upcomingRideViewController.view.frame = CGRect(x: 0, y: 30, width: view.frame.width, height: view.frame.height - 30) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(upcomingRideViewController.view)
upcomingRideViewController.didMove(toParent: self)
upcomingRideViewController.view.frame = CGRect(x: 0 - self.view.frame.width, y: 30, width: view.frame.width, height: view.frame.height)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.upcomingRideViewController.view.frame = CGRect(x: 0, y: 30, width: self.view.frame.width, height: self.view.frame.height - 30)
}, completion:nil)
upcomingRideViewController.view.isHidden = true
myRideViewControllerPast = storyboard!.instantiateViewController(withIdentifier: "MyRideViewController")
addChild(myRideViewControllerPast)
myRideViewControllerPast.view.frame = CGRect(x: 0, y: 30, width: view.frame.width, height: view.frame.height - 30) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(myRideViewControllerPast.view)
myRideViewControllerPast.didMove(toParent: self)
myRideViewControllerPast.view.frame = CGRect(x: 0 - self.view.frame.width, y: 30, width: view.frame.width, height: view.frame.height - 30)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.myRideViewControllerPast.view.frame = CGRect(x: 0, y: 30, width: self.view.frame.width, height: self.view.frame.height - 30)
}, completion:nil)
myRideViewControllerPast.view.isHidden = true
}
}
private func openCloseSideMenu() {
if sideMenuOpen {
sideMenuOpen = false
controller.removeFromParent()
controller.view.removeFromSuperview()
} else {
sideMenuOpen = true
addChild(controller)
controller.view.frame = CGRect(x: 0, y: 0, width: view.frame.width * 0.8, height: view.frame.height) // or, better, turn off `translatesAutoresizingMaskIntoConstraints` and then define constraints for this subview
view.addSubview(controller.view)
controller.didMove(toParent: self)
controller.view.frame = CGRect(x: 0 - self.view.frame.width, y: 0, width: view.frame.width * 0.8, height: view.frame.height)
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.controller.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.width * 0.8, height: self.view.frame.height)
}, completion:nil)
}
}
}
You need to configure your api calls in segmentControllChanged, there are many ways you can achieve this . One way that will best suit is
You can use flag for each controller to check when the segment is scrolled then only you hit the api explicitly otherwise don't hit it.
1 example for this
CODE -
switch segmentControll.selectedSegmentIndex {
case 1:
print("segment 1")
myRideViewControllerUpcoming.isVisible = true
// call your myRideViewControllerUpcoming api method here
}

Unable to properly animate the frame of a subview within a parent view

I am trying to animate the frame change of a subview within a view. Within the animation block I am setting the size of the subview to half its original width and height. However, when I run the code, the subview unexpectedly started with a larger size and shrunk to its original size instead of becoming half its original size. I am using the code below:
My custom view:
import UIKit
class TestView: UIView {
var testSubview: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.yellow
testSubview = UIView(frame: .zero)
testSubview.backgroundColor = UIColor.red
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
testSubview.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
func testAnimate() {
UIView.animate(withDuration: 3, delay: 0, options: [], animations: { [unowned self] in
self.testSubview.bounds.size = CGSize(width: 50, height: 50)
}, completion: nil)
}
}
My view controller:
import UIKit
class TestViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let testView = TestView()
view.addSubview(testView)
testView.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
testView.center = view.center
testView.layoutIfNeeded()
testView.testAnimate()
}
}
Am I doing something wrongly?
The problem is that your view gets laid out two times, you can check that by printing a debug message inside layoutSubviews().
I would suggest something like this, setting a size variable and use that in both layoutSubviews() and testAnimate():
class TestView: UIView {
var testSubview: UIView!
var mySize = CGSize(width: 100, height: 100)
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.yellow
testSubview = UIView(frame: .zero)
testSubview.backgroundColor = UIColor.red
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
testSubview.frame = CGRect(x: 0, y: 0, width: mySize.width, height: mySize.height)
}
func testAnimate() {
UIView.animate(withDuration: 3, delay: 0, options: [], animations: { [unowned self] in
self.mySize = CGSize(width: 50, height: 50)
self.testSubview.bounds.size = self.mySize
}, completion: nil)
}
}
EDIT: Reformulating my whole answer because there are many things I feel should be changed here.
first of all the difference between setting the bounds of a view and it's frame.
let view = UIView()
view.frame = CGRect(x: 0, y: 0, width: 200, height: 200) // This will set the position and size this view will take relative to it's future parents view
view.bounds = CGRect(x: 50, y: 50, width: 100, height: 100) // This will set position and size of it's own content (i.e. it's background) relative to it's own view
Then comes your testView class variables. Unless you are certain that a variable won't be nil don't use UIView! as the typing, you would end up missing some initialisers and thus your class would not work consistently.
Consider init methods as default values for your variables and you can simply alter them afterwards.
import UIKit
class TestView: UIView {
var testSubview: UIView
override init(frame: CGRect) {
// Initialise your variables before calling super
testSubview = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testSubview.backgroundColor = UIColor.red
super.init(frame: frame)
// Once super is called you can start using class methods or variable such as addSubview or backgroundColor
backgroundColor = UIColor.yellow
addSubview(testSubview)
}
required init?(coder aDecoder: NSCoder) {
testSubview = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
testSubview.backgroundColor = UIColor.blue
super.init(coder: aDecoder)
backgroundColor = UIColor.yellow
addSubview(testSubview)
}
}
now finally to the animation part
import UIKit
class TestView: UIView {
var testSubview: UIView
func testAnimation() {
UIView.animate(withDuration: 3, animations: {
self.testSubview.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) // Simply make the view half its size over 3 seconds
}) { (_) in
UIView.animate(withDuration: 3, animations: {
self.testSubview.transform = CGAffineTransform(scaleX: 1, y: 1) // Upon completion, resize the view back to it's original size
})
}
}
}
or if you really want to use CGRect to do animation on it's position
import UIKit
class TestView: UIView {
var testSubview: UIView
func testAnimation() {
UIView.animate(withDuration: 3, animations: {
self.testSubview.frame = CGRect(x: 0, y: 0, width: 50, height: 50) // use frame not bounds to resize and reposition the frame
}) { (_) in
UIView.animate(withDuration: 3, animations: {
self.testSubview.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
})
}
}
}
you can test the effect of changing the bounds attribute as such
import UIKit
class ViewController: UIViewController {
var testView: TestView!
override func viewDidLoad() {
testView = TestView(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 200)))
testView.bounds = CGRect(x: 50, y: 50, width: 100, height: 100)
testView.clipsToBounds = true
view.addSubview(testView)
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
testView.testAnimation()
}
}
simply play around with clipsToBounds, testView.bounds, testView.subView.frame and testView = TestView(frame: CGRect(x:y:width:height) to see all of this

UIWebView sizeThatFits only works in delegate method

So I use a UIWebView like a UILabel with a UITextBox that changes its text via
#IBAction func textChanged(_ sender: Any){}
I size the UIWebView to the size of its content with a fixed width and a flexible height using
override func viewDidLoad() {
super.viewDidLoad()
label = WebLabel(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 1))
label.delegate = self
label.layer.borderColor = UIColor.black.cgColor
label.layer.borderWidth = 1.0
self.view.addSubview(label)
}
Where WebLabel is a class derived from UIWebView which implements following method :
func set(query: String)
{
let htmlString = makeHTMLString(input: (query))
self.loadHTMLString(htmlString, baseURL: nil)
self.sizeToFit()
}
So with this textChanged I get my desired result :
#IBAction func textChanged(_ sender: Any) {
label.set(query: (sender as! UITextField).text!)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: 1)
let size = label.sizeThatFits(CGSize.zero)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: size.height)
}
But I also want to set a initial html text. I do this using:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
label.set(query: "Hello World !")
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: 1)
let size = label.sizeThatFits(CGSize.zero)
label.frame = CGRect(x: label.frame.origin.x, y: label.frame.origin.y, width: label.frame.width, height: size.height)
}
But that doesn't work. So the code seems to only work when triggered by user in the delegate method. How do I solve this problem ? Thanks a lot for your help !

Activity indicator is not in centered in TableView

I want show activity indicator in TableView with NIB/XIB file, but it shown is not in center, it placed in right side
I do:
override func viewDidLoad() {
super.viewDidLoad()
let actInd: UIActivityIndicatorView = UIActivityIndicatorView()
actInd.frame = CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0)
actInd.center = self.view.center
actInd.hidesWhenStopped = true
actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
self.view.addSubview(actInd)
actInd.startAnimating()
}
This approach works for me.
if let window = UIApplication.shared.keyWindow {
activityIndicator.frame = CGRect(x: window.frame.width/2, y: window.frame.height/2, width: 0, height: 0)
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.white
window.addSubview(activityIndicator)
}
Hope it helps :)
let actInd: UIActivityIndicatorView = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
actInd.frame = CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0)
actInd.hidesWhenStopped = true
actInd.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
self.view.addSubview(actInd)
actInd.startAnimating()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
actInd.center = self.view.center
}
/* Following two functions are acceptable also.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
actInd.center = self.view.center
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
actInd.center = self.view.center
}
*/
You could:
add the UIActivityIndicator in your XIB/Storyboard
set it to hidden (in Storyboard)
create an IBOutlet
toggle spinner.isHidden when ever you want to show/hide it.

How to implement the NavigationBar effect of AppStore ranking list page

I increase the NavigationBar height with the following code
override func viewDidLayoutSubviews() {
setUpSegmentControll()
let view = UIView(frame: CGRect(x: 0, y: 44, width: ScreenWidth, height: 40))
view.backgroundColor = UIColor.init(colorLiteralRed: 89/255, green: 89/255, blue: 89/255, alpha: 1)
segmentControll.center.x = view.center.x
view.addSubview(segmentControll)
self.navigationController?.navigationBar.addSubview(view)
}
But the segment clicked no effect,what's wrong with the code
You need to increase the size of navigation bar. Try below code it works fine
import UIKit
/*extension UINavigationBar {
open override func sizeThatFits(_ size: CGSize) -> CGSize {
var rect = self.frame;
let screenRect = UIScreen.main.bounds
rect.size.width = screenRect.size.width
rect.size.height = 104
return rect.size
}
}*/
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationController!.navigationBar.clipsToBounds = true
}
override func viewDidAppear(_ animated: Bool) {
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 104.0)
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController!.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 64.0)
}
override func viewDidLayoutSubviews() {
let segmentControll = UISegmentedControl(items: ["1","2"])
segmentControll.frame = CGRect(x: 0, y: 5, width: 300, height: 30)
let view = UIView(frame: CGRect(x: 0, y: 64, width: UIScreen.main.bounds.size.width, height: 40))
view.backgroundColor = UIColor.init(colorLiteralRed: 89/255, green: 89/255, blue: 89/255, alpha: 1)
segmentControll.center.x = view.center.x
view.addSubview(segmentControll)
self.navigationController?.navigationBar.addSubview(view)
}
}
You have to increase the height of the navigation bar. Refer the below link to increase the height of the navigation bar
How to increase the height of UINavigationBar?

Resources