drop down menu on navigation bar - ios

In android, there is action bar with drop down menu, an example is the old Gmail app in Android:
As you see above, when the three-dots is clicked, a drop down menu is shown.
My Questions:
I am wondering, if I want to implement the same three-dots button which shows drop down menu in iOS with Navigation Controller, how to do it?
If it is not a common thing to do in iOS, what is the equivalent in iOS?
(I still want to implement it in my iOS project though)

There is no built-in UI component for this in iOS, and it's not widely used in apps.
But when I need to implement it I usually use AssistoLab DropDown, it's a very easy to use, well-documented and stable library.

The closest I can think of is UIPopOverController for iPad.
You can put a tableview in a "popover".
Sample popover
For iPhone Popover visit this tutorial
https://richardallen.me/2014/11/28/popovers.html

That not an iOS thing. BUT that been said, the best approach would be to have do a PopOver. Here theres a good answer for a PopOver
Here theres a framework that do all the work for you.
Any here theres another good answear with a popOver
Also you can just create a simple View. And when u display it, just do an animation on the view height constraint to animate the growing.

What was answered before is not true anymore. Now there are context menus.
With iOS13 there was UIMenu introduced and with iOS14 UIBarButtonItem has a menu property for that you can set a UIMenu. The menu you set there, will pop up when tapping the UIBarButtonItem. (see also https://developer.apple.com/documentation/uikit/uibarbuttonitem/3601188-menu)
You do not need to set any other action on the UIBarButtonItem (see line before last line in my sample code, action is nil).
Here is an example for having a rightBarButtonItem triggering a menu with four items.
let menuHandler: UIActionHandler = { action in
print(action.title)
}
let barButtonMenu = UIMenu(title: "", children: [
UIAction(title: NSLocalizedString("Identify Plant", comment: ""), image: UIImage(systemName: "viewfinder"), handler: menuHandler),
UIAction(title: NSLocalizedString("Plant's diary", comment: ""), image: UIImage(systemName: "books.vertical"), handler: menuHandler),
UIAction(title: NSLocalizedString("Plant's notifications", comment: ""), image: UIImage(systemName: "bell"), handler: menuHandler),
UIAction(title: NSLocalizedString("Remove plant", comment: ""), image: UIImage(systemName: "trash"), handler: menuHandler)
])
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Manage", style: .plain, target: self, action: nil)
navigationItem.rightBarButtonItem?.menu = barButtonMenu
// or using the initializer
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Manage", image: nil, primaryAction: nil, menu: barButtonMenu)
My answer is based on this great sample code article: https://developer.apple.com/documentation/uikit/uinavigationcontroller/customizing_your_app_s_navigation_bar

Related

Swift Program button action viewcontroller

I am wondering how do I get the following programmable button to action when pressed to go to another viewController.
Currently the button calls a function in the same view controller but I want it to go to SocialLoginViewController as Apple rejected my app because it does not allow Apple Signin so I need to change my app to allow that.
let rightBarButton = UIBarButtonItem(title: "Person", style: UIBarButtonItem.Style.done, target: self, action: #selector(FirstViewController.checkLogin(_:)))
rightBarButton.image = buttonIcon
self.tabBarController?.navigationItem.rightBarButtonItem = rightBarButton
So I am wondering what do I need to change to get the action to load
SocialLoginViewController

Not able to change right navigation button title

I set up a right navigation button like so inviewWillAppear in . a class ChatMessageViewController..
let button2 = UIBarButtonItem(image: nil, style: .plain, target: self, action: #selector(blockPressed(sender:)))
button2.title = "Block"
self.navigationItem.rightBarButtonItem = button2
Now on the click of blockPressed another shared function is called like so...
#objc fileprivate func blockPressed(sender: UIButton) {
XMPPConfig.shared.blockUser(userJID: theUserJID!) //XMPPConfig is another class having some common functions and delegate methods.
}
(This function basically blocks a certain user like blocking a whatsapp user. Once blocking happens, certain delegate methods are called. One such delegate method after which I change the Block button is given as follows..)
func xmppBlocking(_ sender: XMPPBlocking!, didBlockJID xmppJID: XMPPJID!) {
print("successfully blocked!")
ChatMessageViewController.shared.setupUnBlock()
}
Doing this also properly calls setupUnBlock() function in ChatMessageViewController like so...
func setupUnBlock() {
if XMPPConfig.shared.sectionGroupsFlag == false {
let button2 = UIBarButtonItem(image: nil, style: .plain, target: self, action: #selector(unblockPressed(sender:)))
button2.title = "Unblock"
self.navigationItem.rightBarButtonItem = button2
}
}
But the button title still remains unchanged...i.e. it is still "Block"..what could be the reason for this...?
You should initialize your UINavigationBarButton using another initializer:
let right = UIBarButtonItem(title: "Some title", style: .plain, target: self, action: #selector(rightNavBarButtonPressed))
You are using UIBarButtonItem(image:... instead.
I tried to duplicate your code and apparently everything works.
So, the problem may be due to three possible problems, as far as i can see.
it may be thread problem. This is unlikley unless you have not turned on the thread checker in xcode.. But inside both unblock and block codes, enter
print(Thread.current)
to see both blocks of codes in setting the rightbarButton is in main thread. If not, you should know how to solve them.
It may be view update problem, unlikely still, but worth a try.. So in your block of codes where you are adding rightBarButton, add one more line of code.
self.navigationController?.viewIfLoaded?.setNeedsLayout()
to update the navigationController's view after you have set the rightBarButtonItem.
The most likely problem in my opinion is that, you have been doubling calling block barButtonItem codes. This means when you have called unblock barButtonItem setup codes, you accidentally called the block barButtonItem too.
To debug this is easy, you just put a statement in each of block of the codes, to see if they appear together.

How to change Back button text from within the child view controller?

I know that you can set the title of the back button from the IB or in prepareForSegue, but in my app I need to update the title according to events that can happen while the controller is visible.
I tried but nothing happens:
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: title, style: .Plain, target: nil, action: nil)
This works though but has no back arrow:
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: title, style: .Plain, target: nil, action: "popVC")
Any ideas?
The backBarButtonItem is the item used for the back button of the next controller in the navigation stack.
So for example if you have a navigation controller with a root viewController A and you push a viewController B, then the back button title that you see once B is pushed is configured using A.
You could have something like this :
A.navigationItem.backBarButtonItem = UIBarButtonItem(title: "Go back to A", style: .Plain, target: nil, action: nil)
Once B is pushed, you see a back button with "Go back to A".
In your case the tricky part is to find A in the navigation stack from B.
You can do it by searching in the viewControllers of the navigationController like so :
// This code works from the `B` view controller
let viewControllers = self.navigationController?.viewControllers ?? []
if let indexOfCurrent = viewControllers.indexOf(self) where (indexOfCurrent > viewControllers.startIndex) {
let indexOfPrevious = indexOfCurrent.advancedBy(-1)
let previousViewController = viewControllers[indexOfPrevious]
previousViewController.navigationItem.backBarButtonItem?.title = "New Title"
}
Edit
I don't know any clean way to refresh the navigation bar after that. Maybe you could ask a separate question just for that.
What you could do is pop and push the view controller without animation
if let navigationController = self.navigationController {
navigationController.popViewControllerAnimated(false)
navigationController.pushViewController(self, animated: false)
}
Or maybe try to create a new UIBarButtonItem instead of changing the title of the existing one.
try this:
let baritems = self.navigationController?.navigationBar.items
for item in baritems!{
if (item.leftBarButtonItem != nil){
item.title = "123"
}
}
This question is pretty old now, but I was a problem changing the back button text based on a nested tableViewController's selected cell.
It looks like the default back button for a navigationViewController bases its text on the title of the view controller it takes the user back to.
You should probably be careful, as my solution makes a couple assumptions that I'm not positive will always be true.
let vcs = navigationController?.viewControllers
vcs?[(vcs?.count)! - 2].navigationItem.title = "Your Text Here"
Assuming that our current view controller is at the top of the navigation stack -> vcs[vcs.count - 1]; there exists a view controller on that stack before this one -> vcs[vcs.count - 2]; and the navigationItem.title of that preceding view controller can be changed without unwanted side effects; we can change our back button text by changing the navigation title of that preceding view controller.

implement a simple back button swift ios

I have a navigation bar placed directly on my scene. On his I have a navigation item. I can successfully change title on it.
Now I want a back button to appear - I do not need any customization at present, just the ability to catch the click and default ios look for whatever plaform the app is running (Since Swift that is ios7+).
In viewDidLoad() I have written
outletCatalogNavItem.backBarButtonItem = UIBarButtonItem(title: "test", style .plain, target: self, action: "ownbackNavigationFuncCode");
In *ViewDidAppear()* outletCatalogNavItem.backBarButtonItem is non-nil
Note: I am not using any shared navigation control across scenes in my storyboard - nor wish to at this point since I am porting an app from another tool/language which has its own navigation/stack logic already (meaning I handle switching and navigation myself in code)
Embed your view controller in a UINavigationController. When you push/segue to a new view controller the < Back button you're looking for will appear on the left hand-side.
let backItem = UIBarButtonItem()
backItem.title = "Back"
navigationItem.backBarButtonItem = backItem

Selector not working on my swift UIBarButtonItem

I'm writing a to-do list type app, in order to learn swift for iOS development. I had a settings button on the Navigation bar, on the right side, and whenever a person clicked a button on top of the table view, they could add a new item to their list. That causes a "cancel" button to appear on the left side of the bar and a "add" button to appear on the right side. When the person is done, however, those buttons disappear, and so I programatically re-create the settings button, with a call to a function that is supposed to call the segue.
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "modify"), style: UIBarButtonItemStyle.Plain, target: nil, action: Selector("showSettings:"))
This is the code that creates the button on the navbar (and it is indeed created)
func showSettings(sender: AnyObject?) {
print("segueShouldBeDone!")
performSegueWithIdentifier("showSettings", sender: sender)
}
And this is the function that is supposed to call the segue (I added the print to see if it was at least being called, and it isn't).
I've had this same problem in another place in my code, but I had given up on fixing it cause it wasn't that important for me then. But now it is interfering with how the app works, so I wanted to know how to fix it.
Any help would be great.
Your showSettings: selector isn't being called because you specified nil instead of self for the bar button item's target. Change the line to:
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "modify"), style: UIBarButtonItemStyle.Plain, target: self, action: Selector("showSettings:"))
This assume the showSettings: method is in the same class that contains this line of code.
Read the documentation for this initializer, specifically the info about the target parameter.

Resources