Swift add Custom View to screen with UIApplication.shared.keyWindow?.addSubview - ios

hope this is an easy one...
I am in a empty new project.
I have added a custom view called MyCustomView:
import UIKit
public class MyCustomView: UIView{
private var littleView: UIView!
open class func show() -> UIView{
let bigView = MyCustomView()
bigView.configureView()
UIApplication.shared.keyWindow?.addSubview(bigView)
return bigView
}
private func configureView(){
let screenSize = UIScreen.main.bounds.size
self.frame = CGRect(x: 0,
y: 0,
width: screenSize.width,
height: screenSize.height)
littleView = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100))
littleView.backgroundColor = .black
addSubview(littleView)
}
}
In the ViewController doing this:
override func viewDidLoad() {
let test = MyFirstView.show()
}
I hoped this will present the view, but I still have to use self.view.addSubview(test) to see it....
I thought with UIApplication.shared.keyWindow?.addSubview(bigView) and adding a subView to it, it should present the View.
What am I missing?

Add the subview in viewDidAppear
override func viewDidAppear() {
let test = MyFirstView.show()
}

Related

UITapGestureRecognizer not working with custom view class

UITapGestureRecognizer works perfectly fine in code 1. tapAction is called as expected.
However it's not working in code 2. Can somebody please tell me what's wrong in code 2?
(This and this are quite similar questions, but still couldn't figure it out) 🧐
Code 1:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myView : UIView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
myView.backgroundColor = .red
myView.addGestureRecognizer( UITapGestureRecognizer(target:self,action:#selector(self.tapAction)) )
self.view.addSubview(myView)
}
#objc func tapAction() {
print("tapped")
}
}
Code 2:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myView = MyView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
self.view.addSubview(myView)
}
}
class MyView : UIView {
override init(frame: CGRect) {
super.init(frame: frame)
initView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func initView(){
let myView : UIView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
myView.backgroundColor = .red
myView.addGestureRecognizer(UITapGestureRecognizer(target:self,action:#selector(self.doSomethingOnTap)))
addSubview(myView)
}
#objc func doSomethingOnTap() {
print("tapped")
}
}
You're creating a subview that in this particular case goes out of the parent bounds because the view main view has 100 height and 100 width and the subview is placed at x: 100 and y: 100, resulting to be positioned at the exact end of the parent.
The subview you create in initView should have (x: 0, y: 0) origin.

how to append child view controller in specific view with fixed height

I'm getting problem in size while adding child view controller
XIB veiw :
class StoreDetailView: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
func addChild(vc: UIViewController){
let v = StoreDetailView(nibName: "StoreDetailView", bundle: nil)
v.view.frame = CGRect(x: 0, y: 0, width: vc.view.frame.width, height: 80)
appendAbleView.addSubview(v.view)
vc.addChild(v)
heightOfAppendAbleView.constant = 80
_scrollView.updateContentView()
}
Output what i'm getting:
Height is not working here :
v.view.frame = CGRect(x: 0, y: 0, width: vc.view.frame.width, height: 80)
i need to show it in grey view which height 80 heightOfAppendAbleView.constant = 80
Only addChild is not enough. Let's try this extension
extension UIViewController {
// Add a child view controller, its whole view is embeded in the containerView
public func addController(controller: UIViewController, containerView: UIView) {
if let parent = controller.parent, parent == self {
return
}
addChild(controller)
controller.view.frame = CGRect.init(origin: .zero, size: containerView.frame.size)
controller.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
containerView.addSubview(controller.view)
controller.didMove(toParent: self)
}
}

When inheriting UIView and creating an instance for the new class, it does not create a view

I have created a new class inheriting UIView. When I create an instance of the new class, the view does not seem to be created.
This is my class.
class QuestionView: UIView {
var metrics : [String : CGFloat] = [:]
override init(frame : CGRect){
super.init(frame: frame)
self.backgroundColor = UIColor.blue
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here I have created an instance of this class to have the following values
x = 0, y = middle of the screen, width = as wide as the screen,
height = 400
class mainView : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var questionView = QuestionView(frame: CGRect(x: 0, y: self.view.frame.height/2, width: self.view.frame.width, height: 400))
self.view.addSubView(questionView)
}
}
I find no view being created.
Add subview(questionView) in mainView class in viewDidLoad method.
self.view.addSubview(questionView)
you can also test the view by setting the background color
questionView.backgroundColor = UIColor.red
You should add all views created programmatically in viewDidLayoutSubView like below
override func viewDidLayoutSubviews() {
var questionView = QuestionView(frame: CGRect(x: 0, y: self.view.frame.height/2, width: self.view.frame.width, height: 400))
self.view.addSubView(questionView)
}
Try following code to get the view in front, use bringSubviewToFront function.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let questionView = QuestionView(frame: CGRect(x: 0, y: self.view.frame.height/2, width: self.view.frame.width, height: 400))
self.view.addSubview(questionView)
self.view.bringSubviewToFront(questionView)
}

How do I programmatically change the height of a navigationBar in Swift?

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let height = CGFloat(84)
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: height)
}
This code simply inserts space above the titleView. A custom titleView at point (0,0) has ~20 points of space above it. A height >40 starts to run off the navBar.
You can subclass UINavigationBar :
class CustomNavigationBar: UINavigationBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
let newSize :CGSize = CGSize(width: self.frame.size.width,height: 84)
return newSize
}
}
Then create the navigation controller and use the initialiser to use your custom navigation bar class.
let nav = UINavigationController(navigationBarClass:CustomNavigationBar.self,toolbarClass: nil)
All existing behavior for UINavigationBar is preserved and your custom height is adopted.
OR
Like you already tried :
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 84 //whatever height you want
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
OR :
You can try this solution Changing the height of the Navigation bar iOS Swift
you can use a custom view to replace the navigation bar.This is more easy and flexible. hide the navi bar and implement a custom view.
class ViewController : UIViewController {
var navBar: UINavigationBar = UINavigationBar()
override func viewDidLoad() {
super.viewDidLoad()
self.setCustomNavBarView()
}
func setCustomNavBarView() {
self.navBar.frame = CGRect(x: 0, y: 0, width: 350, height: 50) // Set you custom width and Height
self.navBar.backgroundColor = UIColor.gray
self.view.addSubview(navBar)
}
}
A simple tutorial on how to do that:
Hope this helps!!
class ViewController: UIViewController {
var navBar: UINavigationBar = UINavigationBar()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.setCustomNavBarView()
}
`func setCustomNavBarView() {
self.navBar.frame = CGRect(x: 0, y: 0, width: 350, height: 100) // Set you custom width and Height
self.navBar.backgroundColor = UIColor.gray
self.view.addSubview(navBar)
}
`
swift 3 updated code here

