I'd like to implement navigation drawer like Uber into iOS(swift). I'm going to achieve it by using a library, called KYDrawerController. https://github.com/ykyouhei/KYDrawerController
However, it cannot provide toggle button, only slide action. Thought I'd like to to implement toggle button that shows the navigation drawer,I have no idea how to add such a function to the library.
If you know how to add the function to the library, or how to achieve my purpose the other way(such as to use the other libraries), please tell me.
Thank you for your kindness.
Using KYDrawerController it can be implemented as follows:
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = UIColor.whiteColor()
title = "MainViewController"
navigationItem.leftBarButtonItem = UIBarButtonItem(
title: "Open",
style: UIBarButtonItemStyle.Plain,
target: self,
action: "didTapOpenButton:"
)
}
func didTapOpenButton(sender: UIBarButtonItem) {
if let drawerController = navigationController?.parentViewController as? KYDrawerController {
drawerController.setDrawerState(.Opened, animated: true)
}
}
}
https://github.com/ykyouhei/KYDrawerController/tree/master/Example/Code
Related
I've been creating a small iOS app using Swift just for fun, and I have already decided that I want a notification box (a bell-shaped button you can click on to check if there's any notification), and I also wanted to add the bell-shaped button to every screen.
So, I decided to make a base view controller and have other view controllers inherit it. However, that's when my problem arose; I have no idea how to add an action func for that button. Since I create the bell-shaped button programmatically, I cannot just ^ drag and create a new IBaction.
I found this post: link, but this is for a UIButton, not for a UIBarButton, and it didn't work for me.
Sorry for this long question. Below is a simple, one-sentenced question:
MY PROBLEM
How can I add an action to a UIBarButton programmatically?
UPDATE
Here's my base view controller:
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// add a notification button
let notificationButton = UIBarButtonItem(image: UIImage(systemName: "bell.fill"))
notificationButton.tintColor = .black
self.navigationItem.rightBarButtonItem = notificationButton
}
}
UPDATE2
Here's my new code:
import UIKit
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// add a notification button
let notificationButton = UIBarButtonItem(
image: UIImage(systemName: "bell.fill"),
style: .plain,
target: self,
action: #selector(notificationButtonPressed)
)
notificationButton.tintColor = .black
self.navigationItem.rightBarButtonItem = notificationButton
}
#objc func notificationButtonPressed() {
print("Hello")
}
}
You can pass a target-action pair to the initialiser of UIBarButtonItem:
let barButton = UIBarButtonItem(
image: UIImage(systemName: "bell.fill"),
style: .plain,
target: self, action: #selector(buttonTapped)
)
// somewhere in your view controller:
#objc func buttonTapped() {
// do something when the bar button is tapped
}
See the documentation here.
This is similar to UIButton's addTarget(_:action:for:_) method, if you are familiar with that.
Update: This bug has been fixed in iOS 14.5
I have the following class embedded in a UINavigationController:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let barButton = UIBarButtonItem(title: "Save", style: .plain, target: nil, action: nil)
barButton.accessibilityLabel = "Save meeting"
navigationItem.rightBarButtonItem = barButton
}
}
When running iOS 14.4, the accessibility label is ignored and only the visible title is announced by VoiceOver. However, on iOS 13.7, the accessibility label is correctly used. Has the UIBarButtonItem usage changed or is this an iOS bug?
Screenshot for context:
When I must implement a UIBarButtonItem, I always follow these instructions to be sure that a11y will be stable and completely functional. 👍
I don't know if this situation is a bug or a kind of regression due to the new iOS version but implementing a11y in the navigation bar buttons as customization is a perfect way to encounter no unfortunate surprises even if it looks like a boilerplate solution. 🤓
I've created a blank project with a simple view controller embedded in a navigation controller where a right bar button is displayed as follows:
class NavBarViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
var a11yRightBarButton: UIBarButtonItem?
let a11y = UILabel()
a11y.text = "OK"
a11y.sizeToFit()
a11y.isUserInteractionEnabled = true //Mandatory to use the 'tap gesture'.
a11yRightBarButton = UIBarButtonItem(customView: a11y)
let tap = UITapGestureRecognizer(target: self,
action: #selector(validateActions(info:)))
a11yRightBarButton?.customView?.addGestureRecognizer(tap)
a11yRightBarButton?.isAccessibilityElement = true
a11yRightBarButton?.accessibilityTraits = .button
a11yRightBarButton?.accessibilityLabel = "validate your actions"
navigationItem.rightBarButtonItem = a11yRightBarButton
}
#objc func validateActions(info: Bool) -> Bool {
print("hello")
return true
}
}
Your right bar button displays "OK" and VoiceOver reads out "validate your actions" under iOS 14.4 and Xcode 12.4. 😉
Following this rationale, you can use a UIBarButtonItem as supporting the accessibilityLabel property in iOS 14. 🎉
Set accessibility of UIBarButtonItem to true.
let barButton = UIBarButtonItem(title: "Save", style: .plain, target: nil, action: nil)
barButton.accessibilityLabel = "Save meeting"
barButton.isAccessibilityElement = true
navigationItem.rightBarButtonItem = barButton
I am new to swift , I have a very simple question. I implement a navigation controller with two items at top like this
I did this by adding a navigation controller to the project and then adding this lines of code in to the viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
self.title = ""
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .add, target: self, action: Selector(("barButtonItemClicked:"))), animated: true)
}
now my question is about how to open a new view controller I mean a new page after clicks on plus (+) button at the navigation bar. I searched a lot but did not find any exact thing relate to this. Appreciate you if possible help me. thank you
Your code should be like this one:
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, style: .plain, target: self, action: #selector(performToVC))
#objc func performToVC() {
performSegue(withIdentifier: "vc", sender: self)
}
Here is code for Push TO OTherView Controller
#objc func PoushTOHistoryVC() {
let secondViewController = self.storyboard?.instantiateViewController(withIdentifier: "HistoryViewController") as! HistoryViewController
self.navigationController?.pushViewController(secondViewController, animated: true)
}
here is Button for Add
self.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(PoushTOHistoryVC)), animated: true)
you need to add HistoryViewControlle to Stroyboard ViewController HistoryViewControlle and Don't forget
First you have to create new view controller which you have to open on that plus (+) button at the navigation bar. After creating new view controller you have to press and hold the control key on the keyboard and the click on the (+) button at the navigation bar and drag it to the new view controller and then release the click button image for reference, then it will show you a pop up with options such as show, show details etcimage for reference, select show option.
I have this below code that changes the back button image on next screen.
I have 30 screens in my app and i want back button to be same across all 30 screens. Is it possible that I don't copy paste this code on all 30 screens and just write it once and rather reuse it across 30 screens.
Also, the code attached with back button should work fine on all screens when i reuse it
I am using iOS 8 and Xcode 6.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let backButtonImage: UIImage = UIImage(named: "back")!
var backBarItem: UIBarButtonItem = UIBarButtonItem(image: backButtonImage, style: UIBarButtonItemStyle.Plain, target: self, action: Selector("method"))
segue.destinationViewController.navigationItem.leftBarButtonItem = backBarItem;
}
func method() {
self.navigationController?.popViewControllerAnimated(true)
}
You can change it globally
UINavigationBar.appearance().backIndicatorImage = UIImage(named: "custom-back")
UINavigationBar.appearance().backIndicatorTransitionMaskImage = UIImage(named: "custom-back")
Or per navigation controller.
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.backIndicatorImage = UIImage(named: "custom-back")
navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "custom-back")
}
Full detail here https://sarunw.com/posts/how-to-change-back-button-image/
To general change the appearance of UI-Elements in iOS look at UIAppearance. This way you can set it once and it will be everywhere in your app.
I would recommend setting it in the AppDelegate application:didFinishLaunchingWithOptions:.
Try this:
let backImg: UIImage = UIImage(named: "back")!
UIBarButtonItem.appearance().setBackButtonBackgroundImage(backImg, forState: .Normal, barMetrics: .Default)
I only have one navigation Controller in my app, so this may or may not be helpful. But, I created a subclass of UINavigationController. Then in this subclass, I override the pushViewController method:
override func pushViewController(_ viewController: UIViewController, animated: Bool) {
let pushingVC = viewControllers[viewControllers.count - 1]
let backItem = UIBarButtonItem()
backItem.title = ""
pushingVC.navigationItem.backBarButtonItem = backItem
super.pushViewController(viewController, animated: animated)
}
This, makes it so every time a viewController is pushed, from my customNavigationController, it uses the custom back button for every view. You have to make sure you change your UINavigationControllers type to your custom Subclass. But, this works for me in Swift 3.0.
You could use appearance()
Swift
let backImage = UIImage(named: "back")
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor:
UIColor.white], for: .normal)
UIBarButtonItem.appearance().tintColor = UIColor.green
I'm not quite sure what you wanted, so I'll answer most of what I think you could want for your sake and anyone looking at this in the future.
First: You want a back button similar to those on default apple apps. To do so, you need to a) get a reference to the destination scene and it's view controller. I will assume you have done so and set it equal to controller for future reference. b) You need to set the left bar button item. Set it with:
controller.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Insert Title Here!!", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
Place all of this in prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) (you will also find the destination scene with this, likely with segue.destinationViewController
Second: You want to use an image named "Back" for all items. If so, repeat step a) above, and insert this handy bit of code:
UIBarButtonItem(image: "Back", style: UIBarButtonItemStyle.Plain, target: nil, action: nil)
I also know you want to not have to copy it, but it's not as if this is that computer intensive anyways and it's probably simplest.
Third: You're smart and don't hate advances in programming so you want to use a storyboard. If so, simply drag in a Navigation Bar from the object menu, add a navigation item, and copy it to all of your scenes. If your scenes are linked to custom classes, then super happy fun time good news, you can simply link the navigation item to your custom class through an IBAction and use that function to do all the fancy coding your heart could ever desire.
Fourth: You really, really don't want to copy anything even if it's not that hard. If so, you can subclass a UIViewController with your own custom class, add the code I mentioned above, and then subclass all your future UIView classes as this. To be honest, I'm not entirely sure this would work and it seems unnecessarily laborious, but it's up to you.
I'm a bit tired right now so sorry for all the things I'm finding funny, but I hope I helped, and please tell me if I missed your point entirely and I can try and think of a solution.
I am familiar with this code: self.navigationItem.leftBarButtonItem = self.editButtonItem.
See this code:
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tblTasks: UITableView! // declaring this allows you to reload the tableView to update your items
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
I have the code that allows for the edit button to be present, yet no edit button is to be seen in my app nor the storyboard.
I am a Swift beginner, if someone could point me in the right direction that would be awesome.
The stock "Edit" button is only available on UITableViewController. For other view controller types you'll have to create a button yourself.
If you add it into navigationItem you should embed that view controller into UINavigationController to see that button.
You will not see that button in Storyboard because you set it in code. In Storyboard you setup only initial state of the controller.
How to setup editing mode in UIViewController subclass:
There is editButtonItem variable in UIViewController. If you add it on screen, setEditing(_:,animated:) will be triggered when user tap that button.
Also it will change button text between Edit and Done according to ViewController's isEditing state.
You can get current state from self.isEditing
Do not forget to call super.setEditing(_:animated:), or it will not change state of the button and view controller.
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
// custom code to handle edit mode
}
editButtonItem (iOS 10.0+)
isEditing (iOS 2.0+)
setEditing(_:animated:) (iOS 2.0+)
You can create your own edit button, like:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .Plain, target: self, action: Selector("editTableView"))
And then:
func editTableView()
{
if self.navigationItem.rightBarButtonItem.title == "Edit"
{
self.navigationItem.rightBarButtonItem.title = "Done"
//edit your tableView Here!
}
else
{
self.navigationItem.rightBarButtonItem.title = "Edit"
//when youre finishing editing
}
}