Button action does not react when .touchUpInside inside a navigation bar - swift

I created a UICollectionViewController to simulate a Feed app and I wanted to configure the top navigation bar similar to the Twitter one, with custom buttons that trigger actions, here's mine
The problem I'm facing is that when I click on the black profile icon, the action is not triggered.
Here's my code:
import UIKit
class HomeViewController: UICollectionViewController {
//MARK: - Properties
private lazy var profileButton: UIButton = {
let button = UIButton(type: .system)
button.setImage(UIImage(systemName: "person.fill"), for: .normal)
button.tintColor = UIColor(rgb: 0x79CBBF)
button.addTarget(self, action: #selector(didTapProfile), for: .touchUpInside)
return button
}()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setupNavBar()
}
// MARK: - Helpers
func setupNavBar() {
let width = view.frame.width
let titleView = UIView()
titleView.backgroundColor = .clear
titleView.frame = .init(x: 0, y: 0, width: width, height: 50)
titleView.addSubview(profileButton)
profileButton.tintColor = .black
profileButton.centerY(inView: titleView, leftAnchor: titleView.leftAnchor, paddingLeft: 0)
titleView.addSubview(filterButton)
filterButton.centerY(inView: titleView, leftAnchor: profileButton.rightAnchor, paddingLeft: view.frame.width - 60 - 16)
navigationItem.titleView = titleView
}
// MARK: - Actions
#objc func didTapProfile() {
print("did tap profile")
}
As said below, I added a .addTarget to the button but the #selector(didTapProfile) function does not get triggered when the button is inside the navigation bar.
Any hints on how to do this?

Instead of creating a title view and measuring its size and stuff... there are a load of convenience functions for doing this...
Take a look here... https://www.hackingwithswift.com/example-code/uikit/how-to-add-a-bar-button-to-a-navigation-bar
You can do something like...
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(didTapProfile))
There are different ways to create UIBarButtonItem with images and text also...
https://developer.apple.com/documentation/uikit/uibarbuttonitem

Related

Swift: UIBarButtonItem with bigger size than UIToolbar

I have a UIToolbar installed on my Viewcontroller on the bottom via Storyboard. I also added a bottom in the Storyboard and now I want to give this bottom a greater height than the toolbar itself.
It should be something like that, but it cannot be a Tabbar but needs to be a Toolbar, as the items on it are purely contextual actions and not top level navigation items (see Apple guidelines here and here):
I tried the following code in my Viewcontroller without success (as mentioned here):
class MyVC: UIViewController {
#IBOutlet var ibOutletForButton: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: 0.0, y: 0.0, width: 20, height: 120)
menuBtn.setImage(UIImage(named:"iconImage"), for: .normal)
menuBtn.addTarget(self, action: #selector(onMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside)
let menuBarItem = UIBarButtonItem(customView: menuBtn)
let currWidth = menuBarItem.customView?.widthAnchor.constraint(equalToConstant: 24)
currWidth?.isActive = true
let currHeight = menuBarItem.customView?.heightAnchor.constraint(equalToConstant: 124)
currHeight?.isActive = true
ibOutletForButton = menuBarItem
}
}
How could I get the button bigger and moved up that it looks like on the image?
One way you could do this is to add the button directly to the UIViewController instead of to the UIToolbar. You have then complete freedom of positioning and sizing.
As you don't use a UITabBar, you will stay within your UIViewController and it should be no problem
You can create 4 BarbuttonItem after first 2, give some flexible space between items and add your 'plus' button to toolbar directly in that space.
#IBOutlet weak var myToolBar: UIToolbar!
let menuBtn = UIButton(type: .custom)
override func viewDidLoad() {
super.viewDidLoad()
let menuBtn = UIButton(type: .custom)
menuBtn.frame = CGRect(x: myToolBar.center.x-10, y: -60, width: 20, height: 120)
menuBtn.setImage(UIImage(named:"iconImage"), for: .normal)
menuBtn.addTarget(self, action: #selector(onMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside)
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let items = myToolBar.items!
myToolBar.setItems([items[0],items[1],spacer,items[2],items[3]], animated: false)
myToolBar.addSubview(menuBtn)
}

How can I center a button on view programmatically

I am trying to center a Button onto the bottom of a view but it never appears. The only time it appears is when I uncomment takePhotoButton.frame. What is the proper way to do this?
import UIKit
import AVFoundation
class InputViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let photoPreviewImageView = UIImageView()
photoPreviewImageView.frame = view.bounds
photoPreviewImageView.backgroundColor = UIColor.green
view.addSubview(photoPreviewImageView)
let imageOfPhotoButton = UIImage(named: "smallcircle.circle.fill") as UIImage?
let takePhotoButton = UIButton(type: .custom) as UIButton
takePhotoButton.setImage(imageOfPhotoButton, for: .normal)
//takePhotoButton.frame = CGRect(x: 10, y: 10, width: 60, height: 60) // It will appear with this code however i took it away because im trying to center it at the bottom of the screen
takePhotoButton.center = view.center
photoPreviewImageView.addSubview(takePhotoButton)
}
}
Use constraint anchors. After you add the takePhotoButton set them the following way:
takePhotoButton.bottomAnchor.constraint(equalTo: photoPreviewImageView.bottomAnchor).isActive = true
takePhotoButton.centerXAnchor.constraint(equalTo: photoPreviewImageView.centerXAnchor).isActive = true
This will set make your button have the same bottom and center as it's container.
Good day,
you have to add constraint.
import UIKit
class ViewController: UIViewController {
var loginButton : UIButton = {
let button = UIButton(type: .system)
button.setTitle("Login", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.backgroundColor = .red
button.tintColor = .white
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
constraintsInit()
}
func constraintsInit(){
view.addSubview(loginButton)
NSLayoutConstraint.activate([
loginButton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
loginButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
loginButton.heightAnchor.constraint(equalToConstant: 30),
loginButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor,constant: 30),
loginButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor,constant: -30),
])
}
}
on youtube you can find several people that explain how create the views, using only code.

Add a button load more below uitableview

I need a solution in swift to add a button below uitableview, how to do it ? do I have to add a custom cell at the end ? or add an another view below uitableview ? I tried to add a view, but I can't see this one.
Here is the simplest way to add a button/CustomView at the bottom of the tableView.
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: CGRect(origin: .zero, size: CGSize(width: self.tableView.frame.width, height: 40)))
button.setTitle("Load more", for: .normal)
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(moreButtonClicked(_:)), for: .touchUpInside)
self.tableView.tableFooterView = button
}
#objc func moreButtonClicked(_ sender: UIButton) {
print("More button clicked, fetch more data!")
}

How to add button layout constraints ARSKView?

I'm using SpriteKit (ARSKView) with UIKit elements, and I'd like to add a button that stays in the bottom left of the screen at all times. When pressed, the button would clear all nodes.
This is the code I tried to get the button to display, but when I try adding the bottom anchor and left anchor constraints, I get this error
Unable to activate constraint with anchors
and because they have no common ancestor.
Does the constraint or its anchors reference items in different view
hierarchies? That's illegal.'
The button works fine when tapped, but how can I add layout constraints in ARSKView?
And how do I get the button to clear all the nodes from the scene?
Here is my code
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// Show statistics such as fps and node count
sceneView.showsFPS = true
sceneView.showsNodeCount = true
// sceneView.showsPhysics = true
// Load the SKScene from 'Scene.sks'
if let scene = SKScene(fileNamed: "Scene") {
sceneView.presentScene(scene)
}
let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
button.backgroundColor = UIColor(red: 0, green: 0, blue:0, alpha: 0.4)
button.setTitle("Clear Screen", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button.bottomAnchor.constraint(equalTo: sceneView.bottomAnchor).isActive = true
button.leftAnchor.constraint(equalTo: sceneView.leftAnchor).isActive = true
self.view.addSubview(button)
}
#objc func buttonAction(sender: UIButton!) {
print("Button tapped")
}

Swift - Getting tap location on a button which was created through custom UIView class

I have a main scrollerview in my main UIViewController and a custom UIView class. This custom UIView class has few lines of code to create Button and Label programmatically. The action to be performed by Button click is working fine, but I also need to get the exact tap location (CGPoint) on the button as the button is long and tap x-coordinate is required for next actions. I tried few solutions got from stackoverflow and is working for other objects like Label and Imageview but doesn't work for button.
My custom UIView class:
import UIKit
class DrawProj: UIView {
override func drawRect(rect: CGRect) {
let button = UIButton(type: .System)
button.frame = CGRectMake(24, 15, linewidth - 25, 20)
button.backgroundColor = UIColor.orangeColor()
button.addTarget(nil, action: "onButtonTap:", forControlEvents: .TouchUpInside)
self.addSubview(button)
}
}
And Code in main Viewcontroller
let DrawProjectLanes = DrawProj(frame: CGRect(x: startx, y: starty, width: endx , height: 50))
DrawProjectLanes.backgroundColor = UIColor.clearColor()
DrawProjectLanes.userInteractionEnabled = true
MainScroller.addSubview(DrawProjectLanes)
You should override touchesBegan for this to work:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
Then declare your button subview as a property:
class DrawProj: UIView {
var button: UIButton!
override func drawRect(rect: CGRect) {
button = UIButton(type: .System)
button.frame = CGRectMake(24, 15, linewidth - 25, 20)
button.backgroundColor = UIColor.orangeColor()
button.addTarget(nil, action: "onButtonTap:", forControlEvents: .TouchUpInside)
self.addSubview(button)
}
}
In touchesBegan, do this to get the x position of the tap, relative to the button's frame:
let posX = touches.first!.locationInView(button).x
Then, you can use this posX variable however you want.
How to instantiate a view controller:
In the storyboard, select the VC that you would like to present. Go to the identity inspector, set a Storyboard ID for the VC:
Then in code,
let sb = UIStoryboard(name: "Main", bundle: nil)
let viewController = sb.instantiateViewControllerWithIdentifier("put the storyboard ID that you set earlier here")
let topViewController = UIApplication.sharedApplication().keyWindow?.rootViewController?.presentationController
topViewController?.presentViewController(viewController, animated: true, completion: nil)