Center UILabel created in code using Swift - ios

This may be the simplest thing you can possibly due in Xcode in Swift and for some reason, it is not working properly.
I want to center a label in a view. The only other thing in the view previously was a webView added programatically but for now I have removed that so basically, I have an empty VC in which I'm trying to center a label.
There are umpteen answers on SO about this and I've tried every combination but can't get it to to work.
Can anyone suggest a foolproof way to accomplish the simple task of centering a UILabel?
Below is the code I currently have and steps I've taken along with result:
I created an empty view controller in Storyboard and embedded it in a navigation controller.
I set the View Controller in Storyboard to my swift VC class. I also have already cleaned project, closed and re-opened XCode and also deleted storyboard and recreated it in case it was corrupted. Still nothing works.
myVC.swift
import UIKit
class myVC: UIViewController,WKScriptMessageHandler, WKNavigationDelegate,WKUIDelegate {
var title= "Hello there"
var loadingLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
webView.uiDelegate = self
loadingLabel.translatesAutoresizingMaskIntoConstraints = false
// loadingLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
// loadingLabel.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
// loadingLabel = UILabel(frame: CGRect(x: 0, y: self.view.center.y, width: 290, height: 70))
loadingLabel.center = self.view.center
loadingLabel.textAlignment = .center
loadingLabel.font = UIFont(name: "Halvetica", size: 18.0)
loadingLabel.numberOfLines = 0
loadingLabel.text = "TEXT I WANT TO CENTER"
loadingLabel.lineBreakMode = .byTruncatingTail
loadingLabel.center = self.view.center
self.view.addSubview(loadingLabel)
self.title = title
}
override func loadView() {
super.loadView()
}
}

Add the loadingLabel as subview before adding the constraints.
view.addSubview(loadingLabel)
loadingLabel.translatesAutoresizingMaskIntoConstraints = false
loadingLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
loadingLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true

Related

Making NavigationBar subview clickable in Swift

I have a View Controller embedded in Navigation Controller. The view has 1 WKWebView, hence, I'm setting view = webView in loadView() override.
So, I'm adding a small little sub navigation bar underneath my navigation controller to allow a user to change their location.I can add the subview to the navigation controller, I'm just not able to make it clickable.
override func loadView() {
let config = WKWebViewConfiguration()
config.processPool = YourModelObject.sharedInstance.processPool
webView = WKWebView(frame: .zero, configuration: config)
webView.navigationDelegate = self
self.webView.scrollView.delegate = self
view = webView
..
if let navigationBar = self.navigationController?.navigationBar {
let secondFrame = CGRect(x: 50, y: 44.1, width: navigationBar.frame.width, height: 30)
let secondLabel = UILabel(frame: secondFrame)
secondLabel.textColor = .black
secondLabel.text = "Getting your location..."
secondLabel.isUserInteractionEnabled = true
let guestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(setLocation(_:)))
secondLabel.addGestureRecognizer(guestureRecognizer)
secondLabel.textAlignment = .left
secondLabel.font = secondLabel.font.withSize(14)
secondLabel.tag = 1002
navigationBar.addSubview(secondLabel)
}
}
And then the setLocation function
#objc func setLocation(_ sender: Any) {
print("location label tapped")
}
But when I tap the label, I'm not getting anything printed in console. I don't know if the use of target: self is wrong for the tapGestureRecognizer or what's going on here.
I too am new to Swift, so my answer is far from guaranteed. I just know what it's like to be in your position,
Perhaps try creating a subclass of navigationBar for the sub navigation bar, i.e. mySubNavigationBar. Then in the subclass's code do all the initialization that you need to do. Including the print line so you'll know if you're getting there.
p.s. I would have put this as a comment, but I don't have enough points to add comments.

Is this an iOS 14 UISplitViewController bug?

