I'm implementing a photo gallery via a UIPageViewController subclass (called GalleryController) embedded in a UINavigationController. The navigation bar hides when I tap, but the animation is odd:
https://www.youtube.com/watch?v=9SLF3Nq3uNE
Here's the code in GalleryController:
override var navigationItem: UINavigationItem {
let item = super.navigationItem
// Access super and add items to it.
// Don't create a new UINavigationItem instance — that breaks the back button.
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = touchSize / 2
item.rightBarButtonItems = [
UIBarButtonItem(title: "All Photos", style: .plain, target: self, action: #selector(showAllPhotos)),
space,
UIBarButtonItem(title: "Delete", style: .plain, target: self, action: #selector(deletePhoto))
]
return item
}
This problem started occuring only after the page view controller was introduced.
What's causing this, and how do I fix it?
The solution turned out to be to do the following in the init of the UIPageViewController subclass:
automaticallyAdjustsScrollViewInsets = false
I don't know why it works, but it does.
I was earlier doing this in the child view controller (that represents a single page of the page view controller), but that wasn't working.
Related
I have three screen as below, now i go from the list of hotels to their detail view and from their to the ratings page, i perform the ratings and come back to detail page with ratings added, but now however , if i were to use the back button the navigation takes me back to ratings page instead of main page with hotels list , can any one please suggest how to avoid it ...
A->B->C but when coming back C->B but now B->C instead of B->A
SOLVED
So here is the mistake i was making
let backimage = UIImage(named: "back")
navigationController?.navigationBar.backIndicatorImage = backimage
navigationController?.navigationBar.backIndicatorTransitionMaskImage = backimage
navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: self, action: #selector(handleBackButton))
I was trying to hit the navigation bar back button item and make it do the work, it would reset back to default, what i need was to target navigationItem and not navigationcontroller, which i did and now from my handler it goes to root controller like below
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "", style: .done, target: self, action: #selector(handleBackButton))
navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(handleBackButton))
#objc func handleBackButton() {
_ = navigationController?.popToRootViewController(animated: false)
}
Following scenarios code u can use:
1) C->B or B->A
self.navigationController?.popViewController(animated: true)
2) C->A
self.navigationController?.popToRootViewController(animated: true)
If you are using navigationController, to pop back manually you have to use.
_=self.navigationController?.popViewController(animated: true)
For pop to a specific view controller you have to use
self.navigationController?.popToViewController(yourViewController, animated: true)
But before this you have to confirm that the navigation array contains the view controller to pop.
But this is not required for default navigation back button.
I think your issue is with pushing view controller to navigationController.
Please refer the codes for push:
self.navigationController?.pushViewController(yourViewController!, animated: true)
Note: pop will not work with presentViewController
I am creating a project where I need to have a default back button and custom filter button on the left side of the navigation bar.
I have created custom back button, custom filter button and add both of them to leftBarButtonItems
navigationItem.leftBarButtonItems = alignedLeftBarButtonItems()
func alignedLeftBarButtonItems() -> [UIBarButtonItem] {
let filterButton = createLeftCustomBarButton()
// back button creation
let backButton = UIBarButtonItem(image: R.image.navBackArrow(), style: .plain, target: self, action: #selector(self.backButtonPressed(_:)))
backButton.tintColor = UIColor.white
let barButtonsItems = [
backButton,
UIBarButtonItem(customView: filterButton)
]
return barButtonsItems
}
Things are fine and working.
Concern:
Default, User can go to the previous VC by sliding from left to
right. This functionality is lost in making this. Is there a way I can
have both buttons with the sliding functionality.
You need to use UIBarButtonItem to use default left or right swipe functionality for back button:
let backButton = UIBarButtonItem(image: Image.backButton, style: UIBarButtonItemStyle.plain, target: self, action: #selector(actionBackButton))
self.navigationItem.leftBarButtonItem = backButton
With Custom button, you cannot get this functionality
My app requires me to add multiple buttons in my navigation bar.
Here is an image of what my nav bar looks like
How do i achieve this type of design?
You can configure your view controller's navigationItem in various ways to achieve this design.
Left side
To allow additional buttons next to the system "back button" on the left:
navigationItem.leftItemsSupplementBackButton = true
This allows you to add a left bar button item for the circular image:
navigationItem.setLeftBarButtonItem(imageItem, animated: trueOrFalse)
imageItem would be a UIBarButtonItem initialized with a customView or image, as discussed in some of the other answers here.
For the back button itself, to achieve a simple "<" without showing the title of the previous view or showing "< Back", you can open the storyboard and set the Back Button text of the previous view controller to a single space, as described in this post.
Title area
For the title area, as discussed in the other answers:
navigationItem.titleView = (a custom view)
Right side
For the right side, you can add multiple buttons:
navigationItem.setRightBarButtonItems([button1, button2, button3, button4], animated: trueOrFalse)
Here, button1, button2, button3, and button4 are each UIBarButtonItems. You would likely initialize these buttons with images.
Looks like you also will want to set the tintColor of the navigation bar to black, so that the bar buttons are rendered in black:
navigationController?.navigationBar.tintColor = .black
All of this code would be done in the view controller, usually in viewDidLoad, unless you need to dynamically change which buttons are shown as the content of your view controller changes.
Try this:
let callImage = UIImage(named: "call")!
let videoImage = UIImage(named: "video")!
let searchImage = UIImage(named: "search")!
let callButton = UIBarButtonItem(image: callImage, style: .plain, target: self, action: #selector(didTapCallButton))
let videoButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapVideoButton))
let searchButton = UIBarButtonItem(image: searchImage, style: .plain, target: self, action: #selector(didTapSearchButton))
navigationItem.rightBarButtonItems = [callButton, videoButton, searchButton]
Selector methods
func didTapCallButton(sender: AnyObject){
...
}
func didTapVideoButton(sender: AnyObject){
...
}
func didTapSearchButton(sender: AnyObject){
...
}
You can create your own view and put down your Images, Labels, etc...
After that, you write:
self.navigationItem.titleView = yourView
UINavigationItem has a property called rightBarButtonItems, this expects an array of UIBarButtonItem which would in your case be each of your buttons.
You can use the initialiser on UIBarButtonItem to specify the image and style:
init(image: UIImage?, style: UIBarButtonItemStyle, target: Any?, action: Selector?)
Initializes a new item using the specified image and other properties.
On your view controller you can access the navigation item through the accessor navigationItem, if you embed your view controller inside a UINavigationController you will need to access the navigationItem on that instance and not the view controller.
You can Add UIView in navigation bar so that you can add multiple buttons in that view.
I'm having
a problem getting a button to show on a navigation controller. I have researched this and I think it has to do with how navigation works. Pushed and Popped from a stack.
Here is what I have:
I have the initial view as a navigation controller. This controller calls several views but the view that I'm having an issue with is a UICollectionViewController. This is called from a button click on the first viewController connected to the navigationController. I then have a segue setup that goes from the UICollectionViewCell to a new ViewController. So I'm assuming this is a second level NavigationController.
Secondly I have a Back Button Image that is displayed on my navigation instead of the text < Back.
The back button shows fine in the navigation controller on all the views except for the one called from the second level segue.
As I understand from reading other posts on this topic it is because a new navigation Controller is created on the second level segue.
I'm fine with that because everything works fine but I need the button to show on that second navcontroller.
I was trying to programmatically add the button to the navigation controller associated with the current view. I am using this code:
override func viewDidLoad() {
super.viewDidLoad()
var image = UIImage(named: "NavLogo")
var back_image = UIImage(named: "BackButton")
image = image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
back_image = back_image?.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.plain, target: nil, action: nil)
self.navigationController?.navigationItem.leftBarButtonItem = UIBarButtonItem(image: back_image, style: UIBarButtonItemStyle.plain, target: nil, action: nil)
}
This code does not seem to add the button to the current navigation controller.
This project is using Swift 3 and Xcode 8
Use
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.plain, target: nil, action: nil)
instead of
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.plain, target: nil, action: nil)
The reason for this is explained in this link.
I have a UIViewContoller that is intentionally NOT embedded in a UINavigationController and I want to add custom buttons in the navigation area. I believe the code I've written should work because it follows the suggested method I found on several threads about UIBarButtonItem (these mostly have to do with styling though). Here's my code:
override func viewDidLoad() {
super.viewDidLoad()
let settingsButton = UIBarButtonItem(title: "Settings", style: .Plain, target: self, action: #selector(self.segueToSettings(_:)))
let saveToLogButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(self.logThisLift(_:)))
let viewLogButton = UIBarButtonItem(title: "Log", style: .Plain, target: self, action: #selector(self.segueToLog(_:)))
self.navigationItem.leftBarButtonItem = settingsButton
self.navigationItem.rightBarButtonItems = [viewLogButton, saveToLogButton]
}
and here's the result (with the View hierarchy visible too):
I thought perhaps I needed to add Bar Button Items in the Storyboard but that would seem to defeat the purpose of doing it in code like I'm trying to do.
I've tried debugging the view hierarchy as well and I don't see them there.
Does anybody know why these wouldn't be appearing?
In your code you use self.navigationItem but you don't have a navigation item since your controller is not embedded in navigation controller.
You already added a navigation bar but you need to add a navigation item.
You have to drag a navigation item to the navigation bar and then binding to the code (via an outlet). It should be like this after that:
#IBOutlet weak var navItem: UINavigationItem!
And then you can say:
self.navItem.leftBarButtonItem = settingsButton
self.navItem.rightBarButtonItems = [viewLogButton, saveToLogButton]
You should see it in the document outline like this: