Does anyone know how I can move a back button image to the edge of the screen?
This is what it looks like right now:
and this is how I want it to look:
If you add custom view as a button and add as leftBarButtonItem it always takes default x (frame's start position) position for that view as defined for navigation bar item. You can add something like this to get your desired output:
class AnotherViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let containerView = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 200, height: 50)))
let btnBack = UIButton(frame: CGRect(x: -25, y: 0, width: 45, height: 45))
btnBack.setImage(UIImage(named: "dark_ic_back.png")?.withRenderingMode(.alwaysTemplate), for: .normal)
btnBack.tintColor = .black
btnBack.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
containerView.addSubview(btnBack)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: containerView)
}
#objc func backAction(_ sender: UIButton) {
self.navigationController?.popViewController(animated: true)
}
}
Output:
Try to change its insets:
self.navigationController?.navigationBar.backItem?.backBarButtonItem?.imageInsets = UIEdgeInsets(top: 0, left: -12, bottom: 0, right: 12)
and find values to move it right to the edge.
Related
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)
}
I have the following function I use to customize the navigation bar across almost all the apps view controllers and table view controllers - instead of replicating the code numerous times I am looking for way to easily call the function on those view controllers needing it.
I have tried wrapping in extension UIViewController { } but run into a selector issue saying the following:
Argument of '#selector' cannot refer to local function
'Tapped(tapGestureRecognizer:)'
Code:
func navBar(){
// Profile Image
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.image = UIImage(url: URL(string: "test.com"))
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.layer.cornerRadius = 20
imageView.layer.masksToBounds = true
containView.addSubview(imageView)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
}
#objc func imageTapped(tapGestureRecognizer: UITapGestureRecognizer) {
print("Profile Tapped")
}
How can this UIImage be seen in the navigation bar across various view controller without needing to rewrite the same code across all.
Lot a way to do it. I'll usually istance and personalize an UIViewController and use it around the whole app.
class baseController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//call your navBar here
navbar()
}
func navBar(){
// Profile Image
let containView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
imageView.image = UIImage(url: URL(string: "test.com"))
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.layer.cornerRadius = 20
imageView.layer.masksToBounds = true
containView.addSubview(imageView)
let rightBarButton = UIBarButtonItem(customView: containView)
self.navigationItem.rightBarButtonItem = rightBarButton
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureRecognizer)
}
}
Now instance this class whenever you want and your controller will get your navBar() every time with this
class mineController:baseController {
//your code here...
}
I need to hide the two right button in the Navigation Bar, then unhide it after the user selects some options.I added two buttons(i.e search and setting button) in the storyboard
Unfortunately, the following doesn't work:
navigationItem.rightBarButtonItem.isHidden = true
if I use below code then not able to show them again
navigationItem.rightBarButtonItem = nil
Add them programatically
class YourVC: UIViewController {
var item1 = UIBarButtonItem()
var item2 = UIBarButtonItem()
override func viewDidLoad() {
super.viewDidLoad()
let btn1 = UIButton()
btn1.setImage(UIImage(named: "validImage1"), for: .normal)
btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
item1.customView = btn1
let btn2 = UIButton()
btn2.setImage(UIImage(named: "validImage2"), for: .normal)
btn2.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
item2.customView = btn2
self.navigationItem.rightBarButtonItems = [item1,item2]
}
}
You can hide them:
self.navigationItem.rightBarButtonItems = nil
and show:
self.navigationItem.rightBarButtonItems = [item1,item2]
I am trying to make a game where if I press a button it can spawn another button in another area so you can click and keep doing that, every time you press the button you should get a point. I don't know how to spawn another button when I pressed one button.
// this is the code
var monkeyPosition : Int = 1
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.addSubview(makeButtonSpawn())
view.addSubview(makeButtonSpawn2())
}
#IBAction func monkeyPlayer(_ sender: UIButton) {
if sender.tag == 1 && (monkeyPosition == 1) {
makeButtonSpawn2().isHidden = false
}
}
func makeButtonSpawn() -> UIButton {
let monkey = UIButton(type: UIButton.ButtonType.system)
//Set a frame for the button. Ignored in AutoLayout/ Stack Views
monkey.frame = CGRect(x: 30, y: 30, width: 90, height: 90)
monkey.backgroundColor = UIColor.blue
makeButtonSpawn().isHidden = true
return monkey
}
func makeButtonSpawn2() -> UIButton {
let monkey = UIButton(type: UIButton.ButtonType.system)
//Set a frame for the button. Ignored in AutoLayout/ Stack Views
monkey.frame = CGRect(x: 80, y: 80, width: 90, height: 90)
monkey.backgroundColor = UIColor.blue
makeButtonSpawn2().isHidden = true
return monkey
}
Create instance variables for your buttons, then you will be able to access them from places in your class. Also you can set its properties inside variable closure instead of declaring method
class ViewController: UIViewController {
var button1: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 30, y: 30, width: 90, height: 90)
button.backgroundColor = .blue
return button
}()
var button2: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 80, y: 80, width: 90, height: 90)
button.backgroundColor = .blue
button.isHidden = true
return button
}()
}
Next, you need to add your buttons as subviews to main view and you need to add target for them
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.backgroundColor = UIColor(white: 0.25, alpha: 1.0)
view.addSubview(button1)
view.addSubview(button2)
button1.addTarget(self, action: #selector(button1Pressed(_:)), for: .touchUpInside)
button2.addTarget(self, action: #selector(button2Pressed(_:)), for: .touchUpInside)
}
#objc func button1Pressed(_ sender: UIButton) {
}
#objc func button2Pressed(_ sender: UIButton) {
}
Finally, you can unhide second button when first button is pressed
#objc func button1Pressed(_ sender: UIButton) {
if monkeyPosition == 1 {
button2.isHidden = false
}
}
I make a Google Auth for my App, but I don't know how to present a new viewController after touchup GIDSignInButton!
Here how I make GIDSignInButton:
viewDidLoad (){
let googleBtn = GIDSignInButton()
googleBtn.frame = CGRect(x: 16, y: 500 + 66, width: view.frame.width - 32, height: 35)
view.addSubview(googleBtn)}
Here's a code example that will present a second, programmatically generated view controller using a standard UIButton. Obviously, you could do the same with your GIDSignInButton:
class MyViewController: UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
let button = UIButton(frame: CGRect(x: 10, y: 250, width: self.view.frame.width - 20, height: 35))
button.setTitle("Go to VC2", for: .normal)
button.backgroundColor = UIColor.blue
button.addTarget(self, action:#selector(self.buttonClicked), for: .touchUpInside)
self.view.addSubview(button)
}
func buttonClicked(sender: UIButton!)
{
let secondViewController = MySecondViewController()
present(secondViewController, animated: true, completion: {})
}
}
class MySecondViewController:UIViewController
{
override func viewDidLoad() {
self.view.backgroundColor = UIColor.darkGray
}
}
Note, however, that if you are presenting multiple views, you are advised to embed them in a Navigation Controller, as per Apple's Documentation