In my app, I want a three-column UISplitViewController. I create it like this:
let svc = UISplitViewController(style: .tripleColumn)
svc.preferredDisplayMode = .twoOverSecondary
svc.setViewController(TestViewController(), for: .primary)
svc.setViewController(TestViewController(), for: .supplementary)
svc.setViewController(TestViewController(), for: .secondary)
svc.primaryBackgroundStyle = .sidebar
This ViewController that I'm presenting is a really simple viewController. It doesn't do anything except, present a centered red square.
class TestViewController: UIViewController {
private var redView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
redView.backgroundColor = .red
redView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(redView)
redView.widthAnchor.constraint(equalToConstant: 30).isActive = true
redView.heightAnchor.constraint(equalToConstant: 30).isActive = true
redView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
redView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
}
}
Now, when I run this code, I get the following result.
As you can see, 2 of the 3 squares are off-center. Anyone know, what I'm doing wrong here? Or is this a known bug?
You should use "Safe Area" instead of "self.view" when setting to center.
The detail view here has a push-away effect. You just need to click on it and the primary view controller will hide, like below.

How to overlay a view above a keyboard in iOS [duplicate]

This question already has answers here:
How to display UIView over keyboard in iOS
(7 answers)
Closed 5 years ago.
I need to present a help screen that overlays an open keyboard - the help screen should dim the whole view underneath and keep just a small hole with full transparency to "highlight" that piece. The point is to provide some information about several view components while highlighting them. Without a keyboard, I could just put a view at top of the hierarchy, but in this case the UI uses a keyboard with a custom input accessory that needs to be visible.
I tried to insert a new UIWindow and put it above all the UIWindows:
class CustomTextField: UITextField {
override var canResignFirstResponder: Bool {
return false
}
}
class ViewController: UIViewController {
var textField: UITextField = CustomTextField()
override func viewDidAppear(_ animated: Bool) {
view.backgroundColor = .white
super.viewDidAppear(animated)
textField.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
view.addSubview(textField)
textField.backgroundColor = UIColor.gray
textField.becomeFirstResponder()
DispatchQueue.main.asyncAfter(wallDeadline: .now() + 1) {
self.window.windowLevel = 100000002.0 // based on experiments with UIApplication.shared.windows this should be the top most window
let controller = UIViewController()
controller.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
self.window.rootViewController = controller
self.window.makeKeyAndVisible()
}
}
let window = UIWindow(frame: UIScreen.main.bounds)
}
But there are two problems with this approach:
The keyboard gets hidden as soon as the window becomes key and visible.
Even when using windowLevel = 100000002.0 it seems that the keyboard is above the window (the keyboard gets animated, so while hiding, I can see that its above my window).
Any ideas how to deal with these two problems? Is it even possible?
OK, as pointed out by #Krunal, this is kind of a duplicate of this question. The trick there is to add the overlay view to the window in which keyboard is (which happens to be the UIApplication.shared.windows.last):
class ViewController: UIViewController {
var textField: UITextField = UITextField()
override func viewDidAppear(_ animated: Bool) {
view.backgroundColor = .white
super.viewDidAppear(animated)
textField.frame = CGRect(x: 0, y: 0, width: 200, height: 50)
view.addSubview(textField)
textField.backgroundColor = UIColor.gray
textField.becomeFirstResponder()
DispatchQueue.main.asyncAfter(wallDeadline: .now() + 1) {
// this does the trick
let customView = UIView(frame: self.view.bounds)
customView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
customView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
UIApplication.shared.windows.last?.addSubview(customView)
}
}
}

Create JTAppleCalendarView in code

I want to create and customize a JTAppleCalendarView using only Swif 3 code, i.e. without the Interface Builder, Storyboards or XIB files.
I can create customs labels by code, however when I try to create a JTAppleCalendarView, I simply can not change the frame value, neither the heightAnchor or widthAnchor. This way, my calendar is not displayed.
I am attaching the code of the init of the my custom UIViewController (which implements the Datasource and Delegate protocols):
init(frame: CGRect) {
super.init(nibName: nil, bundle: nil)]
self.view = UIView(frame: frame)
self.view.backgroundColor = UIColor.green
let margins = self.view.layoutMarginsGuide
let calendar = JTAppleCalendarView()
print("CalendarView frame: ", calendar.frame)
calendar.dataSource = self
calendar.delegate = self
calendar.cellInset = CGPoint(x: 0, y: 0)
calendar.backgroundColor = UIColor.white
calendar.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(calendar)
calendar.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
calendar.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
calendar.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
//calendar.widthAnchor.constraint(equalTo: margins.widthAnchor).isActive = true
calendar.heightAnchor.constraint(equalToConstant: 400).isActive = true
}
Whenever I change calendar.heightAnchor, calendar.widthAnchor or calendar.frame, I get the error "Unexpectedly found nil while unwrapping an Optional value.".
I followed the library tutorial, however they only presents the creation using Interface Builders, which I am not using in my project. Tecnically, the component is just a custom UIView, so I am confused with this error.
In the code above, I forgot to register the cell.
Solved registering the cell with something like: calendar.registerCellViewClass(type: SomeCellClass.self).
So far, it worked for a simple project. I did not tested with playgrounds.

Unable to click on Textfield on GMaps for iOS Subview

I would like to add a searchbar (like in the Google Maps App for iOS).
So to look like the same as in that App, ill created a UITextField.
For example:
override func viewDidLoad() {
/* Add Google Map */
let camera = GMSCameraPosition.cameraWithLatitude(49.077872,longitude: 19.450339, zoom: 17)
mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
self.view = mapView
mapView.delegate = self
mapView.indoorDisplay.delegate = self
mapView.myLocationEnabled = true
mapView.settings.myLocationButton = true
mapView.padding = UIEdgeInsetsMake(64, 0, 64, 0)
mapView.setMinZoom(15, maxZoom: 19)
// add Searchbar
let screenWidth = UIScreen.mainScreen().bounds.width
searchTextField = UITextField(frame: CGRectMake(16, 50, screenWidth - 32, 40))
searchTextField.delegate = self
searchTextField.placeholder = "Gebäude und Räume suchen"
searchTextField.backgroundColor = UIColor.whiteColor()
searchTextField.clearButtonMode = UITextFieldViewMode.WhileEditing
searchTextField.layer.borderWidth = 1
searchTextField.layer.borderColor = UIColor.customGrey().CGColor
searchTextField.font = UIFont.systemFontOfSize(16.0)
let showCategories = UIButton(type: .Custom)
showCategories.frame = CGRectMake(0, 0, 40, 40)
showCategories.setTitle(String.fontAwesomeIconWithCode("fa-calendar-plus-o"), forState: .Normal)
showCategories.setTitleColor(UIColor.customDarkGrey(), forState: .Normal)
showCategories.titleLabel?.font = UIFont.fontAwesomeOfSize(20)
showCategories.addTarget(self,action: "calendarAddButtonPressed",forControlEvents: UIControlEvents.TouchUpInside)
searchTextField.rightView = showCategories
searchTextField.rightViewMode = .Always
searchTextField.userInteractionEnabled = true
self.mapView.addSubview(searchTextField)
The Button works fine, but i am unable to focus on the TextField.
When ill set (in ViewDidLoad).
searchTextField.becomesFirstResponder()
The Keyboard is there.
Also that event:
func textFieldDidBeginEditing(textField: UITextField) {
print("start searching")
self.becomeFirstResponder()
}
Is not fireing.
Any ideas? When the SubView is not on the top level - the button should not work too, or?
The accepted answer didn't help me at all, but it turns out there's another question on SO that is similar, but with Objective C.
All GMSMapViews have a GMSBlockingGestureRecognizer by default, and that is why your textField isn't working the way you want it to. The solution is to remove it, so you can put this in your viewDidLoad() method:
Swift 3
for gesture in mapView.gestureRecognizers! {
mapView.removeGestureRecognizer(gesture)
}
Alternatively, if you for some reason added other gesture recognizers to the mapView, you can do this:
for (index,gesture) in mapView.gestureRecognizers!.enumerated() {
if index == 0 {
mapView.removeGestureRecognizer(gesture)
}
}
Since the GMSBlockingGestureRecognizer is added by default, it will always be the first one in the array of gesture recognizers.
Also, make sure you put the for loop somewhere it will only be called once because if it is called multiple times, you could remove other gestures unintentionally.
Ok ill found a solution for someone who is struggling with the same problems.
When you set:
self.view = mapView
It looks like that you are unable to set ANY subviews, because that Views never receive touch events.
So in that case use:
mapView = GMSMapView.mapWithFrame(self.view.bounds, camera: camera)
self.view.addSubview(mapView)
Then all SubViews work fine.

Resources