Cant change border color in Cocoa Swift Mac OS - swift

I am new to Cocoa with Swift and made a textfield programmatically like this:
let usernameTextField: NSTextField = {
let textField = NSTextField()
textField.isBezeled = false
textField.drawsBackground = false
textField.focusRingType = .none
textField.placeholderString = "Username"
textField.font = NSFont.systemFont(ofSize: 18)
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
Later, in viewDidLoad, I do this:
usernameTextField.layer?.borderColor = NSColor.systemRed.cgColor
But the color doesn't change to red. Why is this? Thanks!

Try adding border width:
usernameTextField.layer?.borderWidth = 2
or don't add it in viewDidLoad() try adding it in viewWillLayoutSubviews()

Have no idea if this is helpful or not, but it will change a subclassed NSTextField's border color:
import Cocoa
var borderColor = NSColor()
class TextField: NSTextField {
override func draw(_ rect: NSRect) {
super.draw(rect)
let border = NSBezierPath(rect: bounds)
borderColor.set()
border.lineWidth = 2.0
border.stroke()
}
#objc func changeBorderColor(_ sender: AnyObject ) {
borderColor = .red
self.needsDisplay = true
}
}
let txtFld = TextField()
class ApplicationDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}
func buildWnd() {
let _wndW:CGFloat = 400
let _wndH:CGFloat = 200
window = NSWindow(contentRect: NSMakeRect( 0, 0, _wndW, _wndH ), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: false)
window.center()
window.title = "Swift Test Window"
window.makeKeyAndOrderFront(nil)
// === Text Field === //
let txtFld = TextField (frame:NSMakeRect( 60, 60, 180, 24 ))
window.contentView!.addSubview(txtFld)
txtFld.stringValue = "Text"
borderColor = .green
// === Button === //
let myBtn = NSButton (frame:NSMakeRect( 150, 100, 135, 30 ))
myBtn.bezelStyle = .rounded
myBtn.title = "Change Border"
myBtn.target = txtFld
myBtn.action = #selector(txtFld.changeBorderColor(_:))
window.contentView!.addSubview (myBtn)
// === Quit btn === //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 5, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}
func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let appDelegate = ApplicationDelegate()
// **** main.swift **** //
let application = NSApplication.shared
application.setActivationPolicy(.regular)
application.delegate = appDelegate
application.activate(ignoringOtherApps:true)
application.run()

Related

How to customize a NSPopUpButton and its NSMenu?

I want to style a NSPopUpButton with my own colors. I've gotten pretty much everything else to work except for the caps at the top and bottom of the menu and I can't get the NSPopUpButton to show an image. Here are a few screenshots of the problem:
Why is the drawn background bigger on my custom view compared to the system NSPopUpButton?
Here is an image of the caps problem:
I can't figure out where those caps are drawn and how I can change their color to match the menu items?
View controller
import Cocoa
let textColor = NSColor(calibratedWhite: 0.9, alpha: 1)
let surfacePrimaryColor = NSColor(calibratedWhite: 0.1, alpha: 1)
let surfaceSecondaryColor = NSColor(calibratedWhite: 0.3, alpha: 1)
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.translatesAutoresizingMaskIntoConstraints = false
let stackView = NSStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
let cell = PopUpButtonCell()
cell.imagePosition = .imageLeading
let icon = NSImage(systemSymbolName: "folder", accessibilityDescription: nil)
cell.image = icon
print("cell.image: \(cell.image)")
let popUpButton = NSPopUpButton()
popUpButton.cell = cell
for title in (Array(1...100).map { "Folder \($0)" }) {
let menuItem = NSMenuItem()
menuItem.title = title
let menuItemView = MenuItemView()
menuItemView.translatesAutoresizingMaskIntoConstraints = false
menuItemView.onAction {
cell.title = title
menuItem.menu?.cancelTracking()
}
menuItem.view = menuItemView
let titleLabel = NSTextField(string: title)
titleLabel.drawsBackground = false
titleLabel.isBezeled = false
titleLabel.isSelectable = false
titleLabel.isEditable = false
titleLabel.maximumNumberOfLines = 1
titleLabel.textColor = textColor
let deleteButton = Button(systemSymbolName: "xmark")
deleteButton.font = NSFont.systemFont(ofSize: 14)
deleteButton.isBordered = false
deleteButton.contentTintColor = textColor
deleteButton.onAction {
popUpButton.removeItem(withTitle: title)
}
let menuItemStackView = NSStackView()
menuItemView.addSubview(menuItemStackView)
menuItemStackView.orientation = .horizontal
menuItemStackView.edgeInsets = NSEdgeInsets(top: 6, left: 10, bottom: 6, right: 10)
menuItemStackView.translatesAutoresizingMaskIntoConstraints = false
menuItemStackView.leadingAnchor.constraint(equalTo: menuItemView.leadingAnchor).isActive = true
menuItemStackView.trailingAnchor.constraint(equalTo: menuItemView.trailingAnchor).isActive = true
menuItemStackView.topAnchor.constraint(equalTo: menuItemView.topAnchor).isActive = true
menuItemStackView.bottomAnchor.constraint(equalTo: menuItemView.bottomAnchor).isActive = true
menuItemStackView.addView(titleLabel, in: .leading)
menuItemStackView.addView(deleteButton, in: .trailing)
popUpButton.menu?.addItem(menuItem)
}
let popUpButton2 = NSPopUpButton()
popUpButton2.addItems(withTitles: Array(1...100).map { "File \($0)" })
stackView.addArrangedSubview(popUpButton)
stackView.addArrangedSubview(popUpButton2)
}
}
Custom button with onAction closure
import AppKit
typealias Listener = () -> Void
class Button: NSButton {
private var listener: Listener?
init(systemSymbolName: String) {
super.init(frame: .zero)
image = NSImage(systemSymbolName: systemSymbolName, accessibilityDescription: nil)
target = self
action = #selector(actionPerformed(_:))
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
#objc func actionPerformed(_ sender: AnyObject) {
listener?()
}
func onAction(_ closure: #escaping Listener) {
listener = closure
}
}
Custom popup button cell
import Cocoa
class PopUpButtonCell: NSPopUpButtonCell {
override var controlView: NSView? {
didSet {
controlView?.wantsLayer = true
controlView?.layer?.backgroundColor = surfaceSecondaryColor.cgColor
controlView?.layer?.cornerRadius = 4
}
}
// Prevent system background drawing
override func drawBezel(withFrame frame: NSRect, in controlView: NSView) {
}
override func drawTitle(_ title: NSAttributedString, withFrame frame: NSRect, in controlView: NSView) -> NSRect {
let attributedTitle = NSMutableAttributedString(attributedString: title)
let range = NSMakeRange(0, attributedTitle.length)
attributedTitle.addAttributes([NSAttributedString.Key.foregroundColor : textColor], range: range)
return super.drawTitle(attributedTitle, withFrame: frame, in: controlView)
}
}
Why is image nil after setting it on the NSPopUpButton?
How can I change the color of the menu caps?
Why is image nil after setting it on the NSPopUpButton?
See setImage:
This method has no effect. The image displayed in a pop up button is taken from the selected menu item (in the case of a pop up menu) or from the first menu item (in the case of a pull-down menu).

