I have a problem regarding swipe back gestures in swift. After I push the new uicollectionviewcontroller when certain cell is pressed at the parent uicollectionviewcontroller, I swipe back to the parent viewcontroller. But only a few navigationitems appear on the navigation bar. However, when I go back by pressing the "back" button, all the navigation items appear. Here's my code:
override func viewDidLoad() {
setupNavBarButtons()}
func setupNavBarButtons(){
let flexible = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil)
flexible.isEnabled = false
let logoImg = UIImage(named: "wee")?.withRenderingMode(.alwaysOriginal)
let homeBarButtonItem = UIBarButtonItem(image:logoImg, style: .plain, target: self, action: #selector(handleHome))
homeBarButtonItem.isEnabled = false
let cameraImg = UIImage(named: "nav bar_circles")?.withRenderingMode(.alwaysOriginal)
let cameraButtonItem = UIBarButtonItem(image:cameraImg, style: .plain, target: self, action: nil)
cameraButtonItem.isEnabled = false
navigationItem.rightBarButtonItems = [flexible, cameraButtonItem, flexible, cameraButtonItem, flexible, cameraButtonItem]
navigationItem.leftBarButtonItems = [flexible, cameraButtonItem, flexible, cameraButtonItem, flexible, cameraButtonItem, flexible, homeBarButtonItem]
navigationItem.accessibilityElementsHidden = false
navigationController?.hidesBarsOnSwipe = false
navigationController?.isNavigationBarHidden = false
}
func showAppDetailForApp(pht: UIImage){
let layout = UICollectionViewFlowLayout()
let detailLauncher = ShowPhoto(collectionViewLayout: layout)
detailLauncher.info = pht
navigationController?.navigationBar.barTintColor = UIColor.white
navigationController?.pushViewController(detailLauncher, animated: true)
}
Thanks in advance.
Please Set below code line in your pushed view controller's viewDidLoad() method.
self.navigationController.interactivePopGestureRecognizer?.isEnabled = false
Related
I have a viewController that's embedded in a navigationController. From my viewController I programmatically add three UIBarButtonItem and a UISearchBar. Under the navigationbar I have a WKWebView that is covering the whole screen. The issue it that the UIBarButtonItems doesn't respond to any clicks before I've taped or in any way interacted with the WKWebView. After I tap or scroll the WKWebView the UIBarButtonItems work fine until I perform a search in the UISearchBar. The UIBarButtonItems stops responding again until I interact with the WKWebView.
I have tried adding navigationController?.navigationBar.becomeFirstResponder() in DidAppear and in searchBarTextDidEndEditing as suggested on some forum post. It has no effect on the issue.
This is what I do in DidLoad to initiate the navbar:
self.navigationController?.setNavigationBarHidden(false, animated: true)
searchBar.delegate = self
searchBar.sizeToFit()
searchBar.setImage(UIImage(named: "ssl"), for: .search, state: .normal)
searchBar.searchBarStyle = .minimal
searchBar.showsCancelButton = false
let textField = searchBar.value(forKey: "searchField") as? UITextField
textField?.textAlignment = .center
textField?.leftViewMode = UITextField.ViewMode.never
textField?.clearButtonMode = UITextField.ViewMode.whileEditing
textField?.keyboardType = .URL
textField?.autocapitalizationType = .none
textField?.leftView?.contentMode = .scaleAspectFit
let back = UIBarButtonItem(image: UIImage(named: "back"), style: .plain, target: self, action: #selector(naviagteBack))
let forward = UIBarButtonItem(image: UIImage(named: "forward"), style: .plain, target: self, action: #selector(naviagteForward))
let reload = UIBarButtonItem(image: UIImage(named: "reload"), style: .plain, target: self, action: #selector(navigateReload))
navigationItem.titleView = searchBar
reload.tintColor = .black
navigationItem.rightBarButtonItem = reload
back.tintColor = .lightGray
forward.tintColor = .lightGray
navigationItem.leftBarButtonItems = [back, forward]
I want the UIBarButtonItems to be active all of the time. Not just after I interact with the WKWebView. And no, it has nothing to do with the capabilities of goBack() e.t.c. I have added print("!") to the button functions and it outputs nothing while in the "unactivated" state.
I am trying to make a custom back button using this code:
let back = UIImage(named: "header_backarrow")
let backView = UIImageView(image: back)
let backItem = UIBarButtonItem(customView: backView)
navigationItem.leftBarButtonItem = backItem
I want the navigation item to perform this code:
func dismissManual() {
dismiss(animated: true, completion: nil)
}
I have tried many things like following this Stack Overflow post: Execute action when back bar button of UINavigationController is pressed
I have also tried making it a navigationItem.backBarButtonItem; however, nothing seems to work. Some things show the correct custom image, but do not work as a button; on the other hand, some work as a button, but do not show the correct image.
Does anybody know how I can show the correct image and make the item work as a button? Thanks.
Do it as follows:
override func viewDidLoad() {
super.viewDidLoad()
let back = UIImage(named: "header_backarrow")
let backView = UIImageView(image: back)
backView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissManual))
backView.addGestureRecognizer(tap)
let backItem = UIBarButtonItem(customView: backView)
navigationItem.leftBarButtonItem = backItem
}
#objc func dismissManual() {
print("print----")
// dismiss(animated: true, completion: nil)
}
Add gesture to backView it will work!
It's similiar to this question IOS - Swift - adding target and action to BarButtonItem's customView
Swift 4.1
The issue is that UIImage does not have tap recognition. You will have to add a tap gesture recognizer to your backView.
lazy var singleTap: UITapGestureRecognizer = {
let singleTap = UITapGestureRecognizer(target: self, action: #selector(tapDetected))
singleTap.numberOfTapsRequired = 1
return singleTap
}()
// Actions
#objc func tapDetected() {
dismiss(animated: true, completion: nil)
}
If you show your code, with some screenshots I can give more help if this doesn't solve the issue.
You are creating your UIBarButtonItem incorrectly. You do not need the image view.
Do it as follows:
let back = UIImage(named: "header_backarrow")
let backItem = UIBarButtonItem(image: back, style: .plain, target: self, action: #selector(dismissManual))
navigationItem.leftBarButtonItem = backItem
#objc func dismissManual() {
dismiss(animated: true, completion: nil)
}
Note that the function must be marked with #objc.
Depending on your image and how you want it displayed, you may need to create the image as follows:
let back = UIImage(named: "header_backarrow").withRenderingMode(.alwaysOriginal)
Another option is to create a UIButton with the image and setup to call your dismissManual function. Create the UIBarButtonItem with the button as the custom view.
But it's easier to create a standard UIBarButtonItem when all you have is a simple image or a simple string.
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped))
// Adding button to navigation bar (rightBarButtonItem or leftBarButtonItem)
self.navigationItem.rightBarButtonItem = barButtonItem
// Private action
#objc fileprivate func menuButtonTapped() { // body method here }
Check out this, it may help Thanks.
I have viewController. Inside is I have UIView
lazy var cView : UIView = {
var view = UIView()
view.backgroundColor = .red
return view
}()
Inside this view I have UINavigationBar
lazy var navigationBar : UINavigationBar = {
let bar = UINavigationBar()
let leftButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.done, target: self, action: #selector(cancel))
bar.topItem?.setLeftBarButton(leftButton, animated: true)
let rightButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(done))
bar.topItem?.setRightBarButton(rightButton, animated: true)
bar.barTintColor = .green
bar.tintColor = UIColor.red
bar.barStyle = .default
bar.isTranslucent = false
return bar
}()
The problem is that in viewController I see only red view with green bar and without any buttons.
What am I doing wrong ? How to make buttons visible ?
bar.topItem UINavigationItem is nil when UINavigationBar is initialized. You can use bar.setItems(items: [UINavigationItem]?, animated: Bool) method to set bar.topItem
I am having trouble creating a UINavigationController toolbar programmatically. I have previously used storyboards to do this successfully but would like to try doing it all in code.
I have created the UIBarButtonItems programmatically, but the actual functions or actions they are supposed to perform when pressed are not working.
To clarify, I am NOT attempting to add UIBarButtonItems to the top bar. I've seen dozens of questions all asking the same thing. I am referring to the toolbar at the bottom that comes with the UINavigationController. This means no "rightBarButtonItem" or "leftBarButtonItem"
Here is the code:
class ProgOneViewController: UIViewController {
var chatRoomsButton: UIBarButtonItem = {
var button = UIBarButtonItem(title: "Chats", style: .plain, target: self, action: #selector(segueToChatRoomController(_:)))
return button
}()
var exploreButton: UIBarButtonItem = {
var button = UIBarButtonItem(title: "Explore", style: .plain, target: self, action: #selector(segueToExploreController(_:)))
return button
}()
var profileButton: UIBarButtonItem = {
var button = UIBarButtonItem(title: "Profile", style: .plain, target: self, action: #selector(segueToProfileController(_:)))
return button
}()
// Flexible spaces that are added in between each button.
var flexibleSpace1: UIBarButtonItem = {
var flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
return flexibleSpace
}()
var flexibleSpace2: UIBarButtonItem = {
var flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
return flexibleSpace
}()
var flexibleSpace3: UIBarButtonItem = {
var flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
return flexibleSpace
}()
var flexibleSpace4: UIBarButtonItem = {
var flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
return flexibleSpace
}()
// These are the functions that are not being called for some mysterious reason.
func segueToChatRoomController(_ sender: Any) {
print("segueing to chat rooms controller")
let chatRoomsController = ChatRoomsViewController()
let navController = UINavigationController(rootViewController: chatRoomsController)
self.present(navController, animated: false, completion: nil)
}
func segueToExploreController(_ sender: Any) {
print("segueing to explore controller")
let exploreController = ExploreCollectionViewController()
let navController = UINavigationController(rootViewController: exploreController)
self.present(navController, animated: false, completion: nil)
}
func segueToProfileController(_ sender: Any) {
print("segueing to profile controller")
let profileController = ProfileTableViewController()
let navController = UINavigationController(rootViewController: profileController)
self.present(navController, animated: false, completion: nil)
}
func setUpToolbar() {
print("setting up toolbar")
self.navigationController?.setToolbarHidden(false, animated: false)
self.navigationController?.toolbar.isUserInteractionEnabled = true
let toolBarItems = [flexibleSpace1, chatRoomsButton, flexibleSpace2, exploreButton, flexibleSpace3, profileButton, flexibleSpace4]
self.setToolbarItems(toolBarItems, animated: true)
// For some reason, these two methods leave the toolbar empty.
//self.navigationController?.setToolbarItems(toolBarItems, animated: true)
//self.navigationController?.toolbar.items = toolBarItems
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
setUpToolbar()
}
}
EDIT*
Here is the code used to instantiate the ProgOneViewController inside a UINavigationController
func pushToTestProgrammaticallyCreatedViews() {
let progOneViewController = ProgOneViewController()
let navController = UINavigationController(rootViewController: progOneViewController)
//navController.isToolbarHidden = false
//progOneViewController.setUpToolbar()
self.present(navController, animated: false, completion: nil)
}
I called this function upon clicking a button in my storyboard-created view controller. The function signature was long in order to specify which viewControllers were tests (created programmatically) :)
first of all you have to make sure that your ProgOneViewController is really included in a UINavigationController. if that is the case the toolbar as well as the barbuttonitems are shown (tried your code in my project).
except of that you have to change all of your barbuttonitem declarations to lazy var so that the references to self within the declarations point to the viewcontroller and target-action works.
feel free to ask if there are any questions :)
I have 3 nav bar items in my navigationBar like so:
func setupNavBarButtons() {
let searchImage = UIImage(named: "search_icon")?.imageWithRenderingMode(.AlwaysOriginal)
let searchBarButtonItem = UIBarButtonItem(image: searchImage, style: .Plain, target: self, action: #selector(handleSearch))
let mapBarButtonItem = UIBarButtonItem(title: "Map", style: .Plain, target: self, action: #selector(displayMap))
navigationItem.rightBarButtonItems = [mapBarButtonItem , searchBarButtonItem]
let filterBarButtonItem = UIBarButtonItem(title: "Filter", style: .Plain , target: self, action: #selector(displayFilter))
navigationItem.leftBarButtonItem = filterBarButtonItem
}
When I tap the search icon it calls the function below:
func handleSearch() {
self.navigationItem.titleView = searchController.searchBar
}
I want to hide all navigationBarItems while user is searching and then return nav bar items once user is done searching
You can try like this in your handleSearch method remove the left and right bar button item, After that on searchBarCancelButtonClicked method of UISearchBarDelegate you can set it again that bar items.
func handleSearch() {
searchController.searchBar.hidden = false
self.navigationItem.titleView = searchController.searchBar
searchController.searchBar.becomeFirstResponder()
navigationItem.rightBarButtonItems = nil
navigationItem.leftBarButtonItems = nil
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
self.setupNavBarButtons()
searchController.searchBar.hidden = true
}