As my title saying is there any way to customize default back button action method ?
I tried to find on Google but not get any answer that fulfill my requirement.
I know one way to Add UIBarButtonItem to self.navigationItem.leftBarButtonItem and customize action method but I will be hide < sign of Back button and I don't want this.
Some R&D that done by Google.
1) How to override self.navigationItem.backBarButtonItem Action?
2) iOS disable animation for NavigationController back button
3) Google Question/Answer
Add image that look like <Back button that is one way but I want to going with native way.
One option is to implement the viewWillDisappear method on the View Controller and set animationEnable No
override func viewWillDisappear(animated : Bool) {
super.viewWillDisappear(animated)
UIView.setAnimationsEnabled(false)
}
override func viewDidDisappear(_ animated: Bool) {
UIView.setAnimationsEnabled(false)
}
you have to add your custom bar button there...
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: YourDesiredFrame)
button.setImage(UIImage(named : "back"), for: .normal)
button.addTarget(self, action: #selector(backButtonTapped(_:)), for: .touchUpInside)
let barButton = UIBarButtonItem(customView: button)
self.navigationItem.backBarButtonItem = barButton
}
func backButtonTapped(_ sender : UIButton) {
_ = self.navigationController?.popViewController(animated : false)
}
// Swift 4
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// turn on animations
UIView.setAnimationsEnabled(true)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// turn off animations
UIView.setAnimationsEnabled(false)
}
Related
I would like to implement a toolbar in my tab bar or ender my tab bar like in the photo app. I show you :
Tab Bar
turn to when select button tapped
Tool bar
I already try to put the toolbar in the Tab bar controller view, without success.
Thanks for your replies !
A simple solution for this is to hide the tabBar on some event (Photos app has a button which does this). Then create a custom ToolBar and add it as a subview of the view controller.
I believe this might be the sort of behaviour you're looking for. You don't have to use a custom UIButton you could use a UIBarButtonItem, but that's up to you, I just chose to demonstrate it with a custom UIButton to show you that this is one way of doing it.
class ViewController: UIViewController {
var selectButton: UIButton!
var isInSelectMode = false
override func viewDidLoad() {
super.viewDidLoad()
selectButton = UIButton(type: .system)
selectButton.addTarget(self, action: #selector(selectButtonTapped), for: .touchUpInside)
selectButton.setTitle("Select", for: .normal)
view.addSubview(selectButton)
let trashButton = UIBarButtonItem(barButtonSystemItem: .trash, target: nil, action: nil)
toolbarItems = [trashButton]
selectButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
selectButton.trailingAnchor.constraint(equalTo: view.layoutMarginsGuide.trailingAnchor, constant: -15),
selectButton.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor, constant: 15),
])
}
#objc func selectButtonTapped() {
isInSelectMode = !isInSelectMode
if isInSelectMode {
selectButton.setTitle("Done", for: .normal)
tabBarController?.tabBar.isHidden = true
tabBarController?.tabBar.backgroundColor = .systemBackground
navigationController?.setToolbarHidden(false, animated: true)
} else {
selectButton.setTitle("Select", for: .normal)
tabBarController?.tabBar.isHidden = false
tabBarController?.tabBar.backgroundColor = .clear
navigationController?.setToolbarHidden(true, animated: true)
}
}
}
Here's what it looks like:
==> Tested in iOS 15.5
==> First your view controller must embed in UINavigationController
==> in viewDidLoad set editButtonItem to navigationItem and also configure UINavigationController native toolbarItems
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.rightBarButtonItem = editButtonItem
self.toolbarItems = [UIBarButtonItem(barButtonSystemItem: .trash, target: self, action: nil)]
}
==> After that override setEditing Method and implement your logic as required. and you are done
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.setEditing(editing, animated: true)
self.tabBarController?.tabBar.isHidden = editing
self.navigationController?.setToolbarHidden(!editing, animated: true)
}
You can check it out image here
==> But there is one issue and need further assistance... if anyone have any idea then comment bellow..
Issue : toolbar leave safeArea space and came top of that...
You can also checkout Demo Native toolbar Demo
I've a NavigationViewController which segues to a TabbedBarController. I don't want to show the back button on the TabbedBarController.
I've tried both these code snippets in Swift , neither works,
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.hidesBackButton = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.hidesBackButton = true
}
Here's a snap shot,
Here's the tabbed bar view controller,
How can I hide the back button on the Tabbed bar view controller. How can I hide the back button on my tabbed bar controller?
There are quite many ways to do what you want, but what I'm 99.9% sure that would work is that you can add a barButton in your leftBarButtonItems to replace the default backButton of your navigationController:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)]
}
Also, when overriding any lifecycle methods of a controller, you might not want to miss anything from the parent class, so don't forget to call its super equivalent like super.viewWillAppear(animated)
I hope this helps!
EDIT: Two ways to do what you want in tabBarController and since I can already picture the flow of your project.
Put the code inside the viewWillAppear of your tabBarController. This means that you might need to subclass the UITabBarController. So it should be like this:
class MyTabBarController: UITabBarController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.leftBarButtonItems = [UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)]
}
}
You should present modally your tabBarController (this is more ideal).
I understand how to set my UITableView into edit mode, and how to dynamically create an edit button:
override func viewDidLoad() {
tableView.allowsMultipleSelectionDuringEditing = true
tableView.setEditing(false, animated: false)
navigationItem.leftBarButtonItem = editButtonItem()
}
But when I tap the edit button, I would like a new button to appear on the navigation bar (i.e. a 'plus'/'add' button). To do this I think I need to create an IBAction, but I don't know how to link the editButtonItem() to an action. Any ideas?
Ok, big thanks to Ahmed and vadian for their comments, but what I got working was this:
override func setEditing(editing: Bool, animated: Bool) {
// Toggles the edit button state
super.setEditing(editing, animated: animated)
// Toggles the actual editing actions appearing on a table view
tableView.setEditing(editing, animated: true)
if (self.editing) {
navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .Add, target: self,
action: #selector(clickMe))
} else {
// we're not in edit mode
let newButton = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: navigationController, action: nil)
navigationItem.rightBarButtonItem = newButton
}
}
func clickMe()
{
print("Button Clicked")
}
As the edit button is pressed (and flips from Edit -> Done and back again) the code in the IF/ELSE statements will execute.
You can replace the default action of editButtonItem() by assigning a new function defined in your view controller to its action property.
editButtonItem().action = #selector(yourCustomAction(_:))
func yourCustomAction(sender: UIBarButtonItem) {}
I have a NavigationBar at the top of a TableView. It looks nice opening/closing the search.
However, if I click on a button in a cell and get directed to another page (with segue); and then use Back button to unwind, it seems like bugged.
()
So it looks like it is pressed and opened but it shouldn't have. It should be looked like the top picture instead (just UIBarButtonItem - search button)
I couldn't figure out the issue creating this problem.
Please note that < Back is created automatically and I didn't write any code to create it. Is there something I am doing wrong?
Update: Added some snippets...
First, created a different class for handling the search
class SearchBarViewController: UIViewController, UISearchBarDelegate {
var searchBar : UISearchBar?
var searchBarWrapper : UIView?
var searchBarButtonItem : UIBarButtonItem?
func constructSearchBar()
{
searchBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
self.navigationItem.rightBarButtonItem = searchBarButtonItem
}
func showSearchBar() {
// styling & configuration
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
UIView.animateWithDuration(0.2, animations: {
self.searchBar?.resignFirstResponder()
self.searchBarWrapper?.alpha = 0
}, completion: { (success) -> Void in
self.searchBar = nil
self.searchBarWrapper = nil
self.navigationItem.rightBarButtonItem = self.searchBarButtonItem
})
}
}
And my ViewController:
class ViewController: SearchBarViewController {
override func viewDidLoad() {
super.viewDidLoad()
constructSearchBar()
}
}
Regarding to emrys57's answer, I tried adding viewWillAppear() in my ViewController but I couldn't make it work, as my cancel looks a little different:
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
// Here, I couldn't figure out what to put because
// my searchBarCancelButtonClicked() needs searchBar and
// forces me to use (!) but then it says, it's optional..
}
The answer is...
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
navigationItem.titleView = nil
constructSearchBar()
}
You have not posted code, so it's not entirely clear what's gone wrong. Using UISearchBar, I think you must be handling the buttons separately yourself, as opposed to using UISearchController. I think that you may not be clearing away the search bar when coming back from the second VC. This code clears out the search bar in viewWillAppear:
class ViewController: UIViewController {
var cancelButton: UIBarButtonItem?
var searchButton: UIBarButtonItem?
override func viewDidLoad() {
super.viewDidLoad()
cancelButton = UIBarButtonItem(barButtonSystemItem: .Cancel, target: self, action: Selector("searchCancelPressed:"))
searchButton = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: Selector("searchPressed:"))
}
override func viewWillAppear(animated: Bool) {
super.viewDidAppear(animated)
searchCancelPressed(nil)
}
func searchPressed(sender: AnyObject) {
navigationItem.titleView = UISearchBar()
navigationItem.rightBarButtonItem = cancelButton
}
func searchCancelPressed(sender: AnyObject?) {
navigationItem.titleView = nil
navigationItem.rightBarButtonItem = searchButton
}
}
and that is working nicely for me when I do a push from a button to the second VC and then hit back.
Following the edit to the original question, this code seems to work, although it may not be the most elegant way of constructing the answer:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationItem.titleView = nil
searchBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
navigationItem.rightBarButtonItem = searchBarButtonItem
}
The function constructSearchBar no longer needs to be called in viewDidLoad, and can be deleted.
I want to have a back button on the second view controller I have. When it loads now, it does show the back button but I want to change the title from Back to something else. I implemented to viewWillAppear method where I invoke showing the navigation bar.
The following didn't work:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
self.navigationController?.navigationBar.hidden = false
self.navigationController?.navigationBar.backItem?.title = "Something Else"
}
Please help me change the title. Should it be in the willAppear or viewDidLoad?
Add this right before the push or popViewController statement in your first view:
let backButton = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = backButton
Or you can do it in your second view this way:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated);
let backButton = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = backButton
}
Ksa_coder I have tried the solution for your question and finally I got.You want to add the below coding in second view controller in viewWillAppear method
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated);
var btnBack = UIBarButtonItem(title: "Something Else",style: UIBarButtonItemStyle.Plain ,target: nil,action: nil)
self.navigationController!.navigationBar.topItem!.backBarButtonItem = btnBack
}