UITextField not responds to touch events when added to UIView - ios

I have an issue with UITextField that do not respond to the touch events when it's added to ContainerView. When I try to add UITextField to the main UIViewController it seems to be fine and it responds (keyboard is showing).
I tried to bring the subview to the front, enabled user interaction on ContainerView - nothing helped.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.scrollView = UIScrollView()
self.containerView = UIView()
self.scrollView.delegate = self
self.containerView.userInteractionEnabled = true
self.scrollView.addSubview(containerView)
self.view.addSubview(scrollView)
registerForKeyboardNotifications()
setupGesturesAndMap()
setupActivityIndicator()
setupCircleButton()
setupBrowseTextField()
// Initializing status
status = Status.Init
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = self.view.bounds
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
}
and there is function responsible for setup of browseTextField:
func setupBrowseTextField() {
// Setup of browseTextField
browseTextField = UITextField(frame: CGRectMake(10, self.view.frame.height / 2, self.view.frame.width - 20, self.view.frame.height / 12))
browseTextField.placeholder = "Enter your destination here"
browseTextField.font = UIFont.systemFontOfSize(15)
browseTextField.borderStyle = UITextBorderStyle.RoundedRect
browseTextField.autocorrectionType = UITextAutocorrectionType.No
browseTextField.keyboardType = UIKeyboardType.Default
browseTextField.returnKeyType = UIReturnKeyType.Done
browseTextField.clearButtonMode = UITextFieldViewMode.WhileEditing
browseTextField.contentVerticalAlignment = UIControlContentVerticalAlignment.Center
browseTextField.delegate = self
containerView.addSubview(browseTextField)
}
Would anyone of you have any suggestions?

I see you have set the frame of the containerView as
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
scrollView.contentSize.width is 0.
This solves your problem.
containerView.frame = self.view.bounds
Also your can give the containerView size by the frame size of the scrollView as
containerView.frame = CGRectMake(0, 0, scrollView.frame.width, scrollView.frame.height)

Related

autoresizingMask not working as expected for UITableView.tableHeaderView's subview

I'm adding a header view to my UITableView and want to add a subview to it having some margins.
class ViewController: UIViewController {
private let tablewView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
tablewView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tablewView)
[
tablewView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
tablewView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
tablewView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tablewView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
].forEach{ $0.isActive = true}
let headerView = UIView(frame: CGRect(x: 0, y: 120, width: 200, height: 100))
headerView.backgroundColor = .blue
let subView = UIView(frame: CGRect(x: 10, y: 10, width: 180, height: 80))
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
subView.backgroundColor = .yellow
headerView.addSubview(subView)
tablewView.tableHeaderView = headerView
}
}
The problem is that the right margin isn't preserved when the header is resized (when the table view is laid out). As you can see on the image, the right margin is missing:
If I'm using the same view without UITableView, then the margin is preserved as expected.
Is it a UIKit bug? Are there any workarounds?
I know that I can try AutoLayout solutions from here Is it possible to use AutoLayout with UITableView's tableHeaderView? but they're looking a bit hacky. autoresizingMask is supposed to work, after all.
In Cocoa programming as in comedy, timing is everything.
Add the subview in a one-time implementation of viewDidLayoutSubviews and all will be well. The subview will appear correctly, and will continue working if the table view is resized (e.g. due to rotation of the interface).
So, cut these four lines:
let subView = UIView(frame: CGRect(x: 10, y: 10, width: 180, height: 80))
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
subView.backgroundColor = .yellow
headerView.addSubview(subView)
And instead:
var didLayout = false
override func viewDidLayoutSubviews() {
guard !didLayout else { return }
didLayout.toggle()
if let h = tablewView.tableHeaderView {
let subView = UIView(frame: h.bounds.insetBy(dx: 10, dy: 10))
subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
subView.backgroundColor = .yellow
h.addSubview(subView)
}
}

How to set the frame of a ViewController without storyboard

I want to create a view (e.g. 100x100) with ViewController without using the storyboard. I am wondering what the best way to declare the frame of the ViewController is.
I tried:
class MyLittleViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
}
And I tried to see this view on my MainViewController:
override func viewDidLoad() {
super.viewDidLoad()
let myLittleView = MyLittleViewController()
myLittleView.willMove(toParent: self)
myLittleView.view.translatesAutoresizingMaskIntoConstraints = false
myLittleView.view.backgroundColor = .red
view.addSubview(myLittleView.view)
// enable auto-sizing (for example, if the device is rotated)
myLittleView.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addChild(myLittleView)
myLittleView.didMove(toParent: self)
myLittleView.view.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
myLittleView.view.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
It doesn't work like I expected because the little view doesn't appear on the main view. Any hints?
You shouldn't mix frame layout with auto-layout set a width & height constraints also
NSLayoutConstraint.activate([
myLittleView.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
myLittleView.view.centerYAnchor.constraint(equalTo: view.centerYAnchor),
myLittleView.view.heightAnchor.constraint(equalToConstant:100),
myLittleView.view.widthAnchor.constraint(equalToConstant:100)
])
OR
myLittleView.view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
myLittleView.view.center = view.center
OR
override func loadView() {
view = UIView()
view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
Edit:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
let myLittleView = MyLittleViewController()
myLittleView.willMove(toParent: self)
myLittleView.view.backgroundColor = .red
view.addSubview(myLittleView.view)
// enable auto-sizing (for example, if the device is rotated)
myLittleView.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addChild(myLittleView)
myLittleView.didMove(toParent: self)
myLittleView.view.center = view.center
}
}
class MyLittleViewController: UIViewController {
override func loadView() {
view = UIView()
view.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
}
}
Another way to set frame of the view controller is override method loadView() and set the view frame like this
func loadView() {
view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
}

Why am I unable to interact with my Button? Swift

I have the code below. I added a button and want something to happen when I press it, but it doesn't seem to work. In this case I want the system to print out "hi" and "hey". I can't seem to figure out the problem. Any help would be appreciated.
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var containerView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
var buttonOne: UIButton!
buttonOne = UIButton(type: UIButtonType.System)
buttonOne.setTitle("Level 1", forState: UIControlState.Normal)
buttonOne.frame = CGRectMake(10, 50, 100, 100)
buttonOne.backgroundColor = UIColor.blueColor()
buttonOne.titleLabel?.font = UIFont.systemFontOfSize(17)
buttonOne.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
buttonOne.addTarget(self, action: Selector("clicked:"), forControlEvents: UIControlEvents.TouchUpInside)
self.scrollView = UIScrollView()
self.scrollView.delegate = self
self.scrollView.contentSize = CGSizeMake(0, 1000)
containerView = UIView()
scrollView.addSubview(containerView)
view.addSubview(scrollView)
containerView.addSubview(buttonOne)
}
func clicked(sender: AnyObject){
NSLog("Hey")
print("hi")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.frame = view.bounds
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You have put the button in a scrollview. Here, the scrollview is a superview of the button and the width of the scrollview and its content size width must be greater than or equal to the button width to take action.
You are setting the containerView's width to 0 by setting its bounds size to the contentSize of the scrollview
self.scrollView.contentSize = CGSizeMake(0, 1000)
then
containerView.frame = CGRectMake(0, 0, scrollView.contentSize.width,
scrollView.contentSize.height)

UIScrollView doesn't scroll and doesn't appear on the right position

I need a UIScrollView and a containerView to scroll the content I create. My code for that 2 items is:
var scrollView = UIScrollView()
var darkener = UIView()
var container = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.clearColor()
darkener = UIView(frame: self.view.frame)
darkener.backgroundColor = UIColor.blackColor()
darkener.alpha = 0.0
self.view.addSubview(darkener)
scrollView.frame = self.view.bounds
scrollView.backgroundColor = UIColor.clearColor()
scrollView.contentSize = CGSizeMake(scrollView.frame.width, scrollView.frame.height+1)
scrollView.delegate = self
self.view.addSubview(scrollView)
container = UIView(frame: CGRectMake(0, scrollView.frame.height, scrollView.frame.width, scrollView.frame.height))
container.backgroundColor = UIColor.whiteColor()
container.layer.masksToBounds = true
container.layer.cornerRadius = 10
scrollView.addSubview(container)
}
The problem is that the container view once I Set the Y point to scrollView.frame.height doesn't appear on the screen (it's on the bottom), but in a previous VC that code worked perfectly.
Also, it does not let me scroll on the content. What's wrong there?
If necessary I can upload the implementation, but this I think has no problem.
Solved. I just had to put that at the end of the ViewDidLoad to declare de frame:
The textField is the final label I have on the screen, to declare the limit of the screen.
self.container.frame = CGRectMake(0, self.container.frame.origin.y, self.container.frame.width, textField2.frame.origin.y + textField2.frame.height - 60)
self.scrollView.contentSize = CGSizeMake(self.container.frame.width, self.container.frame.height + 20.0)
And works Ok now.

How to center UILabel in Swift?

I'm trying to center some text but I it doesn't seem to be working.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let title = UILabel()
title.text = "Some Sentence"
title.numberOfLines = 0
title.frame = CGRectMake(self.view.bounds.size.width/2,50,self.view.bounds.size.width, self.view.bounds.size.height) // x , y, width , height
title.textAlignment = .Center
title.sizeToFit()
title.backgroundColor = UIColor.redColor()
self.view.addSubview(title)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
That is the code that I'm using but this is what I get:
It's not center to the screen. Can someone tell me what am I doing wrong?
To center a UILabel just add this row
x and y:
title.center = self.view.center
x:
title.center.x = self.view.center.x
y:
title.center.y = self.view.center.y
Auto Layout
To make your app future proof rather use auto layout anchors instead of setting the frame.
1. Disable translatesAutoresizing
titleLabel.translatesAutoresizingMaskIntoConstraints = false
2. Add CenterX & CenterY constraints
titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
3. Set UILabel's text alignment to center
titleLabel.textAlignment = .center
SWIFT 4
This worked for me and seems more future proof. This also works for a multi-line label.
override func loadView() {
self.view = UIView()
let message = UILabel()
message.text = "This is a test message that should be centered."
message.translatesAutoresizingMaskIntoConstraints = false
message.lineBreakMode = .byWordWrapping
message.numberOfLines = 0
message.textAlignment = .center
self.view.addSubview(message)
message.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
message.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
message.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
Actually what you are doing is centering the text inside the UILabel. What you want to do is to center the label. To do it you can do:
title.frame.origin = CGPoint(x: x, y: y)
If you want to center the horizontal you can do:
title.frame.origin = CGPoint(x: self.view.frame.width / 2, y: yValue)
Also if you want to center the x and y value of your label you can do:
title.frame.origin = CGPoint(x: self.view.frame.width / 2, y: self.view.frame.height / 2)
Code for swift 3/4/5
Paste below code after super.viewDidLoad()
var noDataLbl : UILabel?
noDataLbl = UILabel(frame: CGRect(x: 0, y: self.view.center.y, width: 290, height: 70))
noDataLbl?.textAlignment = .center
noDataLbl?.font = UIFont(name: "Halvetica", size: 18.0)
noDataLbl?.numberOfLines = 0
noDataLbl?.text = "Replace this with your text."
noDataLbl?.lineBreakMode = .byTruncatingTail
noDataLbl?.center = self.view.center
view.addSubview(noDataLbl!)

Resources