iOS UIkit custom segmented buttons

I'm looking to create a view with these buttons. There is a background animation when one of the button touched.
Not sure how to do this.
Is custom segmented buttons the way to go?
I went with custom control
import UIKit
protocol MSegmentedControlDelegate:AnyObject {
func segSelectedIndexChange(to index:Int)
}
class MSegmentedControl: UIControl {
private var buttonTitles:[String]!
private var buttons: [UIButton]!
private var selectorView: UIView!
var textColor:UIColor = .black
var selectorViewColor: UIColor = .white
var selectorTextColor: UIColor = .red
weak var delegate:MSegmentedControlDelegate?
public private(set) var selectedIndex : Int = 0
convenience init(frame:CGRect,buttonTitle:[String]) {
self.init(frame: frame)
self.buttonTitles = buttonTitle
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.backgroundColor = UIColor.white
updateView()
}
func setButtonTitles(buttonTitles:[String]) {
self.buttonTitles = buttonTitles
self.updateView()
}
func setIndex(index:Int) {
buttons.forEach({ $0.setTitleColor(textColor, for: .normal) })
let button = buttons[index]
selectedIndex = index
button.setTitleColor(selectorTextColor, for: .normal)
let selectorPosition = frame.width/CGFloat(buttonTitles.count) * CGFloat(index)
UIView.animate(withDuration: 0.2) {
self.selectorView.frame.origin.x = selectorPosition
}
}
#objc func buttonAction(sender:UIButton) {
for (buttonIndex, btn) in buttons.enumerated() {
btn.setTitleColor(textColor, for: .normal)
if btn == sender {
let selectorPosition = frame.width/CGFloat(buttonTitles.count) * CGFloat(buttonIndex)
selectedIndex = buttonIndex
delegate?.segSelectedIndexChange(to: selectedIndex)
UIView.animate(withDuration: 0.3) {
self.selectorView.frame.origin.x = selectorPosition
}
btn.setTitleColor(selectorTextColor, for: .normal)
}
}
}
}
//Configuration View
extension MSegmentedControl {
private func updateView() {
createButton()
configSelectorView()
configStackView()
}
private func configStackView() {
let stack = UIStackView(arrangedSubviews: buttons)
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
addSubview(stack)
stack.translatesAutoresizingMaskIntoConstraints = false
stack.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
stack.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
stack.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
stack.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
}
private func configSelectorView() {
let selectorWidth = frame.width / CGFloat(self.buttonTitles.count)
selectorView = UIView(frame: CGRect(x: 0, y: 8, width: selectorWidth, height: 32))
selectorView.backgroundColor = selectorViewColor
selectorView.layer.cornerRadius = 16
selectorView.layer.opacity = 0.5
addSubview(selectorView)
}
private func createButton() {
buttons = [UIButton]()
buttons.removeAll()
subviews.forEach({$0.removeFromSuperview()})
for buttonTitle in buttonTitles {
let button = UIButton(type: .system)
button.setTitle(buttonTitle, for: .normal)
button.addTarget(self, action:#selector(MSegmentedControl.buttonAction(sender:)), for: .touchUpInside)
button.setTitleColor(textColor, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
buttons.append(button)
}
buttons[0].setTitleColor(selectorTextColor, for: .normal)
}
}
Usage:
private let segControl: MSegmentedControl = {
let segControl = MSegmentedControl(
frame: CGRect(x: 0, y: 240, width: 280, height: 50),
buttonTitle: ["Average","Total","Pending"])
segControl.textColor = M.Colors.greyWhite
segControl.selectorTextColor = .white
return segControl
}()
To access index change event:
Implement the delegate on parent view:
addSubview(segControl)
segControl.delegate = self
Delegate:
func segSelectedIndexChange(to index: Int) {
switch index {
case 0: print("Average")
case 1: print("Total")
case 2: print("Pending")
default: break
}
}
Result:

How to colour radio buttons?

You can see that Apple has coloured the radio buttons. I would like to do the same. I can't seems to find the option to change the colour in Interface Builder on storyboard.
As for doing it, programmatically, I tried enabling layer .wantsLayer = true and then tried to set the colour by .layer?.borderColour = NSColor.systemBlue.cgColor and tried .layer?.backgroundColor = NSColor.systemRed.cgColor and other similar properties but no avail.
Likewise, how do you add the colour rectangles on NSMenuItem on NSPopUpButton?
The following code demonstrates a group of custom radio buttons for MacOS made by subclassing NSButton. It may be run in an Xcode swift project by copy/pasting into a newly added file called ‘main.swift’ and deleting the original AppDelegate.
import Cocoa
class CustomButton: NSButton {
var circleColor: NSColor!
override func draw(_ rect: NSRect) {
let circle = NSBezierPath(ovalIn: bounds)
switch(self.tag) {
case 0:
circleColor = NSColor.red
case 1:
circleColor = NSColor.green
case 2:
circleColor = NSColor.yellow
case 3:
circleColor = NSColor.orange
default:
break
}
circleColor.set()
circle.fill()
if(self.state) == .on {
let dotRect = NSInsetRect(bounds, 18.0, 18.0);
let dot = NSBezierPath (ovalIn:dotRect)
let dotColor = NSColor.black
dotColor.set()
dot.fill()
}
}
}
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
#objc func radioGrpAction(_ sender:NSButton) {
print("You selected: id = \(sender.tag)")
}
func buildMenu() {
let mainMenu = NSMenu()
NSApp.mainMenu = mainMenu
// **** App menu **** //
let appMenuItem = NSMenuItem()
mainMenu.addItem(appMenuItem)
let appMenu = NSMenu()
appMenuItem.submenu = appMenu
appMenu.addItem(withTitle: "Quit", action:#selector(NSApplication.terminate), keyEquivalent: "q")
}
func buildWnd() {
let _wndW : CGFloat = 300
let _wndH : CGFloat = 200
window = NSWindow(contentRect:NSMakeRect(0,0,_wndW,_wndH),styleMask:[.titled, .closable, .miniaturizable], backing:.buffered, defer:false)
window.center()
window.title = "Radio Button Group"
window.makeKeyAndOrderFront(window)
// === Radio Grp Box === //
let grpBox = NSBox(frame: NSMakeRect( 50,_wndH - 100, 150, 60))
grpBox.title = "Radio Group"
window.contentView!.addSubview (grpBox)
// === Radio Horizontal Grid === //
let _btnW : CGFloat = 24
let _btnH : CGFloat = 24
let _left : CGFloat = 10 // left margin first button
let _YOffset : CGFloat = 5 // 0,0 at left, bottom of group box
let _spacing : CGFloat = 5 // spacing between buttons
for x in stride(from:0, through:3, by:1) {
let _XOffset = _left + CGFloat(x)*(_btnW + _spacing)
let btn = CustomButton(frame:NSMakeRect(_XOffset, _YOffset, _btnW, _btnH))
btn.setButtonType(.radio)
btn.tag = x
if(x == 0){btn.state = .on}
btn.action = #selector(self.radioGrpAction(_:))
grpBox.contentView!.addSubview(btn)
}
// === Quit btn === //
let quitBtn = NSButton (frame:NSMakeRect( _wndW - 50, 10, 40, 40 ))
quitBtn.bezelStyle = .circular
quitBtn.title = "Q"
quitBtn.action = #selector(NSApplication.terminate)
window.contentView!.addSubview(quitBtn)
}
func applicationDidFinishLaunching(_ notification: Notification) {
buildMenu()
buildWnd()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
return true
}
}
let appDelegate = AppDelegate()
// ***** main.swift ***** //
let app = NSApplication.shared
app.setActivationPolicy(.regular)
app.delegate = appDelegate
app.activate(ignoringOtherApps:true)
app.run()
Ok the same but for AppKit:
import Cocoa
import AppKit
extension NSView {
func centerX(inView view: NSView, constant: CGFloat = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: constant).isActive = true
}
func centerY(inView view: NSView, constant: CGFloat = 0) {
translatesAutoresizingMaskIntoConstraints = false
centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: constant).isActive = true
}
func setDimensions(height: CGFloat, width: CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
heightAnchor.constraint(equalToConstant: height).isActive = true
widthAnchor.constraint(equalToConstant: width).isActive = true
}
}
class CustomRadioButton: NSView {
private let containerSize: CGFloat = 60.0
private let selectorSize: CGFloat = 20.0
var containerColor: NSColor = .blue
var selectorColor: NSColor = .red
var selected: Bool = true {
didSet {
selectorView.isHidden = !selected
}
}
private lazy var containerView: NSView = {
let view = NSView()
view.wantsLayer = true
view.layer?.backgroundColor = containerColor.cgColor
return view
}()
private lazy var selectorView: NSView = {
let view = NSView()
view.wantsLayer = true
view.layer?.backgroundColor = selectorColor.cgColor
return view
}()
override init(frame: CGRect) {
super.init(frame: CGRect(x: 0, y: 0, width: containerSize, height: containerSize))
configureUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configureUI() {
addSubview(containerView)
containerView.setDimensions(height: containerSize, width: containerSize)
containerView.layer?.cornerRadius = containerSize / 2
containerView.centerX(inView: self)
containerView.centerY(inView: self)
addSubview(selectorView)
selectorView.setDimensions(height: selectorSize, width: selectorSize)
selectorView.layer?.cornerRadius = selectorSize / 2
selectorView.centerY(inView: containerView)
selectorView.centerX(inView: containerView)
}
}
let selector = CustomRadioButton()
selector.selected = false

How to change a variable UITextView after clicking the button?

I create UITextView with a random tag and text, but it is created with one variable, is it possible to update the variable after creation UITextView (by clicking the add button)? Maybe add a random number to it, for example newText1, newText2.. etc.
So that the next UITextView is already created with a new variable?
P.S Sorry, if the question is silly, I just recently started to study Swift
#IBOutlet weak var addTextButton: UIButton!
#IBOutlet weak var StoriesView: UIView!
var newText = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addTextButton(_ sender: Any) {
let maxNumber = 10000
let i = Int(arc4random_uniform(UInt32(maxNumber)))
newText = UITextView(frame: CGRect(x: self.StoriesView.frame.origin.x + 40, y: self.StoriesView.frame.origin.y + 40, width: 380, height: 80))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.clear
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
}
UPD:
let fontToolbar = UIToolbar(frame:CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
fontToolbar.barStyle = .default
fontToolbar.items = [
UIBarButtonItem(title: "Green", style: .plain, target: self, action: #selector(greenColor)),
UIBarButtonItem(title: "Blue", style: .plain, target: self, action: #selector(blueColor)),
UIBarButtonItem(title: "Red", style: .plain, target: self, action: #selector(redColor)),
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Close Keyboard", style: .plain, target: self, action: #selector(dismissKeyboard))]
fontToolbar.sizeToFit()
newText.inputAccessoryView = fontToolbar
in the toolBar above the keyboard I have buttons, here we change the color
#objc func redColor() {
newText.textColor = UIColor.red}
#objc func blueColor() {
newText.textColor = UIColor.blue}
#objc func greenColor() {
newText.textColor = UIColor.green}
So the color changes only in the newly created UITextView
On click of button, create a new texView and assign it a tag value. Once it is added, update the value of i to +1, so that every textView added has a new tag value.
var i = 1
var newText = UITextView()
#IBAction func addTextButton(_ sender: Any) {
newText = UITextView(frame: CGRect(x: self.StoriesView.frame.origin.x + 40, y: self.StoriesView.frame.origin.y + 40, width: 380, height: 80))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.clear
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
//increment i
i+=1
}
then you can access your textField via tag values like this:
if let textView = self.StoriesView.viewWithTag(i) as? UITextView {
// textView.text = "change it"
}
UPDATE:
Add textView Delegate method, and once a textView starts editing, change the newText value to the currently editing textView
class ViewController : UIViewController, UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
newText = textView
}
}
I have modified your code a bit to have new UITextView object with button click
import UIKit
class ScannerViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var StoriesView: UIView!
#IBOutlet weak var addTextButton: UIButton!
var yposition: CGFloat!
var textFieldTag: [Int]! = []
override func viewDidLoad() {
super.viewDidLoad()
yposition = 20
}
#IBAction func addTextButton(_ sender: Any) {
let xposition = self.StoriesView.frame.origin.x
let maxNumber = 10000
let i = Int(arc4random_uniform(UInt32(maxNumber)))
textFieldTag.append(i)
let newText = UITextView(frame: CGRect(x: xposition , y: yposition , width: 380, height: 40))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.yellow
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
yposition = yposition + 45
}
#IBAction func accessTextFields(_ sender: Any) {
//access all text fields
for tag in textFieldTag {
if let textField = self.StoriesView.viewWithTag(tag) as? UITextView {
//change properties here
textField.backgroundColor = .cyan
}
}
//access specific text fields
if let textField = self.StoriesView.viewWithTag(textFieldTag.first!) as? UITextView {
//change properties here
textField.backgroundColor = .orange
}
if let textField = self.StoriesView.viewWithTag(textFieldTag[textFieldTag.count - 1]) as? UITextView {
//change properties here
textField.backgroundColor = .green
}
}
}
It will have an output as this!!