IOS8 and Swift multiple views with gestures dont work

I'm trying to build a user interface based on generic classes which are based on the same extension of the UIViewController class. This example puts squares on the screen and the tap event would be dealt with in the parent class, but it doesnt work. What am I doing wrong?
Main ViewController.swift:
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//FIRST SQUARE
let widget1 = TestWidget()
widget1.viewX = 10
widget1.viewY = 10
self.view.addSubview(widget1.view)
self.addChildViewController(widget1)
widget1.didMoveToParentViewController(self)
//SECOND SQUARE
let widget2 = TestWidget()
widget2.viewX = 100
widget2.viewY = 100
self.view.addSubview(widget2.view)
self.addChildViewController(widget2)
widget2.didMoveToParentViewController(self)
}
}
Here is the TestWidget class:
class TestWidget : UIViewController {
var viewX : CGFloat!
var viewY : CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
let square = UIView()
square.frame = CGRect(x : viewX, y : viewY, width: 50, height: 50)
square.backgroundColor = UIColor.orangeColor()
self.view.addSubview(square)
//GESTURE PART
var tapForSquare = UITapGestureRecognizer()
tapForSquare.addTarget(self, action : "onTap")
square.addGestureRecognizer(tapForSquare)
square.userInteractionEnabled = true
square.multipleTouchEnabled = true
}
func onTap() {
println("square tapped")
}
}
I have both squares on the screen but the tap action only works on the second one. Is there any problem with this?
onTap() takes an argument. It should be:
onTap(gestureRecognizer: UITapGestureRecognizer)
and add a colon after "onTop" in this line:
tapForSquare.addTarget(self, action : "onTap")
Thanks everyone, it seems interestingly this works only if you set the parent views frame as well.
So something like:
override func viewDidLoad() {
super.viewDidLoad()
self.view.frame = CGRect(x : viewX, y : viewY, width: 50, height: 50)
let square = UIView()
square.frame = CGRect(x : 0, y : 0, width: 50, height: 50)
square.backgroundColor = UIColor.orangeColor()
self.view.addSubview(square)
...
}

Resources