textField will not move in programable scrollview

I have a UIScrollView. I have a UITextField and a UILabel. For some reason my UITextField it will not move in my scroll view but my UILablel will. I have added the UITextField the same way as I added my UILabel to the scrollview using scrollView.addSubview(textField). Anyone see what I am doing wrong on this one?
import Foundation
import UIKit
//here
protocol AddContactDelegate {
func addContact(contact: Contact)
}
class AddContactController: UIViewController {
//delegate
var delegate: AddContactDelegate?
//TextField
let textField: UITextField = {
let tf = UITextField()
tf.placeholder = "Add Your Workout Title"
tf.textAlignment = .center
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
override func viewDidLoad() {
super.viewDidLoad()
//making scroll view
let screensize: CGRect = UIScreen.main.bounds
let screenWidth = screensize.width
let screenHeight = screensize.height
var scrollView: UIScrollView!
scrollView = UIScrollView(frame: CGRect(x: 0, y: 120, width: screenWidth, height: screenHeight))
scrollView.contentSize = CGSize(width: screenWidth, height: 2000)
view.addSubview(scrollView)
//setting up how view looks-----
view.backgroundColor = .white
//top buttons
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDone))
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(handleCancel))
//view elements
view.addSubview(textField)
scrollView.addSubview(textField)
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
textField.widthAnchor.constraint(equalToConstant: view.frame.width - 64).isActive = true
textField.becomeFirstResponder()
//excercise label
let excerciseNumber = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
excerciseNumber.center = CGPoint(x: view.frame.width / 2 , y: view.frame.height / 20)
excerciseNumber.textAlignment = .center
excerciseNumber.text = "Workout Title"
self.view.addSubview(excerciseNumber)
scrollView.addSubview(excerciseNumber)
}
//done button
#objc func handleDone(){
print("done")
guard let fullname = textField.text, textField.hasText else {
print("handle error here")
return
}
let contact = Contact(fullname: fullname, hello: "hi")
delegate?.addContact(contact: contact)
print(contact.fullname)
print(contact.hello)
}
//cancel button
#objc func handleCancel(){
self.dismiss(animated: true, completion: nil )
}
}
As you make the center x and y of the textfield with view not scrollView , You need
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textField.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
textField.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor),
textField.widthAnchor.constraint(equalToConstant: view.frame.width - 64)
])
Also remove
view.addSubview(textField)
self.view.addSubview(excerciseNumber)